1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <stdio.h> 30*7c478bd9Sstevel@tonic-gate #include <errno.h> 31*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 32*7c478bd9Sstevel@tonic-gate #include <string.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 34*7c478bd9Sstevel@tonic-gate #include <pwd.h> 35*7c478bd9Sstevel@tonic-gate #include <unistd.h> 36*7c478bd9Sstevel@tonic-gate #include <syslog.h> 37*7c478bd9Sstevel@tonic-gate 38*7c478bd9Sstevel@tonic-gate #include <netdb.h> 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 41*7c478bd9Sstevel@tonic-gate #include <rpcsvc/yppasswd.h> 42*7c478bd9Sstevel@tonic-gate #include <rpcsvc/ypclnt.h> 43*7c478bd9Sstevel@tonic-gate #include <rpcsvc/yp_prot.h> 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate #include "passwdutil.h" 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate int nis_getattr(char *name, attrlist *item, pwu_repository_t *rep); 48*7c478bd9Sstevel@tonic-gate int nis_getpwnam(char *name, attrlist *items, pwu_repository_t *rep, 49*7c478bd9Sstevel@tonic-gate void **buf); 50*7c478bd9Sstevel@tonic-gate int nis_update(attrlist *items, pwu_repository_t *rep, void *buf); 51*7c478bd9Sstevel@tonic-gate int nis_putpwnam(char *name, char *oldpw, char *dummy, 52*7c478bd9Sstevel@tonic-gate pwu_repository_t *rep, void *buf); 53*7c478bd9Sstevel@tonic-gate int nis_user_to_authenticate(char *user, pwu_repository_t *rep, 54*7c478bd9Sstevel@tonic-gate char **auth_user, int *privileged); 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate /* 57*7c478bd9Sstevel@tonic-gate * nis function pointer table, used by passwdutil_init to initialize 58*7c478bd9Sstevel@tonic-gate * the global Repository-OPerations table "rops" 59*7c478bd9Sstevel@tonic-gate */ 60*7c478bd9Sstevel@tonic-gate struct repops nis_repops = { 61*7c478bd9Sstevel@tonic-gate NULL, /* checkhistory */ 62*7c478bd9Sstevel@tonic-gate nis_getattr, 63*7c478bd9Sstevel@tonic-gate nis_getpwnam, 64*7c478bd9Sstevel@tonic-gate nis_update, 65*7c478bd9Sstevel@tonic-gate nis_putpwnam, 66*7c478bd9Sstevel@tonic-gate nis_user_to_authenticate, 67*7c478bd9Sstevel@tonic-gate NULL, /* lock */ 68*7c478bd9Sstevel@tonic-gate NULL /* unlock */ 69*7c478bd9Sstevel@tonic-gate }; 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate /* 72*7c478bd9Sstevel@tonic-gate * structure used to keep state between get/update/put calls 73*7c478bd9Sstevel@tonic-gate */ 74*7c478bd9Sstevel@tonic-gate typedef struct { 75*7c478bd9Sstevel@tonic-gate char *domain; 76*7c478bd9Sstevel@tonic-gate char *master; 77*7c478bd9Sstevel@tonic-gate char *scratch; 78*7c478bd9Sstevel@tonic-gate int scratchlen; 79*7c478bd9Sstevel@tonic-gate char *c2scratch; 80*7c478bd9Sstevel@tonic-gate int c2scratchlen; 81*7c478bd9Sstevel@tonic-gate struct passwd *pwd; 82*7c478bd9Sstevel@tonic-gate } nisbuf_t; 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate /* 85*7c478bd9Sstevel@tonic-gate * Are we a 'privileged' process? Yes if we are running on the 86*7c478bd9Sstevel@tonic-gate * NIS server AND we are root... 87*7c478bd9Sstevel@tonic-gate */ 88*7c478bd9Sstevel@tonic-gate int 89*7c478bd9Sstevel@tonic-gate nis_privileged(nisbuf_t *nisbuf) 90*7c478bd9Sstevel@tonic-gate { 91*7c478bd9Sstevel@tonic-gate char thishost[MAXHOSTNAMELEN]; 92*7c478bd9Sstevel@tonic-gate if (gethostname(thishost, sizeof (thishost)) == -1) { 93*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "passwdutil.so: Can't get hostname"); 94*7c478bd9Sstevel@tonic-gate return (0); 95*7c478bd9Sstevel@tonic-gate } 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate if (strcmp(nisbuf->master, thishost) != 0) 98*7c478bd9Sstevel@tonic-gate return (0); 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate /* We're running on the NIS server. */ 101*7c478bd9Sstevel@tonic-gate return (getuid() == 0); 102*7c478bd9Sstevel@tonic-gate } 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate /* 105*7c478bd9Sstevel@tonic-gate * nis_to_pwd() 106*7c478bd9Sstevel@tonic-gate * 107*7c478bd9Sstevel@tonic-gate * convert password-entry-line to "struct passwd" 108*7c478bd9Sstevel@tonic-gate */ 109*7c478bd9Sstevel@tonic-gate void 110*7c478bd9Sstevel@tonic-gate nis_to_pwd(char *nis, struct passwd *pwd) 111*7c478bd9Sstevel@tonic-gate { 112*7c478bd9Sstevel@tonic-gate pwd->pw_name = strsep(&nis, ":"); 113*7c478bd9Sstevel@tonic-gate pwd->pw_passwd = strsep(&nis, ":"); 114*7c478bd9Sstevel@tonic-gate pwd->pw_uid = atoi(strsep(&nis, ":")); 115*7c478bd9Sstevel@tonic-gate pwd->pw_gid = atoi(strsep(&nis, ":")); 116*7c478bd9Sstevel@tonic-gate pwd->pw_gecos = strsep(&nis, ":"); 117*7c478bd9Sstevel@tonic-gate pwd->pw_dir = strsep(&nis, ":"); 118*7c478bd9Sstevel@tonic-gate pwd->pw_shell = nis; 119*7c478bd9Sstevel@tonic-gate if (pwd->pw_shell[0]) 120*7c478bd9Sstevel@tonic-gate pwd->pw_shell[strlen(pwd->pw_shell)-1] = '\0'; 121*7c478bd9Sstevel@tonic-gate } 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate /* 124*7c478bd9Sstevel@tonic-gate * nis_user_to_authenticate(name, rep, auth_user, privileged) 125*7c478bd9Sstevel@tonic-gate * 126*7c478bd9Sstevel@tonic-gate */ 127*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 128*7c478bd9Sstevel@tonic-gate int 129*7c478bd9Sstevel@tonic-gate nis_user_to_authenticate(char *user, pwu_repository_t *rep, 130*7c478bd9Sstevel@tonic-gate char **auth_user, int *privileged) 131*7c478bd9Sstevel@tonic-gate { 132*7c478bd9Sstevel@tonic-gate nisbuf_t *buf = NULL; 133*7c478bd9Sstevel@tonic-gate int res; 134*7c478bd9Sstevel@tonic-gate attrlist attr_tmp[1]; 135*7c478bd9Sstevel@tonic-gate uid_t uid; 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate /* 138*7c478bd9Sstevel@tonic-gate * special NIS case: don't bother to get "root" from NIS 139*7c478bd9Sstevel@tonic-gate */ 140*7c478bd9Sstevel@tonic-gate if (strcmp(user, "root") == 0) 141*7c478bd9Sstevel@tonic-gate return (PWU_NOT_FOUND); 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate attr_tmp[0].type = ATTR_UID; 144*7c478bd9Sstevel@tonic-gate attr_tmp[0].next = NULL; 145*7c478bd9Sstevel@tonic-gate 146*7c478bd9Sstevel@tonic-gate res = nis_getpwnam(user, &attr_tmp[0], rep, (void **)&buf); 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate if (res != PWU_SUCCESS) 149*7c478bd9Sstevel@tonic-gate return (res); 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate if (nis_privileged(buf)) { 152*7c478bd9Sstevel@tonic-gate *privileged = 1; 153*7c478bd9Sstevel@tonic-gate *auth_user = NULL; 154*7c478bd9Sstevel@tonic-gate res = PWU_SUCCESS; 155*7c478bd9Sstevel@tonic-gate } else { 156*7c478bd9Sstevel@tonic-gate uid = getuid(); 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate *privileged = (uid == (uid_t)0); 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate /* root, or user herself can change attributes */ 161*7c478bd9Sstevel@tonic-gate if (uid == 0 || uid == buf->pwd->pw_uid) { 162*7c478bd9Sstevel@tonic-gate *auth_user = strdup(user); 163*7c478bd9Sstevel@tonic-gate res = PWU_SUCCESS; 164*7c478bd9Sstevel@tonic-gate } else { 165*7c478bd9Sstevel@tonic-gate res = PWU_DENIED; 166*7c478bd9Sstevel@tonic-gate } 167*7c478bd9Sstevel@tonic-gate } 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate /* 170*7c478bd9Sstevel@tonic-gate * Do not release buf->domain. 171*7c478bd9Sstevel@tonic-gate * It's been set by yp_get_default_domain() 172*7c478bd9Sstevel@tonic-gate * and must not be freed. 173*7c478bd9Sstevel@tonic-gate * See man page yp_get_default_domain(3NSL) 174*7c478bd9Sstevel@tonic-gate * for details. 175*7c478bd9Sstevel@tonic-gate */ 176*7c478bd9Sstevel@tonic-gate if (buf->master) 177*7c478bd9Sstevel@tonic-gate free(buf->master); 178*7c478bd9Sstevel@tonic-gate if (buf->scratch) 179*7c478bd9Sstevel@tonic-gate free(buf->scratch); 180*7c478bd9Sstevel@tonic-gate if (buf->c2scratch) 181*7c478bd9Sstevel@tonic-gate free(buf->c2scratch); 182*7c478bd9Sstevel@tonic-gate free(buf->pwd); 183*7c478bd9Sstevel@tonic-gate free(buf); 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate return (res); 186*7c478bd9Sstevel@tonic-gate } 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate /* 190*7c478bd9Sstevel@tonic-gate * nis_getattr(name, items, rep) 191*7c478bd9Sstevel@tonic-gate * 192*7c478bd9Sstevel@tonic-gate * get account attributes specified in 'items' 193*7c478bd9Sstevel@tonic-gate */ 194*7c478bd9Sstevel@tonic-gate int 195*7c478bd9Sstevel@tonic-gate nis_getattr(char *name, attrlist *items, pwu_repository_t *rep) 196*7c478bd9Sstevel@tonic-gate { 197*7c478bd9Sstevel@tonic-gate nisbuf_t *nisbuf = NULL; 198*7c478bd9Sstevel@tonic-gate struct passwd *pw; 199*7c478bd9Sstevel@tonic-gate attrlist *w; 200*7c478bd9Sstevel@tonic-gate int res; 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate res = nis_getpwnam(name, items, rep, (void **)&nisbuf); 203*7c478bd9Sstevel@tonic-gate if (res != PWU_SUCCESS) 204*7c478bd9Sstevel@tonic-gate return (res); 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate pw = nisbuf->pwd; 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate for (w = items; w != NULL; w = w->next) { 209*7c478bd9Sstevel@tonic-gate switch (w->type) { 210*7c478bd9Sstevel@tonic-gate case ATTR_NAME: 211*7c478bd9Sstevel@tonic-gate if ((w->data.val_s = strdup(pw->pw_name)) == NULL) 212*7c478bd9Sstevel@tonic-gate res = PWU_NOMEM; 213*7c478bd9Sstevel@tonic-gate break; 214*7c478bd9Sstevel@tonic-gate case ATTR_COMMENT: 215*7c478bd9Sstevel@tonic-gate if ((w->data.val_s = strdup(pw->pw_comment)) == NULL) 216*7c478bd9Sstevel@tonic-gate res = PWU_NOMEM; 217*7c478bd9Sstevel@tonic-gate break; 218*7c478bd9Sstevel@tonic-gate case ATTR_GECOS: 219*7c478bd9Sstevel@tonic-gate if ((w->data.val_s = strdup(pw->pw_gecos)) == NULL) 220*7c478bd9Sstevel@tonic-gate res = PWU_NOMEM; 221*7c478bd9Sstevel@tonic-gate break; 222*7c478bd9Sstevel@tonic-gate case ATTR_HOMEDIR: 223*7c478bd9Sstevel@tonic-gate if ((w->data.val_s = strdup(pw->pw_dir)) == NULL) 224*7c478bd9Sstevel@tonic-gate res = PWU_NOMEM; 225*7c478bd9Sstevel@tonic-gate break; 226*7c478bd9Sstevel@tonic-gate case ATTR_SHELL: 227*7c478bd9Sstevel@tonic-gate if ((w->data.val_s = strdup(pw->pw_shell)) == NULL) 228*7c478bd9Sstevel@tonic-gate res = PWU_NOMEM; 229*7c478bd9Sstevel@tonic-gate break; 230*7c478bd9Sstevel@tonic-gate case ATTR_PASSWD: 231*7c478bd9Sstevel@tonic-gate case ATTR_PASSWD_SERVER_POLICY: 232*7c478bd9Sstevel@tonic-gate if ((w->data.val_s = strdup(pw->pw_passwd)) == NULL) 233*7c478bd9Sstevel@tonic-gate res = PWU_NOMEM; 234*7c478bd9Sstevel@tonic-gate break; 235*7c478bd9Sstevel@tonic-gate case ATTR_REP_NAME: 236*7c478bd9Sstevel@tonic-gate if ((w->data.val_s = strdup("nis")) == NULL) 237*7c478bd9Sstevel@tonic-gate res = PWU_NOMEM; 238*7c478bd9Sstevel@tonic-gate break; 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate /* integer values */ 241*7c478bd9Sstevel@tonic-gate case ATTR_UID: 242*7c478bd9Sstevel@tonic-gate w->data.val_i = nisbuf->pwd->pw_uid; 243*7c478bd9Sstevel@tonic-gate break; 244*7c478bd9Sstevel@tonic-gate case ATTR_GID: 245*7c478bd9Sstevel@tonic-gate w->data.val_i = nisbuf->pwd->pw_gid; 246*7c478bd9Sstevel@tonic-gate break; 247*7c478bd9Sstevel@tonic-gate case ATTR_LSTCHG: 248*7c478bd9Sstevel@tonic-gate case ATTR_MIN: 249*7c478bd9Sstevel@tonic-gate case ATTR_MAX: 250*7c478bd9Sstevel@tonic-gate case ATTR_WARN: 251*7c478bd9Sstevel@tonic-gate case ATTR_INACT: 252*7c478bd9Sstevel@tonic-gate case ATTR_EXPIRE: 253*7c478bd9Sstevel@tonic-gate case ATTR_FLAG: 254*7c478bd9Sstevel@tonic-gate case ATTR_AGE: 255*7c478bd9Sstevel@tonic-gate w->data.val_i = -1; /* not used for NIS */ 256*7c478bd9Sstevel@tonic-gate break; 257*7c478bd9Sstevel@tonic-gate default: 258*7c478bd9Sstevel@tonic-gate break; 259*7c478bd9Sstevel@tonic-gate } 260*7c478bd9Sstevel@tonic-gate } 261*7c478bd9Sstevel@tonic-gate 262*7c478bd9Sstevel@tonic-gate /* 263*7c478bd9Sstevel@tonic-gate * Do not release nisbuf->domain. 264*7c478bd9Sstevel@tonic-gate * It's been set by yp_get_default_domain() 265*7c478bd9Sstevel@tonic-gate * and must not be freed. 266*7c478bd9Sstevel@tonic-gate * See man page yp_get_default_domain(3NSL) 267*7c478bd9Sstevel@tonic-gate * for details. 268*7c478bd9Sstevel@tonic-gate */ 269*7c478bd9Sstevel@tonic-gate if (nisbuf->master) 270*7c478bd9Sstevel@tonic-gate free(nisbuf->master); 271*7c478bd9Sstevel@tonic-gate if (nisbuf->scratch) 272*7c478bd9Sstevel@tonic-gate free(nisbuf->scratch); 273*7c478bd9Sstevel@tonic-gate if (nisbuf->c2scratch) 274*7c478bd9Sstevel@tonic-gate free(nisbuf->c2scratch); 275*7c478bd9Sstevel@tonic-gate free(nisbuf->pwd); 276*7c478bd9Sstevel@tonic-gate free(nisbuf); 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate return (res); 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate /* 282*7c478bd9Sstevel@tonic-gate * nis_getpwnam(name, items, rep) 283*7c478bd9Sstevel@tonic-gate * 284*7c478bd9Sstevel@tonic-gate * Get the account information of user 'name' 285*7c478bd9Sstevel@tonic-gate */ 286*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 287*7c478bd9Sstevel@tonic-gate int 288*7c478bd9Sstevel@tonic-gate nis_getpwnam(char *name, attrlist *items, pwu_repository_t *rep, 289*7c478bd9Sstevel@tonic-gate void **buf) 290*7c478bd9Sstevel@tonic-gate { 291*7c478bd9Sstevel@tonic-gate nisbuf_t *nisbuf; 292*7c478bd9Sstevel@tonic-gate int nisresult; 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate nisbuf = calloc(sizeof (*nisbuf), 1); 295*7c478bd9Sstevel@tonic-gate if (nisbuf == NULL) 296*7c478bd9Sstevel@tonic-gate return (PWU_NOMEM); 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate nisbuf->pwd = malloc(sizeof (struct passwd)); 299*7c478bd9Sstevel@tonic-gate if (nisbuf->pwd == NULL) { 300*7c478bd9Sstevel@tonic-gate free(nisbuf); 301*7c478bd9Sstevel@tonic-gate return (PWU_NOMEM); 302*7c478bd9Sstevel@tonic-gate } 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate /* 305*7c478bd9Sstevel@tonic-gate * Do not release nisbuf->domain. 306*7c478bd9Sstevel@tonic-gate * It is going to be set by yp_get_default_domain() 307*7c478bd9Sstevel@tonic-gate * and must not be freed. 308*7c478bd9Sstevel@tonic-gate * See man page yp_get_default_domain(3NSL) 309*7c478bd9Sstevel@tonic-gate * for details. 310*7c478bd9Sstevel@tonic-gate */ 311*7c478bd9Sstevel@tonic-gate if (yp_get_default_domain(&nisbuf->domain) != 0) { 312*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "passwdutil.so: can't get domain"); 313*7c478bd9Sstevel@tonic-gate free(nisbuf->pwd); 314*7c478bd9Sstevel@tonic-gate free(nisbuf); 315*7c478bd9Sstevel@tonic-gate return (PWU_SERVER_ERROR); 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate if (yp_master(nisbuf->domain, "passwd.byname", &nisbuf->master) != 0) { 319*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 320*7c478bd9Sstevel@tonic-gate "passwdutil.so: can't get master for passwd map"); 321*7c478bd9Sstevel@tonic-gate if (nisbuf->master) 322*7c478bd9Sstevel@tonic-gate free(nisbuf->master); 323*7c478bd9Sstevel@tonic-gate free(nisbuf->pwd); 324*7c478bd9Sstevel@tonic-gate free(nisbuf); 325*7c478bd9Sstevel@tonic-gate return (PWU_SERVER_ERROR); 326*7c478bd9Sstevel@tonic-gate } 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate nisresult = yp_match(nisbuf->domain, "passwd.byname", name, 329*7c478bd9Sstevel@tonic-gate strlen(name), &(nisbuf->scratch), 330*7c478bd9Sstevel@tonic-gate &(nisbuf->scratchlen)); 331*7c478bd9Sstevel@tonic-gate if (nisresult != 0) { 332*7c478bd9Sstevel@tonic-gate (void) free(nisbuf->pwd); 333*7c478bd9Sstevel@tonic-gate if (nisbuf->scratch) 334*7c478bd9Sstevel@tonic-gate (void) free(nisbuf->scratch); 335*7c478bd9Sstevel@tonic-gate if (nisbuf->master) 336*7c478bd9Sstevel@tonic-gate (void) free(nisbuf->master); 337*7c478bd9Sstevel@tonic-gate (void) free(nisbuf); 338*7c478bd9Sstevel@tonic-gate return (PWU_NOT_FOUND); 339*7c478bd9Sstevel@tonic-gate } 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate nis_to_pwd(nisbuf->scratch, nisbuf->pwd); 342*7c478bd9Sstevel@tonic-gate 343*7c478bd9Sstevel@tonic-gate /* 344*7c478bd9Sstevel@tonic-gate * check for the C2 security flag "##" in the passwd field. 345*7c478bd9Sstevel@tonic-gate * If the first 2 chars in the passwd field is "##", get 346*7c478bd9Sstevel@tonic-gate * the user's passwd from passwd.adjunct.byname map. 347*7c478bd9Sstevel@tonic-gate * The lookup to this passwd.adjunct.byname map will only 348*7c478bd9Sstevel@tonic-gate * succeed if the caller's uid is 0 because only root user 349*7c478bd9Sstevel@tonic-gate * can use privilege port. 350*7c478bd9Sstevel@tonic-gate */ 351*7c478bd9Sstevel@tonic-gate if (nisbuf->pwd->pw_passwd[0] == '#' && 352*7c478bd9Sstevel@tonic-gate nisbuf->pwd->pw_passwd[1] == '#') { 353*7c478bd9Sstevel@tonic-gate char *key = &nisbuf->pwd->pw_passwd[2]; 354*7c478bd9Sstevel@tonic-gate int keylen; 355*7c478bd9Sstevel@tonic-gate char *p; 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate keylen = strlen(key); 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate nisresult = yp_match(nisbuf->domain, "passwd.adjunct.byname", 360*7c478bd9Sstevel@tonic-gate key, keylen, &(nisbuf->c2scratch), 361*7c478bd9Sstevel@tonic-gate &(nisbuf->c2scratchlen)); 362*7c478bd9Sstevel@tonic-gate 363*7c478bd9Sstevel@tonic-gate if (nisresult == 0 && nisbuf->c2scratch != NULL) { 364*7c478bd9Sstevel@tonic-gate /* Skip username (first field), and pick up password */ 365*7c478bd9Sstevel@tonic-gate p = nisbuf->c2scratch; 366*7c478bd9Sstevel@tonic-gate (void) strsep(&p, ":"); 367*7c478bd9Sstevel@tonic-gate nisbuf->pwd->pw_passwd = strsep(&p, ":"); 368*7c478bd9Sstevel@tonic-gate } 369*7c478bd9Sstevel@tonic-gate } 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate *buf = (void *)nisbuf; 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate return (PWU_SUCCESS); 374*7c478bd9Sstevel@tonic-gate } 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate /* 377*7c478bd9Sstevel@tonic-gate * nis_update(items, rep, buf) 378*7c478bd9Sstevel@tonic-gate * 379*7c478bd9Sstevel@tonic-gate * update the information in "buf" with the attribute/values 380*7c478bd9Sstevel@tonic-gate * specified in "items". 381*7c478bd9Sstevel@tonic-gate */ 382*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 383*7c478bd9Sstevel@tonic-gate int 384*7c478bd9Sstevel@tonic-gate nis_update(attrlist *items, pwu_repository_t *rep, void *buf) 385*7c478bd9Sstevel@tonic-gate { 386*7c478bd9Sstevel@tonic-gate attrlist *p; 387*7c478bd9Sstevel@tonic-gate nisbuf_t *nisbuf = (nisbuf_t *)buf; 388*7c478bd9Sstevel@tonic-gate char *salt; 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate for (p = items; p != NULL; p = p->next) { 391*7c478bd9Sstevel@tonic-gate switch (p->type) { 392*7c478bd9Sstevel@tonic-gate case ATTR_NAME: 393*7c478bd9Sstevel@tonic-gate break; 394*7c478bd9Sstevel@tonic-gate /* 395*7c478bd9Sstevel@tonic-gate * Nothing special needs to be done for 396*7c478bd9Sstevel@tonic-gate * server policy 397*7c478bd9Sstevel@tonic-gate */ 398*7c478bd9Sstevel@tonic-gate case ATTR_PASSWD: 399*7c478bd9Sstevel@tonic-gate case ATTR_PASSWD_SERVER_POLICY: 400*7c478bd9Sstevel@tonic-gate salt = crypt_gensalt( 401*7c478bd9Sstevel@tonic-gate nisbuf->pwd->pw_passwd, nisbuf->pwd); 402*7c478bd9Sstevel@tonic-gate 403*7c478bd9Sstevel@tonic-gate if (salt == NULL) { 404*7c478bd9Sstevel@tonic-gate if (errno == ENOMEM) 405*7c478bd9Sstevel@tonic-gate return (PWU_NOMEM); 406*7c478bd9Sstevel@tonic-gate else { 407*7c478bd9Sstevel@tonic-gate /* algorithm problem? */ 408*7c478bd9Sstevel@tonic-gate syslog(LOG_AUTH | LOG_ALERT, 409*7c478bd9Sstevel@tonic-gate "passwdutil: crypt_gensalt " 410*7c478bd9Sstevel@tonic-gate "%m"); 411*7c478bd9Sstevel@tonic-gate return (PWU_UPDATE_FAILED); 412*7c478bd9Sstevel@tonic-gate } 413*7c478bd9Sstevel@tonic-gate } 414*7c478bd9Sstevel@tonic-gate nisbuf->pwd->pw_passwd = crypt(p->data.val_s, salt); 415*7c478bd9Sstevel@tonic-gate free(salt); 416*7c478bd9Sstevel@tonic-gate break; 417*7c478bd9Sstevel@tonic-gate case ATTR_UID: 418*7c478bd9Sstevel@tonic-gate nisbuf->pwd->pw_uid = (uid_t)p->data.val_i; 419*7c478bd9Sstevel@tonic-gate break; 420*7c478bd9Sstevel@tonic-gate case ATTR_GID: 421*7c478bd9Sstevel@tonic-gate nisbuf->pwd->pw_gid = (gid_t)p->data.val_i; 422*7c478bd9Sstevel@tonic-gate break; 423*7c478bd9Sstevel@tonic-gate case ATTR_AGE: 424*7c478bd9Sstevel@tonic-gate nisbuf->pwd->pw_age = p->data.val_s; 425*7c478bd9Sstevel@tonic-gate break; 426*7c478bd9Sstevel@tonic-gate case ATTR_COMMENT: 427*7c478bd9Sstevel@tonic-gate nisbuf->pwd->pw_comment = p->data.val_s; 428*7c478bd9Sstevel@tonic-gate break; 429*7c478bd9Sstevel@tonic-gate case ATTR_GECOS: 430*7c478bd9Sstevel@tonic-gate nisbuf->pwd->pw_gecos = p->data.val_s; 431*7c478bd9Sstevel@tonic-gate break; 432*7c478bd9Sstevel@tonic-gate case ATTR_HOMEDIR: 433*7c478bd9Sstevel@tonic-gate nisbuf->pwd->pw_dir = p->data.val_s; 434*7c478bd9Sstevel@tonic-gate break; 435*7c478bd9Sstevel@tonic-gate case ATTR_SHELL: 436*7c478bd9Sstevel@tonic-gate nisbuf->pwd->pw_shell = p->data.val_s; 437*7c478bd9Sstevel@tonic-gate break; 438*7c478bd9Sstevel@tonic-gate case ATTR_LSTCHG: 439*7c478bd9Sstevel@tonic-gate case ATTR_MIN: 440*7c478bd9Sstevel@tonic-gate case ATTR_MAX: 441*7c478bd9Sstevel@tonic-gate case ATTR_WARN: 442*7c478bd9Sstevel@tonic-gate case ATTR_INACT: 443*7c478bd9Sstevel@tonic-gate case ATTR_EXPIRE: 444*7c478bd9Sstevel@tonic-gate case ATTR_FLAG: 445*7c478bd9Sstevel@tonic-gate default: 446*7c478bd9Sstevel@tonic-gate break; 447*7c478bd9Sstevel@tonic-gate } 448*7c478bd9Sstevel@tonic-gate } 449*7c478bd9Sstevel@tonic-gate return (PWU_SUCCESS); 450*7c478bd9Sstevel@tonic-gate } 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate /* 453*7c478bd9Sstevel@tonic-gate * nis_putpwnam(name, oldpw, dummy, rep, buf) 454*7c478bd9Sstevel@tonic-gate * 455*7c478bd9Sstevel@tonic-gate * Update the NIS server. The passwd structure in buf will be sent to 456*7c478bd9Sstevel@tonic-gate * the server for user "name" authenticating with password "oldpw". 457*7c478bd9Sstevel@tonic-gate * The dummy parameter is a placeholder where for NIS+ where the 458*7c478bd9Sstevel@tonic-gate * old RPC password is passwd. 459*7c478bd9Sstevel@tonic-gate */ 460*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 461*7c478bd9Sstevel@tonic-gate int 462*7c478bd9Sstevel@tonic-gate nis_putpwnam(char *name, char *oldpw, char *dummy, pwu_repository_t *rep, 463*7c478bd9Sstevel@tonic-gate void *buf) 464*7c478bd9Sstevel@tonic-gate { 465*7c478bd9Sstevel@tonic-gate nisbuf_t *nisbuf = (nisbuf_t *)buf; 466*7c478bd9Sstevel@tonic-gate struct yppasswd yppasswd; 467*7c478bd9Sstevel@tonic-gate struct netconfig *nconf; 468*7c478bd9Sstevel@tonic-gate int ok; 469*7c478bd9Sstevel@tonic-gate enum clnt_stat ans; 470*7c478bd9Sstevel@tonic-gate CLIENT *client; 471*7c478bd9Sstevel@tonic-gate struct timeval timeout; 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate if (strcmp(name, "root") == 0) 474*7c478bd9Sstevel@tonic-gate return (PWU_NOT_FOUND); 475*7c478bd9Sstevel@tonic-gate 476*7c478bd9Sstevel@tonic-gate yppasswd.oldpass = oldpw ? oldpw : ""; 477*7c478bd9Sstevel@tonic-gate yppasswd.newpw = *nisbuf->pwd; 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate /* 480*7c478bd9Sstevel@tonic-gate * If we are privileged, we create a ticlts connection to the 481*7c478bd9Sstevel@tonic-gate * NIS server so that it can check our credentials 482*7c478bd9Sstevel@tonic-gate */ 483*7c478bd9Sstevel@tonic-gate if (nis_privileged(nisbuf)) { 484*7c478bd9Sstevel@tonic-gate nconf = getnetconfigent("ticlts"); 485*7c478bd9Sstevel@tonic-gate if (!nconf) { 486*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 487*7c478bd9Sstevel@tonic-gate "passwdutil.so: Couldn't get netconfig entry"); 488*7c478bd9Sstevel@tonic-gate return (PWU_SYSTEM_ERROR); 489*7c478bd9Sstevel@tonic-gate } 490*7c478bd9Sstevel@tonic-gate client = clnt_tp_create(nisbuf->master, YPPASSWDPROG, 491*7c478bd9Sstevel@tonic-gate YPPASSWDVERS, nconf); 492*7c478bd9Sstevel@tonic-gate freenetconfigent(nconf); 493*7c478bd9Sstevel@tonic-gate } else { 494*7c478bd9Sstevel@tonic-gate /* Try IPv6 first */ 495*7c478bd9Sstevel@tonic-gate client = clnt_create(nisbuf->master, YPPASSWDPROG, 496*7c478bd9Sstevel@tonic-gate YPPASSWDVERS, "udp6"); 497*7c478bd9Sstevel@tonic-gate if (client == NULL) 498*7c478bd9Sstevel@tonic-gate client = clnt_create(nisbuf->master, YPPASSWDPROG, 499*7c478bd9Sstevel@tonic-gate YPPASSWDVERS, "udp"); 500*7c478bd9Sstevel@tonic-gate } 501*7c478bd9Sstevel@tonic-gate 502*7c478bd9Sstevel@tonic-gate if (client == NULL) { 503*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 504*7c478bd9Sstevel@tonic-gate "passwdutil.so: couldn't create client to YP master"); 505*7c478bd9Sstevel@tonic-gate return (PWU_SERVER_ERROR); 506*7c478bd9Sstevel@tonic-gate } 507*7c478bd9Sstevel@tonic-gate 508*7c478bd9Sstevel@tonic-gate timeout.tv_usec = 0; 509*7c478bd9Sstevel@tonic-gate timeout.tv_sec = 55; /* ndp uses 55 seconds */ 510*7c478bd9Sstevel@tonic-gate 511*7c478bd9Sstevel@tonic-gate ans = CLNT_CALL(client, YPPASSWDPROC_UPDATE, xdr_yppasswd, 512*7c478bd9Sstevel@tonic-gate (char *)&yppasswd, xdr_int, (char *)&ok, timeout); 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate if (nisbuf->pwd) 515*7c478bd9Sstevel@tonic-gate (void) free(nisbuf->pwd); 516*7c478bd9Sstevel@tonic-gate if (nisbuf->master) 517*7c478bd9Sstevel@tonic-gate (void) free(nisbuf->master); 518*7c478bd9Sstevel@tonic-gate if (nisbuf->scratch) 519*7c478bd9Sstevel@tonic-gate (void) free(nisbuf->scratch); 520*7c478bd9Sstevel@tonic-gate if (nisbuf->c2scratch) 521*7c478bd9Sstevel@tonic-gate (void) free(nisbuf->c2scratch); 522*7c478bd9Sstevel@tonic-gate 523*7c478bd9Sstevel@tonic-gate (void) clnt_destroy(client); 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate if (ans != RPC_SUCCESS) { 526*7c478bd9Sstevel@tonic-gate return (PWU_UPDATE_FAILED); 527*7c478bd9Sstevel@tonic-gate } 528*7c478bd9Sstevel@tonic-gate 529*7c478bd9Sstevel@tonic-gate /* These errors are obtained from the yppasswdd.c code */ 530*7c478bd9Sstevel@tonic-gate switch (ok) { 531*7c478bd9Sstevel@tonic-gate case 2: return (PWU_DENIED); 532*7c478bd9Sstevel@tonic-gate case 8: return (PWU_BUSY); 533*7c478bd9Sstevel@tonic-gate case 9: return (PWU_SERVER_ERROR); 534*7c478bd9Sstevel@tonic-gate case 4: return (PWU_NOT_FOUND); 535*7c478bd9Sstevel@tonic-gate case 3: return (PWU_NO_CHANGE); 536*7c478bd9Sstevel@tonic-gate case 7: return (PWU_DENIED); 537*7c478bd9Sstevel@tonic-gate case 0: return (PWU_SUCCESS); 538*7c478bd9Sstevel@tonic-gate default: return (PWU_SYSTEM_ERROR); 539*7c478bd9Sstevel@tonic-gate } 540*7c478bd9Sstevel@tonic-gate } 541