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 2004 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 <unistd.h> 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate #include "ns_sldap.h" 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h> 38*7c478bd9Sstevel@tonic-gate #include <nsswitch.h> 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate #include <pwd.h> 41*7c478bd9Sstevel@tonic-gate #include <shadow.h> 42*7c478bd9Sstevel@tonic-gate #include <syslog.h> 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate #include "passwdutil.h" 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate #include "utils.h" 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate int ldap_getattr(char *name, attrlist *item, pwu_repository_t *rep); 49*7c478bd9Sstevel@tonic-gate int ldap_getpwnam(char *name, attrlist *items, pwu_repository_t *rep, 50*7c478bd9Sstevel@tonic-gate void **buf); 51*7c478bd9Sstevel@tonic-gate int ldap_update(attrlist *items, pwu_repository_t *rep, void *buf); 52*7c478bd9Sstevel@tonic-gate int ldap_putpwnam(char *name, char *oldpw, char *dummy, 53*7c478bd9Sstevel@tonic-gate pwu_repository_t *rep, void *buf); 54*7c478bd9Sstevel@tonic-gate int ldap_user_to_authenticate(char *name, pwu_repository_t *rep, 55*7c478bd9Sstevel@tonic-gate char **auth_user, int *privileged); 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate /* 58*7c478bd9Sstevel@tonic-gate * ldap function pointer table, used by passwdutil_init to initialize 59*7c478bd9Sstevel@tonic-gate * the global Repository-OPerations table "rops" 60*7c478bd9Sstevel@tonic-gate */ 61*7c478bd9Sstevel@tonic-gate struct repops ldap_repops = { 62*7c478bd9Sstevel@tonic-gate NULL, /* checkhistory */ 63*7c478bd9Sstevel@tonic-gate ldap_getattr, 64*7c478bd9Sstevel@tonic-gate ldap_getpwnam, 65*7c478bd9Sstevel@tonic-gate ldap_update, 66*7c478bd9Sstevel@tonic-gate ldap_putpwnam, 67*7c478bd9Sstevel@tonic-gate ldap_user_to_authenticate, 68*7c478bd9Sstevel@tonic-gate NULL, /* lock */ 69*7c478bd9Sstevel@tonic-gate NULL /* unlock */ 70*7c478bd9Sstevel@tonic-gate }; 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate /* 73*7c478bd9Sstevel@tonic-gate * structure used to keep state between get/update/put calls 74*7c478bd9Sstevel@tonic-gate */ 75*7c478bd9Sstevel@tonic-gate typedef struct { 76*7c478bd9Sstevel@tonic-gate char *passwd; /* encrypted password */ 77*7c478bd9Sstevel@tonic-gate struct passwd *pwd; 78*7c478bd9Sstevel@tonic-gate ns_ldap_attr_t **attrs; 79*7c478bd9Sstevel@tonic-gate } ldapbuf_t; 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate /* 82*7c478bd9Sstevel@tonic-gate * The following define's are taken from 83*7c478bd9Sstevel@tonic-gate * usr/src/lib/nsswitch/ldap/common/getpwnam.c 84*7c478bd9Sstevel@tonic-gate */ 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate /* passwd attributes filters */ 87*7c478bd9Sstevel@tonic-gate #define _PWD_CN "cn" 88*7c478bd9Sstevel@tonic-gate #define _PWD_UID "uid" 89*7c478bd9Sstevel@tonic-gate #define _PWD_USERPASSWORD "userpassword" 90*7c478bd9Sstevel@tonic-gate #define _PWD_UIDNUMBER "uidnumber" 91*7c478bd9Sstevel@tonic-gate #define _PWD_GIDNUMBER "gidnumber" 92*7c478bd9Sstevel@tonic-gate #define _PWD_GECOS "gecos" 93*7c478bd9Sstevel@tonic-gate #define _PWD_DESCRIPTION "description" 94*7c478bd9Sstevel@tonic-gate #define _PWD_HOMEDIRECTORY "homedirectory" 95*7c478bd9Sstevel@tonic-gate #define _PWD_LOGINSHELL "loginshell" 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate /* 98*7c478bd9Sstevel@tonic-gate * int ldap_user_to_authenticate(user, rep, auth_user, privileged) 99*7c478bd9Sstevel@tonic-gate * 100*7c478bd9Sstevel@tonic-gate * We can't determine whether the user is "privileged" in the LDAP 101*7c478bd9Sstevel@tonic-gate * sense. The operation should be attempted and will succeed if 102*7c478bd9Sstevel@tonic-gate * the user had privileges. 103*7c478bd9Sstevel@tonic-gate * 104*7c478bd9Sstevel@tonic-gate * For our purposes, we say that the user is privileged if he/she 105*7c478bd9Sstevel@tonic-gate * is attempting to change another user's password attributes. 106*7c478bd9Sstevel@tonic-gate */ 107*7c478bd9Sstevel@tonic-gate int 108*7c478bd9Sstevel@tonic-gate ldap_user_to_authenticate(char *user, pwu_repository_t *rep, 109*7c478bd9Sstevel@tonic-gate char **auth_user, int *privileged) 110*7c478bd9Sstevel@tonic-gate { 111*7c478bd9Sstevel@tonic-gate struct passwd *pw; 112*7c478bd9Sstevel@tonic-gate uid_t uid; 113*7c478bd9Sstevel@tonic-gate uid_t priviledged_uid; 114*7c478bd9Sstevel@tonic-gate int res = PWU_SUCCESS; 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate if (strcmp(user, "root") == 0) 117*7c478bd9Sstevel@tonic-gate return (PWU_NOT_FOUND); 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate if ((pw = getpwnam_from(user, rep, REP_LDAP)) == NULL) 120*7c478bd9Sstevel@tonic-gate return (PWU_NOT_FOUND); 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate uid = getuid(); 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate if (uid == pw->pw_uid) { 125*7c478bd9Sstevel@tonic-gate /* changing out own, not privileged */ 126*7c478bd9Sstevel@tonic-gate *privileged = 0; 127*7c478bd9Sstevel@tonic-gate if ((*auth_user = strdup(user)) == NULL) 128*7c478bd9Sstevel@tonic-gate res = PWU_NOMEM; 129*7c478bd9Sstevel@tonic-gate } else { 130*7c478bd9Sstevel@tonic-gate char pwd_buf[1024]; 131*7c478bd9Sstevel@tonic-gate struct passwd pwr; 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate *privileged = 1; 134*7c478bd9Sstevel@tonic-gate /* 135*7c478bd9Sstevel@tonic-gate * specific case for root 136*7c478bd9Sstevel@tonic-gate * we want 'user' to be authenticated. 137*7c478bd9Sstevel@tonic-gate */ 138*7c478bd9Sstevel@tonic-gate if (uid == 0) { 139*7c478bd9Sstevel@tonic-gate priviledged_uid = pw->pw_uid; 140*7c478bd9Sstevel@tonic-gate } else { 141*7c478bd9Sstevel@tonic-gate priviledged_uid = uid; 142*7c478bd9Sstevel@tonic-gate } 143*7c478bd9Sstevel@tonic-gate if (getpwuid_r(priviledged_uid, &pwr, pwd_buf, 144*7c478bd9Sstevel@tonic-gate sizeof (pwd_buf)) != NULL) { 145*7c478bd9Sstevel@tonic-gate if ((*auth_user = strdup(pwr.pw_name)) == NULL) 146*7c478bd9Sstevel@tonic-gate res = PWU_NOMEM; 147*7c478bd9Sstevel@tonic-gate } else { 148*7c478bd9Sstevel@tonic-gate /* hmm. can't find name of current user...??? */ 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate #define MAX_UID_LEN 11 /* UID's larger than 2^32 won't fit... */ 151*7c478bd9Sstevel@tonic-gate if ((*auth_user = malloc(MAX_UID_LEN)) == NULL) { 152*7c478bd9Sstevel@tonic-gate res = PWU_NOMEM; 153*7c478bd9Sstevel@tonic-gate } else { 154*7c478bd9Sstevel@tonic-gate (void) snprintf(*auth_user, MAX_UID_LEN, "%d", 155*7c478bd9Sstevel@tonic-gate (int)uid); 156*7c478bd9Sstevel@tonic-gate } 157*7c478bd9Sstevel@tonic-gate } 158*7c478bd9Sstevel@tonic-gate } 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate return (res); 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate /* 164*7c478bd9Sstevel@tonic-gate * int ldap_getattr(name, item, rep) 165*7c478bd9Sstevel@tonic-gate * 166*7c478bd9Sstevel@tonic-gate * retrieve attributes specified in "item" for user "name". 167*7c478bd9Sstevel@tonic-gate */ 168*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 169*7c478bd9Sstevel@tonic-gate int 170*7c478bd9Sstevel@tonic-gate ldap_getattr(char *name, attrlist *items, pwu_repository_t *rep) 171*7c478bd9Sstevel@tonic-gate { 172*7c478bd9Sstevel@tonic-gate int res; 173*7c478bd9Sstevel@tonic-gate struct passwd *pw = NULL; 174*7c478bd9Sstevel@tonic-gate struct spwd *spw = NULL; 175*7c478bd9Sstevel@tonic-gate attrlist *w; 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate int need_shadow = 0; /* Need shadow info from LDAP server */ 178*7c478bd9Sstevel@tonic-gate int need_normal = 0; /* Need non-shadow info from LDAP server */ 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate /* We need the "shadow" map for the password only */ 181*7c478bd9Sstevel@tonic-gate for (w = items; w != NULL; w = w->next) { 182*7c478bd9Sstevel@tonic-gate if (w->type == ATTR_PASSWD || 183*7c478bd9Sstevel@tonic-gate w->type == ATTR_PASSWD_SERVER_POLICY) 184*7c478bd9Sstevel@tonic-gate need_shadow = 1; 185*7c478bd9Sstevel@tonic-gate else 186*7c478bd9Sstevel@tonic-gate need_normal = 1; 187*7c478bd9Sstevel@tonic-gate } 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate if (need_normal) { 190*7c478bd9Sstevel@tonic-gate res = dup_pw(&pw, getpwnam_from(name, rep, REP_LDAP)); 191*7c478bd9Sstevel@tonic-gate if (res != PWU_SUCCESS) 192*7c478bd9Sstevel@tonic-gate goto out; 193*7c478bd9Sstevel@tonic-gate } 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate if (need_shadow) { 196*7c478bd9Sstevel@tonic-gate res = dup_spw(&spw, getspnam_from(name, rep, REP_LDAP)); 197*7c478bd9Sstevel@tonic-gate if (res != PWU_SUCCESS) { 198*7c478bd9Sstevel@tonic-gate goto out; 199*7c478bd9Sstevel@tonic-gate } 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate for (w = items; res == PWU_SUCCESS && w != NULL; w = w->next) { 203*7c478bd9Sstevel@tonic-gate switch (w->type) { 204*7c478bd9Sstevel@tonic-gate case ATTR_NAME: 205*7c478bd9Sstevel@tonic-gate if ((w->data.val_s = strdup(pw->pw_name)) == NULL) 206*7c478bd9Sstevel@tonic-gate res = PWU_NOMEM; 207*7c478bd9Sstevel@tonic-gate break; 208*7c478bd9Sstevel@tonic-gate case ATTR_COMMENT: 209*7c478bd9Sstevel@tonic-gate if ((w->data.val_s = strdup(pw->pw_comment)) == NULL) 210*7c478bd9Sstevel@tonic-gate res = PWU_NOMEM; 211*7c478bd9Sstevel@tonic-gate break; 212*7c478bd9Sstevel@tonic-gate case ATTR_GECOS: 213*7c478bd9Sstevel@tonic-gate if ((w->data.val_s = strdup(pw->pw_gecos)) == NULL) 214*7c478bd9Sstevel@tonic-gate res = PWU_NOMEM; 215*7c478bd9Sstevel@tonic-gate break; 216*7c478bd9Sstevel@tonic-gate case ATTR_HOMEDIR: 217*7c478bd9Sstevel@tonic-gate if ((w->data.val_s = strdup(pw->pw_dir)) == NULL) 218*7c478bd9Sstevel@tonic-gate res = PWU_NOMEM; 219*7c478bd9Sstevel@tonic-gate break; 220*7c478bd9Sstevel@tonic-gate case ATTR_SHELL: 221*7c478bd9Sstevel@tonic-gate if ((w->data.val_s = strdup(pw->pw_shell)) == NULL) 222*7c478bd9Sstevel@tonic-gate res = PWU_NOMEM; 223*7c478bd9Sstevel@tonic-gate break; 224*7c478bd9Sstevel@tonic-gate case ATTR_PASSWD: 225*7c478bd9Sstevel@tonic-gate case ATTR_PASSWD_SERVER_POLICY: 226*7c478bd9Sstevel@tonic-gate if ((w->data.val_s = strdup(spw->sp_pwdp)) == NULL) 227*7c478bd9Sstevel@tonic-gate res = PWU_NOMEM; 228*7c478bd9Sstevel@tonic-gate break; 229*7c478bd9Sstevel@tonic-gate case ATTR_AGE: 230*7c478bd9Sstevel@tonic-gate if ((w->data.val_s = strdup(pw->pw_age)) == NULL) 231*7c478bd9Sstevel@tonic-gate res = PWU_NOMEM; 232*7c478bd9Sstevel@tonic-gate break; 233*7c478bd9Sstevel@tonic-gate case ATTR_REP_NAME: 234*7c478bd9Sstevel@tonic-gate if ((w->data.val_s = strdup("ldap")) == NULL) 235*7c478bd9Sstevel@tonic-gate res = PWU_NOMEM; 236*7c478bd9Sstevel@tonic-gate break; 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate /* integer values */ 239*7c478bd9Sstevel@tonic-gate case ATTR_UID: 240*7c478bd9Sstevel@tonic-gate w->data.val_i = pw->pw_uid; 241*7c478bd9Sstevel@tonic-gate break; 242*7c478bd9Sstevel@tonic-gate case ATTR_GID: 243*7c478bd9Sstevel@tonic-gate w->data.val_i = pw->pw_gid; 244*7c478bd9Sstevel@tonic-gate break; 245*7c478bd9Sstevel@tonic-gate case ATTR_LSTCHG: 246*7c478bd9Sstevel@tonic-gate w->data.val_i = -1; 247*7c478bd9Sstevel@tonic-gate break; 248*7c478bd9Sstevel@tonic-gate case ATTR_MIN: 249*7c478bd9Sstevel@tonic-gate w->data.val_i = -1; 250*7c478bd9Sstevel@tonic-gate break; 251*7c478bd9Sstevel@tonic-gate case ATTR_MAX: 252*7c478bd9Sstevel@tonic-gate w->data.val_i = -1; 253*7c478bd9Sstevel@tonic-gate break; 254*7c478bd9Sstevel@tonic-gate case ATTR_WARN: 255*7c478bd9Sstevel@tonic-gate w->data.val_i = -1; 256*7c478bd9Sstevel@tonic-gate break; 257*7c478bd9Sstevel@tonic-gate case ATTR_INACT: 258*7c478bd9Sstevel@tonic-gate w->data.val_i = -1; 259*7c478bd9Sstevel@tonic-gate break; 260*7c478bd9Sstevel@tonic-gate case ATTR_EXPIRE: 261*7c478bd9Sstevel@tonic-gate w->data.val_i = -1; 262*7c478bd9Sstevel@tonic-gate break; 263*7c478bd9Sstevel@tonic-gate case ATTR_FLAG: 264*7c478bd9Sstevel@tonic-gate break; 265*7c478bd9Sstevel@tonic-gate default: 266*7c478bd9Sstevel@tonic-gate break; 267*7c478bd9Sstevel@tonic-gate } 268*7c478bd9Sstevel@tonic-gate } 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate out: 271*7c478bd9Sstevel@tonic-gate if (pw) 272*7c478bd9Sstevel@tonic-gate free_pwd(pw); 273*7c478bd9Sstevel@tonic-gate if (spw) 274*7c478bd9Sstevel@tonic-gate free_spwd(spw); 275*7c478bd9Sstevel@tonic-gate 276*7c478bd9Sstevel@tonic-gate return (res); 277*7c478bd9Sstevel@tonic-gate } 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate /* 280*7c478bd9Sstevel@tonic-gate * int ldap_getpwnam(name, items, rep, buf) 281*7c478bd9Sstevel@tonic-gate * 282*7c478bd9Sstevel@tonic-gate * There is no need to get the old values from the ldap 283*7c478bd9Sstevel@tonic-gate * server, as the update will update each item individually. 284*7c478bd9Sstevel@tonic-gate * Therefore, we only allocate a buffer that will be used by 285*7c478bd9Sstevel@tonic-gate * _update and _putpwnam to hold the attributes to update. 286*7c478bd9Sstevel@tonic-gate * 287*7c478bd9Sstevel@tonic-gate * Only when we're about to update a password, we need to retrieve 288*7c478bd9Sstevel@tonic-gate * the old password since it contains salt-information. 289*7c478bd9Sstevel@tonic-gate */ 290*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 291*7c478bd9Sstevel@tonic-gate int 292*7c478bd9Sstevel@tonic-gate ldap_getpwnam(char *name, attrlist *items, pwu_repository_t *rep, 293*7c478bd9Sstevel@tonic-gate void **buf) 294*7c478bd9Sstevel@tonic-gate { 295*7c478bd9Sstevel@tonic-gate attrlist *p; 296*7c478bd9Sstevel@tonic-gate int nr_items; 297*7c478bd9Sstevel@tonic-gate int need_pwd = 0; 298*7c478bd9Sstevel@tonic-gate ldapbuf_t *ldapbuf; 299*7c478bd9Sstevel@tonic-gate int res; 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate for (nr_items = 0, p = items; p != NULL; p = p->next) { 302*7c478bd9Sstevel@tonic-gate nr_items++; 303*7c478bd9Sstevel@tonic-gate if (p->type == ATTR_PASSWD || 304*7c478bd9Sstevel@tonic-gate p->type == ATTR_PASSWD_SERVER_POLICY) 305*7c478bd9Sstevel@tonic-gate need_pwd = 1; 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate ldapbuf = calloc(1, sizeof (ldapbuf_t)); 310*7c478bd9Sstevel@tonic-gate if (ldapbuf == NULL) 311*7c478bd9Sstevel@tonic-gate return (PWU_NOMEM); 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate ldapbuf->attrs = calloc(nr_items, sizeof (ns_ldap_attr_t *)); 314*7c478bd9Sstevel@tonic-gate if (ldapbuf->attrs == NULL) 315*7c478bd9Sstevel@tonic-gate return (PWU_NOMEM); 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate if (need_pwd) { 318*7c478bd9Sstevel@tonic-gate struct spwd *spw; 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate res = dup_pw(&ldapbuf->pwd, getpwnam_from(name, rep, REP_LDAP)); 321*7c478bd9Sstevel@tonic-gate if (res != PWU_SUCCESS) 322*7c478bd9Sstevel@tonic-gate return (res); 323*7c478bd9Sstevel@tonic-gate 324*7c478bd9Sstevel@tonic-gate spw = getspnam_from(name, rep, REP_LDAP); 325*7c478bd9Sstevel@tonic-gate if (spw) { 326*7c478bd9Sstevel@tonic-gate ldapbuf->passwd = strdup(spw->sp_pwdp); 327*7c478bd9Sstevel@tonic-gate if (ldapbuf->passwd == NULL) 328*7c478bd9Sstevel@tonic-gate return (PWU_NOMEM); 329*7c478bd9Sstevel@tonic-gate } 330*7c478bd9Sstevel@tonic-gate } 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate *buf = ldapbuf; 333*7c478bd9Sstevel@tonic-gate return (0); 334*7c478bd9Sstevel@tonic-gate } 335*7c478bd9Sstevel@tonic-gate 336*7c478bd9Sstevel@tonic-gate /* 337*7c478bd9Sstevel@tonic-gate * new_attr(name, value) 338*7c478bd9Sstevel@tonic-gate * 339*7c478bd9Sstevel@tonic-gate * create a new LDAP attribute to be sent to the server 340*7c478bd9Sstevel@tonic-gate */ 341*7c478bd9Sstevel@tonic-gate ns_ldap_attr_t * 342*7c478bd9Sstevel@tonic-gate new_attr(char *name, char *value) 343*7c478bd9Sstevel@tonic-gate { 344*7c478bd9Sstevel@tonic-gate ns_ldap_attr_t *tmp; 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate tmp = malloc(sizeof (*tmp)); 347*7c478bd9Sstevel@tonic-gate if (tmp != NULL) { 348*7c478bd9Sstevel@tonic-gate tmp->attrname = name; 349*7c478bd9Sstevel@tonic-gate tmp->attrvalue = (char **)calloc(2, sizeof (char *)); 350*7c478bd9Sstevel@tonic-gate if (tmp->attrvalue == NULL) { 351*7c478bd9Sstevel@tonic-gate free(tmp); 352*7c478bd9Sstevel@tonic-gate return (NULL); 353*7c478bd9Sstevel@tonic-gate } 354*7c478bd9Sstevel@tonic-gate tmp->attrvalue[0] = value; 355*7c478bd9Sstevel@tonic-gate tmp->value_count = 1; 356*7c478bd9Sstevel@tonic-gate } 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate return (tmp); 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate /* 362*7c478bd9Sstevel@tonic-gate * ldap_update(items, rep, buf) 363*7c478bd9Sstevel@tonic-gate * 364*7c478bd9Sstevel@tonic-gate * create LDAP attributes in 'buf' for each attribute in 'items'. 365*7c478bd9Sstevel@tonic-gate */ 366*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 367*7c478bd9Sstevel@tonic-gate int 368*7c478bd9Sstevel@tonic-gate ldap_update(attrlist *items, pwu_repository_t *rep, void *buf) 369*7c478bd9Sstevel@tonic-gate { 370*7c478bd9Sstevel@tonic-gate attrlist *p; 371*7c478bd9Sstevel@tonic-gate int idx = 0; 372*7c478bd9Sstevel@tonic-gate ldapbuf_t *ldapbuf = (ldapbuf_t *)buf; 373*7c478bd9Sstevel@tonic-gate ns_ldap_attr_t **attrs = ldapbuf->attrs; 374*7c478bd9Sstevel@tonic-gate char *pwd, *val; 375*7c478bd9Sstevel@tonic-gate char *salt; 376*7c478bd9Sstevel@tonic-gate size_t cryptlen; 377*7c478bd9Sstevel@tonic-gate 378*7c478bd9Sstevel@tonic-gate for (p = items; p != NULL; p = p->next) { 379*7c478bd9Sstevel@tonic-gate switch (p->type) { 380*7c478bd9Sstevel@tonic-gate case ATTR_PASSWD: 381*7c478bd9Sstevel@tonic-gate salt = crypt_gensalt(ldapbuf->passwd, ldapbuf->pwd); 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate if (salt == NULL) { 384*7c478bd9Sstevel@tonic-gate if (errno == ENOMEM) 385*7c478bd9Sstevel@tonic-gate return (PWU_NOMEM); 386*7c478bd9Sstevel@tonic-gate else { 387*7c478bd9Sstevel@tonic-gate /* algorithm problem? */ 388*7c478bd9Sstevel@tonic-gate syslog(LOG_AUTH | LOG_ALERT, 389*7c478bd9Sstevel@tonic-gate "passwdutil: crypt_gensalt " 390*7c478bd9Sstevel@tonic-gate "%m"); 391*7c478bd9Sstevel@tonic-gate return (PWU_UPDATE_FAILED); 392*7c478bd9Sstevel@tonic-gate } 393*7c478bd9Sstevel@tonic-gate } 394*7c478bd9Sstevel@tonic-gate 395*7c478bd9Sstevel@tonic-gate pwd = crypt(p->data.val_s, salt); 396*7c478bd9Sstevel@tonic-gate free(salt); 397*7c478bd9Sstevel@tonic-gate cryptlen = strlen(pwd) + sizeof ("{crypt}"); 398*7c478bd9Sstevel@tonic-gate val = malloc(cryptlen); 399*7c478bd9Sstevel@tonic-gate if (val == NULL) 400*7c478bd9Sstevel@tonic-gate return (PWU_NOMEM); 401*7c478bd9Sstevel@tonic-gate (void) snprintf(val, cryptlen, "{crypt}%s", pwd); 402*7c478bd9Sstevel@tonic-gate 403*7c478bd9Sstevel@tonic-gate attrs[idx] = new_attr(_PWD_USERPASSWORD, val); 404*7c478bd9Sstevel@tonic-gate break; 405*7c478bd9Sstevel@tonic-gate /* 406*7c478bd9Sstevel@tonic-gate * For server policy, don't crypt the password, 407*7c478bd9Sstevel@tonic-gate * send the password as is to the server and 408*7c478bd9Sstevel@tonic-gate * let the LDAP server do its own password 409*7c478bd9Sstevel@tonic-gate * encryption 410*7c478bd9Sstevel@tonic-gate */ 411*7c478bd9Sstevel@tonic-gate case ATTR_PASSWD_SERVER_POLICY: 412*7c478bd9Sstevel@tonic-gate val = strdup(p->data.val_s); 413*7c478bd9Sstevel@tonic-gate if (val == NULL) 414*7c478bd9Sstevel@tonic-gate return (PWU_NOMEM); 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate attrs[idx] = new_attr(_PWD_USERPASSWORD, val); 417*7c478bd9Sstevel@tonic-gate break; 418*7c478bd9Sstevel@tonic-gate case ATTR_COMMENT: 419*7c478bd9Sstevel@tonic-gate /* XX correct? */ 420*7c478bd9Sstevel@tonic-gate attrs[idx] = new_attr(_PWD_DESCRIPTION, p->data.val_s); 421*7c478bd9Sstevel@tonic-gate break; 422*7c478bd9Sstevel@tonic-gate case ATTR_GECOS: 423*7c478bd9Sstevel@tonic-gate attrs[idx] = new_attr(_PWD_GECOS, p->data.val_s); 424*7c478bd9Sstevel@tonic-gate break; 425*7c478bd9Sstevel@tonic-gate case ATTR_HOMEDIR: 426*7c478bd9Sstevel@tonic-gate attrs[idx] = new_attr(_PWD_HOMEDIRECTORY, 427*7c478bd9Sstevel@tonic-gate p->data.val_s); 428*7c478bd9Sstevel@tonic-gate break; 429*7c478bd9Sstevel@tonic-gate case ATTR_SHELL: 430*7c478bd9Sstevel@tonic-gate attrs[idx] = new_attr(_PWD_LOGINSHELL, p->data.val_s); 431*7c478bd9Sstevel@tonic-gate break; 432*7c478bd9Sstevel@tonic-gate /* Unsupported items are below this line */ 433*7c478bd9Sstevel@tonic-gate case ATTR_NAME: 434*7c478bd9Sstevel@tonic-gate case ATTR_UID: 435*7c478bd9Sstevel@tonic-gate case ATTR_GID: 436*7c478bd9Sstevel@tonic-gate case ATTR_AGE: 437*7c478bd9Sstevel@tonic-gate case ATTR_LSTCHG: 438*7c478bd9Sstevel@tonic-gate case ATTR_MIN: 439*7c478bd9Sstevel@tonic-gate case ATTR_MAX: 440*7c478bd9Sstevel@tonic-gate case ATTR_WARN: 441*7c478bd9Sstevel@tonic-gate case ATTR_INACT: 442*7c478bd9Sstevel@tonic-gate case ATTR_EXPIRE: 443*7c478bd9Sstevel@tonic-gate case ATTR_FLAG: 444*7c478bd9Sstevel@tonic-gate break; 445*7c478bd9Sstevel@tonic-gate default: 446*7c478bd9Sstevel@tonic-gate break; 447*7c478bd9Sstevel@tonic-gate } 448*7c478bd9Sstevel@tonic-gate if (attrs[idx] == NULL) 449*7c478bd9Sstevel@tonic-gate return (PWU_NOMEM); 450*7c478bd9Sstevel@tonic-gate idx++; 451*7c478bd9Sstevel@tonic-gate } 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate attrs[idx] = NULL; 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate return (PWU_SUCCESS); 456*7c478bd9Sstevel@tonic-gate } 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate /* 459*7c478bd9Sstevel@tonic-gate * ldap_to_pwu_code(error, pwd_status) 460*7c478bd9Sstevel@tonic-gate * 461*7c478bd9Sstevel@tonic-gate * translation from LDAP return values and PWU return values 462*7c478bd9Sstevel@tonic-gate */ 463*7c478bd9Sstevel@tonic-gate int 464*7c478bd9Sstevel@tonic-gate ldap_to_pwu_code(int error, int pwd_status) 465*7c478bd9Sstevel@tonic-gate { 466*7c478bd9Sstevel@tonic-gate switch (error) { 467*7c478bd9Sstevel@tonic-gate case NS_LDAP_SUCCESS: return (PWU_SUCCESS); 468*7c478bd9Sstevel@tonic-gate case NS_LDAP_OP_FAILED: return (PWU_DENIED); 469*7c478bd9Sstevel@tonic-gate case NS_LDAP_NOTFOUND: return (PWU_NOT_FOUND); 470*7c478bd9Sstevel@tonic-gate case NS_LDAP_MEMORY: return (PWU_NOMEM); 471*7c478bd9Sstevel@tonic-gate case NS_LDAP_CONFIG: return (PWU_NOT_FOUND); 472*7c478bd9Sstevel@tonic-gate case NS_LDAP_INTERNAL: 473*7c478bd9Sstevel@tonic-gate switch (pwd_status) { 474*7c478bd9Sstevel@tonic-gate case NS_PASSWD_EXPIRED: 475*7c478bd9Sstevel@tonic-gate return (PWU_DENIED); 476*7c478bd9Sstevel@tonic-gate case NS_PASSWD_CHANGE_NOT_ALLOWED: 477*7c478bd9Sstevel@tonic-gate return (PWU_CHANGE_NOT_ALLOWED); 478*7c478bd9Sstevel@tonic-gate case NS_PASSWD_TOO_SHORT: 479*7c478bd9Sstevel@tonic-gate return (PWU_PWD_TOO_SHORT); 480*7c478bd9Sstevel@tonic-gate case NS_PASSWD_INVALID_SYNTAX: 481*7c478bd9Sstevel@tonic-gate return (PWU_PWD_INVALID); 482*7c478bd9Sstevel@tonic-gate case NS_PASSWD_IN_HISTORY: 483*7c478bd9Sstevel@tonic-gate return (PWU_PWD_IN_HISTORY); 484*7c478bd9Sstevel@tonic-gate case NS_PASSWD_WITHIN_MIN_AGE: 485*7c478bd9Sstevel@tonic-gate return (PWU_WITHIN_MIN_AGE); 486*7c478bd9Sstevel@tonic-gate default: 487*7c478bd9Sstevel@tonic-gate return (PWU_SYSTEM_ERROR); 488*7c478bd9Sstevel@tonic-gate } 489*7c478bd9Sstevel@tonic-gate default: return (PWU_SYSTEM_ERROR); 490*7c478bd9Sstevel@tonic-gate } 491*7c478bd9Sstevel@tonic-gate } 492*7c478bd9Sstevel@tonic-gate 493*7c478bd9Sstevel@tonic-gate int 494*7c478bd9Sstevel@tonic-gate ldap_replaceattr(const char *dn, ns_ldap_attr_t **attrs, const char *binddn, 495*7c478bd9Sstevel@tonic-gate const char *pwd, int *pwd_status) 496*7c478bd9Sstevel@tonic-gate { 497*7c478bd9Sstevel@tonic-gate int result = NS_LDAP_OP_FAILED; 498*7c478bd9Sstevel@tonic-gate int ldaprc; 499*7c478bd9Sstevel@tonic-gate int authstried = 0; 500*7c478bd9Sstevel@tonic-gate char **certpath = NULL; 501*7c478bd9Sstevel@tonic-gate ns_auth_t **app; 502*7c478bd9Sstevel@tonic-gate ns_auth_t **authpp = NULL; 503*7c478bd9Sstevel@tonic-gate ns_auth_t *authp = NULL; 504*7c478bd9Sstevel@tonic-gate ns_cred_t *credp; 505*7c478bd9Sstevel@tonic-gate ns_ldap_error_t *errorp = NULL; 506*7c478bd9Sstevel@tonic-gate 507*7c478bd9Sstevel@tonic-gate debug("%s: replace_ldapattr()", __FILE__); 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate if ((credp = (ns_cred_t *)calloc(1, sizeof (ns_cred_t))) == NULL) 510*7c478bd9Sstevel@tonic-gate return (PWU_NOMEM); 511*7c478bd9Sstevel@tonic-gate 512*7c478bd9Sstevel@tonic-gate /* Fill in the user name and password */ 513*7c478bd9Sstevel@tonic-gate if (dn == NULL || pwd == NULL) 514*7c478bd9Sstevel@tonic-gate goto out; 515*7c478bd9Sstevel@tonic-gate 516*7c478bd9Sstevel@tonic-gate credp->cred.unix_cred.userID = strdup(binddn); 517*7c478bd9Sstevel@tonic-gate credp->cred.unix_cred.passwd = strdup(pwd); 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate /* get host certificate path, if one is configured */ 520*7c478bd9Sstevel@tonic-gate ldaprc = __ns_ldap_getParam(NS_LDAP_HOST_CERTPATH_P, 521*7c478bd9Sstevel@tonic-gate (void ***)&certpath, &errorp); 522*7c478bd9Sstevel@tonic-gate if (ldaprc != NS_LDAP_SUCCESS) 523*7c478bd9Sstevel@tonic-gate goto out; 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate if (certpath && *certpath) 526*7c478bd9Sstevel@tonic-gate credp->hostcertpath = *certpath; 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate /* Load the service specific authentication method */ 529*7c478bd9Sstevel@tonic-gate ldaprc = __ns_ldap_getServiceAuthMethods("passwd-cmd", &authpp, 530*7c478bd9Sstevel@tonic-gate &errorp); 531*7c478bd9Sstevel@tonic-gate 532*7c478bd9Sstevel@tonic-gate if (ldaprc != NS_LDAP_SUCCESS) 533*7c478bd9Sstevel@tonic-gate goto out; 534*7c478bd9Sstevel@tonic-gate 535*7c478bd9Sstevel@tonic-gate /* 536*7c478bd9Sstevel@tonic-gate * if authpp is null, there is no serviceAuthenticationMethod 537*7c478bd9Sstevel@tonic-gate * try default authenticationMethod 538*7c478bd9Sstevel@tonic-gate */ 539*7c478bd9Sstevel@tonic-gate if (authpp == NULL) { 540*7c478bd9Sstevel@tonic-gate ldaprc = __ns_ldap_getParam(NS_LDAP_AUTH_P, (void ***)&authpp, 541*7c478bd9Sstevel@tonic-gate &errorp); 542*7c478bd9Sstevel@tonic-gate if (ldaprc != NS_LDAP_SUCCESS) 543*7c478bd9Sstevel@tonic-gate goto out; 544*7c478bd9Sstevel@tonic-gate } 545*7c478bd9Sstevel@tonic-gate 546*7c478bd9Sstevel@tonic-gate /* 547*7c478bd9Sstevel@tonic-gate * if authpp is still null, then can not authenticate, syslog 548*7c478bd9Sstevel@tonic-gate * error message and return error 549*7c478bd9Sstevel@tonic-gate */ 550*7c478bd9Sstevel@tonic-gate if (authpp == NULL) { 551*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 552*7c478bd9Sstevel@tonic-gate "passwdutil: no legal LDAP authentication method configured"); 553*7c478bd9Sstevel@tonic-gate result = NS_LDAP_OP_FAILED; 554*7c478bd9Sstevel@tonic-gate goto out; 555*7c478bd9Sstevel@tonic-gate } 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate /* 558*7c478bd9Sstevel@tonic-gate * Walk the array and try all authentication methods in order except 559*7c478bd9Sstevel@tonic-gate * for "none". 560*7c478bd9Sstevel@tonic-gate */ 561*7c478bd9Sstevel@tonic-gate for (app = authpp; *app; app++) { 562*7c478bd9Sstevel@tonic-gate authp = *app; 563*7c478bd9Sstevel@tonic-gate /* what about disabling other mechanisms? "tls:sasl/EXTERNAL" */ 564*7c478bd9Sstevel@tonic-gate if (authp->type == NS_LDAP_AUTH_NONE) 565*7c478bd9Sstevel@tonic-gate continue; 566*7c478bd9Sstevel@tonic-gate authstried++; 567*7c478bd9Sstevel@tonic-gate credp->auth.type = authp->type; 568*7c478bd9Sstevel@tonic-gate credp->auth.tlstype = authp->tlstype; 569*7c478bd9Sstevel@tonic-gate credp->auth.saslmech = authp->saslmech; 570*7c478bd9Sstevel@tonic-gate credp->auth.saslopt = authp->saslopt; 571*7c478bd9Sstevel@tonic-gate 572*7c478bd9Sstevel@tonic-gate ldaprc = __ns_ldap_repAttr("shadow", dn, 573*7c478bd9Sstevel@tonic-gate (const ns_ldap_attr_t * const *)attrs, 574*7c478bd9Sstevel@tonic-gate credp, 0, &errorp); 575*7c478bd9Sstevel@tonic-gate if (ldaprc == NS_LDAP_SUCCESS) { 576*7c478bd9Sstevel@tonic-gate result = NS_LDAP_SUCCESS; 577*7c478bd9Sstevel@tonic-gate goto out; 578*7c478bd9Sstevel@tonic-gate } 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate /* 581*7c478bd9Sstevel@tonic-gate * other errors might need to be added to this list, for 582*7c478bd9Sstevel@tonic-gate * the current supported mechanisms this is sufficient 583*7c478bd9Sstevel@tonic-gate */ 584*7c478bd9Sstevel@tonic-gate if ((ldaprc == NS_LDAP_INTERNAL) && 585*7c478bd9Sstevel@tonic-gate (errorp->pwd_mgmt.status == NS_PASSWD_GOOD) && 586*7c478bd9Sstevel@tonic-gate ((errorp->status == LDAP_INAPPROPRIATE_AUTH) || 587*7c478bd9Sstevel@tonic-gate (errorp->status == LDAP_INVALID_CREDENTIALS))) { 588*7c478bd9Sstevel@tonic-gate result = ldaprc; 589*7c478bd9Sstevel@tonic-gate goto out; 590*7c478bd9Sstevel@tonic-gate } 591*7c478bd9Sstevel@tonic-gate 592*7c478bd9Sstevel@tonic-gate /* 593*7c478bd9Sstevel@tonic-gate * If there is error related to password policy, 594*7c478bd9Sstevel@tonic-gate * return it to caller 595*7c478bd9Sstevel@tonic-gate */ 596*7c478bd9Sstevel@tonic-gate if ((ldaprc == NS_LDAP_INTERNAL) && 597*7c478bd9Sstevel@tonic-gate errorp->pwd_mgmt.status != NS_PASSWD_GOOD) { 598*7c478bd9Sstevel@tonic-gate *pwd_status = errorp->pwd_mgmt.status; 599*7c478bd9Sstevel@tonic-gate result = ldaprc; 600*7c478bd9Sstevel@tonic-gate goto out; 601*7c478bd9Sstevel@tonic-gate } else 602*7c478bd9Sstevel@tonic-gate *pwd_status = NS_PASSWD_GOOD; 603*7c478bd9Sstevel@tonic-gate 604*7c478bd9Sstevel@tonic-gate /* we don't really care about the error, just clean it up */ 605*7c478bd9Sstevel@tonic-gate if (errorp) 606*7c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeError(&errorp); 607*7c478bd9Sstevel@tonic-gate } 608*7c478bd9Sstevel@tonic-gate if (authstried == 0) { 609*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 610*7c478bd9Sstevel@tonic-gate "passwdutil: no legal LDAP authentication method configured"); 611*7c478bd9Sstevel@tonic-gate result = NS_LDAP_CONFIG; 612*7c478bd9Sstevel@tonic-gate goto out; 613*7c478bd9Sstevel@tonic-gate } 614*7c478bd9Sstevel@tonic-gate result = PWU_DENIED; 615*7c478bd9Sstevel@tonic-gate 616*7c478bd9Sstevel@tonic-gate out: 617*7c478bd9Sstevel@tonic-gate if (credp) 618*7c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeCred(&credp); 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate if (authpp) 621*7c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeParam((void ***)&authpp); 622*7c478bd9Sstevel@tonic-gate 623*7c478bd9Sstevel@tonic-gate if (errorp) 624*7c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeError(&errorp); 625*7c478bd9Sstevel@tonic-gate 626*7c478bd9Sstevel@tonic-gate return (result); 627*7c478bd9Sstevel@tonic-gate } 628*7c478bd9Sstevel@tonic-gate 629*7c478bd9Sstevel@tonic-gate 630*7c478bd9Sstevel@tonic-gate 631*7c478bd9Sstevel@tonic-gate /* 632*7c478bd9Sstevel@tonic-gate * ldap_putpwnam(name, oldpw, dummy, rep, buf) 633*7c478bd9Sstevel@tonic-gate * 634*7c478bd9Sstevel@tonic-gate * update the LDAP server with the attributes contained in 'buf'. 635*7c478bd9Sstevel@tonic-gate * The dummy parameter is a placeholder for NIS+ where the old 636*7c478bd9Sstevel@tonic-gate * RPC password is passwd. 637*7c478bd9Sstevel@tonic-gate */ 638*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 639*7c478bd9Sstevel@tonic-gate int 640*7c478bd9Sstevel@tonic-gate ldap_putpwnam(char *name, char *oldpw, char *dummy, 641*7c478bd9Sstevel@tonic-gate pwu_repository_t *rep, void *buf) 642*7c478bd9Sstevel@tonic-gate { 643*7c478bd9Sstevel@tonic-gate int res; 644*7c478bd9Sstevel@tonic-gate char *dn; /* dn of user whose attributes we are changing */ 645*7c478bd9Sstevel@tonic-gate char *binddn; /* dn of user who is performing the change */ 646*7c478bd9Sstevel@tonic-gate ns_ldap_error_t *errorp; 647*7c478bd9Sstevel@tonic-gate ldapbuf_t *ldapbuf = (ldapbuf_t *)buf; 648*7c478bd9Sstevel@tonic-gate ns_ldap_attr_t **attrs = ldapbuf->attrs; 649*7c478bd9Sstevel@tonic-gate struct passwd *pw; 650*7c478bd9Sstevel@tonic-gate int pwd_status; 651*7c478bd9Sstevel@tonic-gate uid_t uid; 652*7c478bd9Sstevel@tonic-gate 653*7c478bd9Sstevel@tonic-gate if (strcmp(name, "root") == 0) 654*7c478bd9Sstevel@tonic-gate return (PWU_NOT_FOUND); 655*7c478bd9Sstevel@tonic-gate 656*7c478bd9Sstevel@tonic-gate /* 657*7c478bd9Sstevel@tonic-gate * The LDAP server checks whether we are permitted to perform 658*7c478bd9Sstevel@tonic-gate * the requested change. We need to send the name of the user 659*7c478bd9Sstevel@tonic-gate * who is executing this piece of code, together with his 660*7c478bd9Sstevel@tonic-gate * current password to the server. 661*7c478bd9Sstevel@tonic-gate * If this is executed by a normal user changing his/her own 662*7c478bd9Sstevel@tonic-gate * password, this will simply be the OLD password that is to 663*7c478bd9Sstevel@tonic-gate * be changed. 664*7c478bd9Sstevel@tonic-gate * Specific case if the user who is executing this piece 665*7c478bd9Sstevel@tonic-gate * of code is root. We will then issue the LDAP request 666*7c478bd9Sstevel@tonic-gate * with the DN of the user we want to change the passwd of. 667*7c478bd9Sstevel@tonic-gate */ 668*7c478bd9Sstevel@tonic-gate 669*7c478bd9Sstevel@tonic-gate /* 670*7c478bd9Sstevel@tonic-gate * convert name of user whose attributes we are changing 671*7c478bd9Sstevel@tonic-gate * to a distinguished name 672*7c478bd9Sstevel@tonic-gate */ 673*7c478bd9Sstevel@tonic-gate res = __ns_ldap_uid2dn(name, &dn, NULL, &errorp); 674*7c478bd9Sstevel@tonic-gate if (res != NS_LDAP_SUCCESS) 675*7c478bd9Sstevel@tonic-gate goto out; 676*7c478bd9Sstevel@tonic-gate 677*7c478bd9Sstevel@tonic-gate /* 678*7c478bd9Sstevel@tonic-gate * create a dn for the user who is executing this code 679*7c478bd9Sstevel@tonic-gate */ 680*7c478bd9Sstevel@tonic-gate uid = getuid(); 681*7c478bd9Sstevel@tonic-gate if (uid == 0) { 682*7c478bd9Sstevel@tonic-gate if ((pw = getpwnam_from(name, rep, REP_LDAP)) == NULL) { 683*7c478bd9Sstevel@tonic-gate res = NS_LDAP_OP_FAILED; 684*7c478bd9Sstevel@tonic-gate goto out; 685*7c478bd9Sstevel@tonic-gate } 686*7c478bd9Sstevel@tonic-gate } else if ((pw = getpwuid_from(uid, rep, REP_LDAP)) == NULL) { 687*7c478bd9Sstevel@tonic-gate /* 688*7c478bd9Sstevel@tonic-gate * User executing this code is not known to the LDAP 689*7c478bd9Sstevel@tonic-gate * server. This operation is to be denied 690*7c478bd9Sstevel@tonic-gate */ 691*7c478bd9Sstevel@tonic-gate res = NS_LDAP_OP_FAILED; 692*7c478bd9Sstevel@tonic-gate goto out; 693*7c478bd9Sstevel@tonic-gate } 694*7c478bd9Sstevel@tonic-gate 695*7c478bd9Sstevel@tonic-gate res = __ns_ldap_uid2dn(pw->pw_name, &binddn, NULL, &errorp); 696*7c478bd9Sstevel@tonic-gate if (res != NS_LDAP_SUCCESS) 697*7c478bd9Sstevel@tonic-gate goto out; 698*7c478bd9Sstevel@tonic-gate 699*7c478bd9Sstevel@tonic-gate res = ldap_replaceattr(dn, attrs, binddn, oldpw, 700*7c478bd9Sstevel@tonic-gate &pwd_status); 701*7c478bd9Sstevel@tonic-gate 702*7c478bd9Sstevel@tonic-gate out: 703*7c478bd9Sstevel@tonic-gate while (*attrs) { 704*7c478bd9Sstevel@tonic-gate free((*attrs)->attrvalue[0]); 705*7c478bd9Sstevel@tonic-gate free(*attrs); 706*7c478bd9Sstevel@tonic-gate attrs++; 707*7c478bd9Sstevel@tonic-gate } 708*7c478bd9Sstevel@tonic-gate if (ldapbuf->passwd) { 709*7c478bd9Sstevel@tonic-gate (void) memset(ldapbuf->passwd, 0, strlen(ldapbuf->passwd)); 710*7c478bd9Sstevel@tonic-gate free(ldapbuf->passwd); 711*7c478bd9Sstevel@tonic-gate } 712*7c478bd9Sstevel@tonic-gate if (ldapbuf->pwd) 713*7c478bd9Sstevel@tonic-gate free_pwd(ldapbuf->pwd); 714*7c478bd9Sstevel@tonic-gate free(dn); 715*7c478bd9Sstevel@tonic-gate 716*7c478bd9Sstevel@tonic-gate return (ldap_to_pwu_code(res, pwd_status)); 717*7c478bd9Sstevel@tonic-gate } 718