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 2003 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 /* 30*7c478bd9Sstevel@tonic-gate * DESCRIPTION: This is the N2L equivalent of changepasswd.c. The traditional 31*7c478bd9Sstevel@tonic-gate * version modifies the NIS source files and then initiates a 32*7c478bd9Sstevel@tonic-gate * ypmake to make the maps and push them. 33*7c478bd9Sstevel@tonic-gate * 34*7c478bd9Sstevel@tonic-gate * For N2L there are no source files and the policy is that the 35*7c478bd9Sstevel@tonic-gate * definitive information is that contained in the DIT. Old 36*7c478bd9Sstevel@tonic-gate * information is read from LDAP. Assuming this authenticates, and 37*7c478bd9Sstevel@tonic-gate * the change is acceptable, this information is modified and 38*7c478bd9Sstevel@tonic-gate * written back to LDAP. 39*7c478bd9Sstevel@tonic-gate * 40*7c478bd9Sstevel@tonic-gate * Related map entries are then found and updated finally 41*7c478bd9Sstevel@tonic-gate * yppushes of the changed maps are initiated. Since the 42*7c478bd9Sstevel@tonic-gate * definitive information has already correctly been updated the 43*7c478bd9Sstevel@tonic-gate * code is tolerant of some errors during this operation. 44*7c478bd9Sstevel@tonic-gate * 45*7c478bd9Sstevel@tonic-gate * What was previously in the maps is irrelevant. 46*7c478bd9Sstevel@tonic-gate * 47*7c478bd9Sstevel@tonic-gate * Some less than perfect code (like inline constants for 48*7c478bd9Sstevel@tonic-gate * return values and a few globals) is retained from the original. 49*7c478bd9Sstevel@tonic-gate */ 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 53*7c478bd9Sstevel@tonic-gate #include <ctype.h> 54*7c478bd9Sstevel@tonic-gate #include <unistd.h> 55*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 56*7c478bd9Sstevel@tonic-gate #include <string.h> 57*7c478bd9Sstevel@tonic-gate #include <stdio.h> 58*7c478bd9Sstevel@tonic-gate #include <errno.h> 59*7c478bd9Sstevel@tonic-gate #include <syslog.h> 60*7c478bd9Sstevel@tonic-gate #include <pwd.h> 61*7c478bd9Sstevel@tonic-gate #include <signal.h> 62*7c478bd9Sstevel@tonic-gate #include <crypt.h> 63*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 64*7c478bd9Sstevel@tonic-gate #include <rpcsvc/yppasswd.h> 65*7c478bd9Sstevel@tonic-gate #include <utmpx.h> 66*7c478bd9Sstevel@tonic-gate #include <shadow.h> 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate #include <ndbm.h> 69*7c478bd9Sstevel@tonic-gate /* DO NOT INCLUDE SHIM_HOOKS.H */ 70*7c478bd9Sstevel@tonic-gate #include "shim.h" 71*7c478bd9Sstevel@tonic-gate #include "yptol.h" 72*7c478bd9Sstevel@tonic-gate #include "../ldap_util.h" 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate /* Constants */ 75*7c478bd9Sstevel@tonic-gate #define CRYPTPWSIZE CRYPT_MAXCIPHERTEXTLEN 76*7c478bd9Sstevel@tonic-gate #define STRSIZE 100 77*7c478bd9Sstevel@tonic-gate #define FINGERSIZE (4 * STRSIZE - 4) 78*7c478bd9Sstevel@tonic-gate #define SHELLSIZE (STRSIZE - 2) 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate #define UTUSERLEN (sizeof (((struct utmpx *)0)->ut_user)) 81*7c478bd9Sstevel@tonic-gate #define COLON_CHAR ':' 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate /* 84*7c478bd9Sstevel@tonic-gate * Path to DBM files. This is only required for N2L mode. Traditional mode 85*7c478bd9Sstevel@tonic-gate * works with the source files and uses the NIS Makefile to generate the maps. 86*7c478bd9Sstevel@tonic-gate * Seems to be hard coded in the rest of NIS so same is done here. 87*7c478bd9Sstevel@tonic-gate */ 88*7c478bd9Sstevel@tonic-gate #define YPDBPATH "/var/yp" 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate /* Names of password and adjunct mappings. Used to access DIT */ 91*7c478bd9Sstevel@tonic-gate #define BYNAME ".byname" 92*7c478bd9Sstevel@tonic-gate #define BYUID ".byuid" 93*7c478bd9Sstevel@tonic-gate #define BYGID ".bygid" 94*7c478bd9Sstevel@tonic-gate #define PASSWD_MAPPING "passwd" BYNAME 95*7c478bd9Sstevel@tonic-gate #define PASSWD_ADJUNCT_MAPPING "passwd.adjunct" BYNAME 96*7c478bd9Sstevel@tonic-gate #define AGEING_MAPPING "ageing" BYNAME 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate /* Bitmasks used in list of fields to change */ 99*7c478bd9Sstevel@tonic-gate #define CNG_PASSWD 0x0001 100*7c478bd9Sstevel@tonic-gate #define CNG_SH 0x0002 101*7c478bd9Sstevel@tonic-gate #define CNG_GECOS 0x0004 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate /* Globals :-( */ 104*7c478bd9Sstevel@tonic-gate extern int single, nogecos, noshell, nopw, mflag; 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate /* 107*7c478bd9Sstevel@tonic-gate * Structure for containing the information is currently in the DIT. This is 108*7c478bd9Sstevel@tonic-gate * similar to the passwd structure defined in getpwent(3C) apart from. 109*7c478bd9Sstevel@tonic-gate * 110*7c478bd9Sstevel@tonic-gate * 1. Since GID and UID are never changed they are not converted to integers. 111*7c478bd9Sstevel@tonic-gate * 2. There are extra fields to hold adjunct information. 112*7c478bd9Sstevel@tonic-gate * 3. There are extra fields to hold widely used information. 113*7c478bd9Sstevel@tonic-gate */ 114*7c478bd9Sstevel@tonic-gate struct passwd_entry { 115*7c478bd9Sstevel@tonic-gate char *pw_name; 116*7c478bd9Sstevel@tonic-gate char *pw_passwd; 117*7c478bd9Sstevel@tonic-gate char *pw_uid; 118*7c478bd9Sstevel@tonic-gate char *pw_gid; 119*7c478bd9Sstevel@tonic-gate char *pw_gecos; 120*7c478bd9Sstevel@tonic-gate char *pw_dir; 121*7c478bd9Sstevel@tonic-gate char *pw_shell; 122*7c478bd9Sstevel@tonic-gate char *adjunct_tail; /* Tail of adjunct entry (opaque) */ 123*7c478bd9Sstevel@tonic-gate bool_t adjunct; /* Flag indicating if DIT has adjunct info */ 124*7c478bd9Sstevel@tonic-gate char *pwd_str; /* New password string */ 125*7c478bd9Sstevel@tonic-gate char *adjunct_str; /* New adjunct string */ 126*7c478bd9Sstevel@tonic-gate }; 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate /* Prototypes */ 129*7c478bd9Sstevel@tonic-gate extern bool_t validloginshell(char *sh, char *arg, int); 130*7c478bd9Sstevel@tonic-gate extern int validstr(char *str, size_t size); 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate suc_code write_shadow_info(char *, struct spwd *); 133*7c478bd9Sstevel@tonic-gate int put_new_info(struct passwd_entry *, char *); 134*7c478bd9Sstevel@tonic-gate char *create_pwd_str(struct passwd_entry *, bool_t); 135*7c478bd9Sstevel@tonic-gate int proc_domain(struct yppasswd *, bool_t, char *); 136*7c478bd9Sstevel@tonic-gate int proc_request(struct yppasswd *, struct passwd_entry *, bool_t, char *); 137*7c478bd9Sstevel@tonic-gate int modify_ent(struct yppasswd *, struct passwd_entry *t, bool_t, char *); 138*7c478bd9Sstevel@tonic-gate int get_change_list(struct yppasswd *, struct passwd_entry *); 139*7c478bd9Sstevel@tonic-gate struct passwd_entry *get_old_info(char *, char *); 140*7c478bd9Sstevel@tonic-gate static char *get_next_token(char *, char **, char *); 141*7c478bd9Sstevel@tonic-gate void free_pwd_entry(struct passwd_entry *); 142*7c478bd9Sstevel@tonic-gate struct spwd *get_old_shadow(char *, char *); 143*7c478bd9Sstevel@tonic-gate suc_code decode_shadow_entry(datum *, struct spwd *); 144*7c478bd9Sstevel@tonic-gate void free_shadow_entry(struct spwd *); 145*7c478bd9Sstevel@tonic-gate int proc_maps(char *, struct passwd_entry *); 146*7c478bd9Sstevel@tonic-gate int proc_map_list(char **, char *, struct passwd_entry *, bool_t); 147*7c478bd9Sstevel@tonic-gate int update_single_map(char *, struct passwd_entry *, bool_t); 148*7c478bd9Sstevel@tonic-gate bool_t strend(char *s1, char *s2); 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate /* 151*7c478bd9Sstevel@tonic-gate * FUNCTION: shim_changepasswd() 152*7c478bd9Sstevel@tonic-gate * 153*7c478bd9Sstevel@tonic-gate * DESCRIPTION: N2L version of changepasswd(). When this is called 'useshadow' 154*7c478bd9Sstevel@tonic-gate * etc. will have been set up but are meaningless. We work out 155*7c478bd9Sstevel@tonic-gate * what to change based on information from the DIT. 156*7c478bd9Sstevel@tonic-gate * 157*7c478bd9Sstevel@tonic-gate * INPUTS: Identical to changepasswd() 158*7c478bd9Sstevel@tonic-gate * 159*7c478bd9Sstevel@tonic-gate * OUTPUTS: Identical to changepasswd() 160*7c478bd9Sstevel@tonic-gate */ 161*7c478bd9Sstevel@tonic-gate void 162*7c478bd9Sstevel@tonic-gate shim_changepasswd(SVCXPRT *transp) 163*7c478bd9Sstevel@tonic-gate { 164*7c478bd9Sstevel@tonic-gate struct yppasswd yppwd; 165*7c478bd9Sstevel@tonic-gate bool_t root_on_master = FALSE; 166*7c478bd9Sstevel@tonic-gate char domain[MAXNETNAMELEN+1]; 167*7c478bd9Sstevel@tonic-gate char **domain_list; 168*7c478bd9Sstevel@tonic-gate int dom_count, i; 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate int ret, ans = 2; /* Answer codes */ 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate /* Clean out yppwd ... maybe we don't trust RPC */ 173*7c478bd9Sstevel@tonic-gate memset(&yppwd, 0, sizeof (struct yppasswd)); 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate /* Get the RPC args */ 176*7c478bd9Sstevel@tonic-gate if (!svc_getargs(transp, xdr_yppasswd, (caddr_t)&yppwd)) { 177*7c478bd9Sstevel@tonic-gate svcerr_decode(transp); 178*7c478bd9Sstevel@tonic-gate return; 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate /* Perform basic validation */ 182*7c478bd9Sstevel@tonic-gate if ((!validstr(yppwd.newpw.pw_passwd, CRYPTPWSIZE)) || 183*7c478bd9Sstevel@tonic-gate (!validstr(yppwd.newpw.pw_name, UTUSERLEN)) || 184*7c478bd9Sstevel@tonic-gate (!validstr(yppwd.newpw.pw_gecos, FINGERSIZE)) || 185*7c478bd9Sstevel@tonic-gate (!validstr(yppwd.newpw.pw_shell, SHELLSIZE))) { 186*7c478bd9Sstevel@tonic-gate svcerr_decode(transp); 187*7c478bd9Sstevel@tonic-gate return; 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate /* 191*7c478bd9Sstevel@tonic-gate * Special case: root on the master server can change other 192*7c478bd9Sstevel@tonic-gate * users' passwords without first entering the old password. 193*7c478bd9Sstevel@tonic-gate * We need to ensure that this is indeed root on the master 194*7c478bd9Sstevel@tonic-gate * server. (bug 1253949) 195*7c478bd9Sstevel@tonic-gate */ 196*7c478bd9Sstevel@tonic-gate if (strcmp(transp->xp_netid, "ticlts") == 0) { 197*7c478bd9Sstevel@tonic-gate svc_local_cred_t cred; 198*7c478bd9Sstevel@tonic-gate if (!svc_get_local_cred(transp, &cred)) { 199*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 200*7c478bd9Sstevel@tonic-gate "Couldn't get local user credentials"); 201*7c478bd9Sstevel@tonic-gate } else if (cred.ruid == 0) 202*7c478bd9Sstevel@tonic-gate root_on_master = TRUE; 203*7c478bd9Sstevel@tonic-gate } 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate /* 206*7c478bd9Sstevel@tonic-gate * Get the domain name. This is tricky because a N2L server may be 207*7c478bd9Sstevel@tonic-gate * handling multiple domains. There is nothing in the request to 208*7c478bd9Sstevel@tonic-gate * indicate which one we are trying to change a passwd for. First 209*7c478bd9Sstevel@tonic-gate * we try to get a list of password related domains from the mapping 210*7c478bd9Sstevel@tonic-gate * file. 211*7c478bd9Sstevel@tonic-gate */ 212*7c478bd9Sstevel@tonic-gate if (0 != (dom_count = get_mapping_domain_list(&domain_list))) { 213*7c478bd9Sstevel@tonic-gate /* Got a domain list ... process all the domains */ 214*7c478bd9Sstevel@tonic-gate for (i = 0; i < dom_count; i ++) { 215*7c478bd9Sstevel@tonic-gate ret = proc_domain(&yppwd, root_on_master, 216*7c478bd9Sstevel@tonic-gate domain_list[i]); 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate /* If one has worked don't care if others fail */ 219*7c478bd9Sstevel@tonic-gate if (0 != ans) 220*7c478bd9Sstevel@tonic-gate ans = ret; 221*7c478bd9Sstevel@tonic-gate } 222*7c478bd9Sstevel@tonic-gate } 223*7c478bd9Sstevel@tonic-gate else 224*7c478bd9Sstevel@tonic-gate { 225*7c478bd9Sstevel@tonic-gate /* 226*7c478bd9Sstevel@tonic-gate * There was no domain list in the mapping file. The 227*7c478bd9Sstevel@tonic-gate * traditional version of this code calls ypmake which picks 228*7c478bd9Sstevel@tonic-gate * up the domain returned by getdomainname(). Fall back to the 229*7c478bd9Sstevel@tonic-gate * same mechanism. 230*7c478bd9Sstevel@tonic-gate */ 231*7c478bd9Sstevel@tonic-gate if (0 > getdomainname(domain, MAXNETNAMELEN+1)) { 232*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 233*7c478bd9Sstevel@tonic-gate "Could not get any domain info"); 234*7c478bd9Sstevel@tonic-gate } else { 235*7c478bd9Sstevel@tonic-gate /* Got one domain ... process it. */ 236*7c478bd9Sstevel@tonic-gate ans = proc_domain(&yppwd, root_on_master, domain); 237*7c478bd9Sstevel@tonic-gate } 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate /* Send reply packet */ 241*7c478bd9Sstevel@tonic-gate if (!svc_sendreply(transp, xdr_int, (char *)&ans)) 242*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 243*7c478bd9Sstevel@tonic-gate "could not reply to RPC call"); 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate /* 247*7c478bd9Sstevel@tonic-gate * FUNCTION : proc_domain() 248*7c478bd9Sstevel@tonic-gate * 249*7c478bd9Sstevel@tonic-gate * DESCRIPTION: Process a request for one domain 250*7c478bd9Sstevel@tonic-gate * 251*7c478bd9Sstevel@tonic-gate * GIVEN : Pointer to the request. 252*7c478bd9Sstevel@tonic-gate * Root on master flag 253*7c478bd9Sstevel@tonic-gate * Domain 254*7c478bd9Sstevel@tonic-gate * 255*7c478bd9Sstevel@tonic-gate * OUTPUTS : Answer code for reply 256*7c478bd9Sstevel@tonic-gate */ 257*7c478bd9Sstevel@tonic-gate int 258*7c478bd9Sstevel@tonic-gate proc_domain(struct yppasswd *yppwd, bool_t root_on_master, char *domain) 259*7c478bd9Sstevel@tonic-gate { 260*7c478bd9Sstevel@tonic-gate struct passwd_entry *old_pwd; 261*7c478bd9Sstevel@tonic-gate char *p; 262*7c478bd9Sstevel@tonic-gate int ans = 2; 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate /* security hole fix from original source */ 265*7c478bd9Sstevel@tonic-gate for (p = yppwd->newpw.pw_name; (*p != '\0'); p++) 266*7c478bd9Sstevel@tonic-gate if ((*p == ':') || !(isprint(*p))) 267*7c478bd9Sstevel@tonic-gate *p = '$'; /* you lose buckwheat */ 268*7c478bd9Sstevel@tonic-gate for (p = yppwd->newpw.pw_passwd; (*p != '\0'); p++) 269*7c478bd9Sstevel@tonic-gate if ((*p == ':') || !(isprint(*p))) 270*7c478bd9Sstevel@tonic-gate *p = '$'; /* you lose buckwheat */ 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate /* Get old info from DIT for this domain */ 273*7c478bd9Sstevel@tonic-gate old_pwd = get_old_info(yppwd->newpw.pw_name, domain); 274*7c478bd9Sstevel@tonic-gate if (NULL == old_pwd) { 275*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 276*7c478bd9Sstevel@tonic-gate "Could not get old information for %s in " 277*7c478bd9Sstevel@tonic-gate "domain %s", yppwd->newpw.pw_name, domain); 278*7c478bd9Sstevel@tonic-gate return (ans); 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate /* Have a request that can be replied to */ 282*7c478bd9Sstevel@tonic-gate ans = proc_request(yppwd, old_pwd, root_on_master, domain); 283*7c478bd9Sstevel@tonic-gate free_pwd_entry(old_pwd); 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate return (ans); 286*7c478bd9Sstevel@tonic-gate } 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate /* 289*7c478bd9Sstevel@tonic-gate * FUNCTION : proc_request() 290*7c478bd9Sstevel@tonic-gate * 291*7c478bd9Sstevel@tonic-gate * DESCRIPTION: Process a request 292*7c478bd9Sstevel@tonic-gate * 293*7c478bd9Sstevel@tonic-gate * GIVEN : Pointer to the request. 294*7c478bd9Sstevel@tonic-gate * Pointer to old information from LDAP 295*7c478bd9Sstevel@tonic-gate * Root on master flag 296*7c478bd9Sstevel@tonic-gate * Domain 297*7c478bd9Sstevel@tonic-gate * 298*7c478bd9Sstevel@tonic-gate * OUTPUTS : Answer code for reply 299*7c478bd9Sstevel@tonic-gate */ 300*7c478bd9Sstevel@tonic-gate int 301*7c478bd9Sstevel@tonic-gate proc_request(struct yppasswd *yppwd, struct passwd_entry *old_pwd, 302*7c478bd9Sstevel@tonic-gate bool_t root_on_master, char *domain) 303*7c478bd9Sstevel@tonic-gate { 304*7c478bd9Sstevel@tonic-gate struct sigaction sa, osa1, osa2, osa3; 305*7c478bd9Sstevel@tonic-gate int ans; 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate /* Authenticate */ 308*7c478bd9Sstevel@tonic-gate if ((0 != strcmp(crypt(yppwd->oldpass, old_pwd->pw_passwd), 309*7c478bd9Sstevel@tonic-gate old_pwd->pw_passwd)) && !root_on_master) { 310*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_NOTICE, "Passwd incorrect %s", 311*7c478bd9Sstevel@tonic-gate yppwd->newpw.pw_name); 312*7c478bd9Sstevel@tonic-gate return (7); 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate /* Work out what we have to change and change it */ 316*7c478bd9Sstevel@tonic-gate ans = modify_ent(yppwd, old_pwd, root_on_master, domain); 317*7c478bd9Sstevel@tonic-gate if (0 != ans) 318*7c478bd9Sstevel@tonic-gate return (ans); 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate /* 321*7c478bd9Sstevel@tonic-gate * Generate passwd and adjunct map entries. This creates extra 322*7c478bd9Sstevel@tonic-gate * malloced strings in old_pwd. These will be freed when 323*7c478bd9Sstevel@tonic-gate * free_pwd_entry() is called to free up the rest of the structure. 324*7c478bd9Sstevel@tonic-gate */ 325*7c478bd9Sstevel@tonic-gate old_pwd->pwd_str = create_pwd_str(old_pwd, FALSE); 326*7c478bd9Sstevel@tonic-gate if (NULL == old_pwd->pwd_str) { 327*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 328*7c478bd9Sstevel@tonic-gate "Could not create passwd entry"); 329*7c478bd9Sstevel@tonic-gate return (2); 330*7c478bd9Sstevel@tonic-gate } 331*7c478bd9Sstevel@tonic-gate if (old_pwd->adjunct) { 332*7c478bd9Sstevel@tonic-gate old_pwd->adjunct_str = create_pwd_str(old_pwd, TRUE); 333*7c478bd9Sstevel@tonic-gate if (NULL == old_pwd->adjunct_str) { 334*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 335*7c478bd9Sstevel@tonic-gate "Could not create adjunct entry"); 336*7c478bd9Sstevel@tonic-gate return (2); 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate } else { 339*7c478bd9Sstevel@tonic-gate old_pwd->adjunct_str = NULL; 340*7c478bd9Sstevel@tonic-gate } 341*7c478bd9Sstevel@tonic-gate 342*7c478bd9Sstevel@tonic-gate /* Put the information back to DIT */ 343*7c478bd9Sstevel@tonic-gate ans = put_new_info(old_pwd, domain); 344*7c478bd9Sstevel@tonic-gate if (0 != ans) { 345*7c478bd9Sstevel@tonic-gate return (ans); 346*7c478bd9Sstevel@tonic-gate } 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate /* Are going to be forking pushes, set up signals */ 349*7c478bd9Sstevel@tonic-gate memset(&sa, 0, sizeof (struct sigaction)); 350*7c478bd9Sstevel@tonic-gate sa.sa_handler = SIG_IGN; 351*7c478bd9Sstevel@tonic-gate sigaction(SIGTSTP, &sa, (struct sigaction *)0); 352*7c478bd9Sstevel@tonic-gate sigaction(SIGHUP, &sa, &osa1); 353*7c478bd9Sstevel@tonic-gate sigaction(SIGINT, &sa, &osa2); 354*7c478bd9Sstevel@tonic-gate sigaction(SIGQUIT, &sa, &osa3); 355*7c478bd9Sstevel@tonic-gate 356*7c478bd9Sstevel@tonic-gate /* Update and push all the maps */ 357*7c478bd9Sstevel@tonic-gate ans = proc_maps(domain, old_pwd); 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate /* Tidy up signals */ 360*7c478bd9Sstevel@tonic-gate sigaction(SIGHUP, &osa1, (struct sigaction *)0); 361*7c478bd9Sstevel@tonic-gate sigaction(SIGINT, &osa2, (struct sigaction *)0); 362*7c478bd9Sstevel@tonic-gate sigaction(SIGQUIT, &osa3, (struct sigaction *)0); 363*7c478bd9Sstevel@tonic-gate 364*7c478bd9Sstevel@tonic-gate return (ans); 365*7c478bd9Sstevel@tonic-gate } 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate /* 368*7c478bd9Sstevel@tonic-gate * FUNCTION: proc_maps() 369*7c478bd9Sstevel@tonic-gate * 370*7c478bd9Sstevel@tonic-gate * DESCRIPTION: Gets all the map lists and processes them. 371*7c478bd9Sstevel@tonic-gate * 372*7c478bd9Sstevel@tonic-gate * INPUTS: Domain name 373*7c478bd9Sstevel@tonic-gate * New info to write into maps 374*7c478bd9Sstevel@tonic-gate * 375*7c478bd9Sstevel@tonic-gate * OUTPUT : Answer code 376*7c478bd9Sstevel@tonic-gate */ 377*7c478bd9Sstevel@tonic-gate int 378*7c478bd9Sstevel@tonic-gate proc_maps(char *domain, struct passwd_entry *pwd) 379*7c478bd9Sstevel@tonic-gate { 380*7c478bd9Sstevel@tonic-gate char **map_list; /* Array of passwd or adjunct maps */ 381*7c478bd9Sstevel@tonic-gate int ans = 0; 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate /* Get list of passwd maps from mapping file */ 384*7c478bd9Sstevel@tonic-gate map_list = get_passwd_list(FALSE, domain); 385*7c478bd9Sstevel@tonic-gate if (map_list != NULL) { 386*7c478bd9Sstevel@tonic-gate /* Process list of passwd maps */ 387*7c478bd9Sstevel@tonic-gate ans = proc_map_list(map_list, domain, pwd, FALSE); 388*7c478bd9Sstevel@tonic-gate free_passwd_list(map_list); 389*7c478bd9Sstevel@tonic-gate if (0 != ans) 390*7c478bd9Sstevel@tonic-gate return (ans); 391*7c478bd9Sstevel@tonic-gate } 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate /* 394*7c478bd9Sstevel@tonic-gate * If we get here either there were no passwd maps or there were 395*7c478bd9Sstevel@tonic-gate * some and they were processed successfully. Either case is good 396*7c478bd9Sstevel@tonic-gate * continue and process passwd.adjunct maps. 397*7c478bd9Sstevel@tonic-gate */ 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate /* Get list of adjunct maps from mapping file */ 400*7c478bd9Sstevel@tonic-gate map_list = get_passwd_list(TRUE, domain); 401*7c478bd9Sstevel@tonic-gate if (map_list != NULL) { 402*7c478bd9Sstevel@tonic-gate /* 403*7c478bd9Sstevel@tonic-gate * Process list of adjunct maps. If the required information 404*7c478bd9Sstevel@tonic-gate * is not present in LDAP then the updates attempts will log 405*7c478bd9Sstevel@tonic-gate * an error. No need to make the check here 406*7c478bd9Sstevel@tonic-gate */ 407*7c478bd9Sstevel@tonic-gate ans = proc_map_list(map_list, domain, pwd, TRUE); 408*7c478bd9Sstevel@tonic-gate free_passwd_list(map_list); 409*7c478bd9Sstevel@tonic-gate } 410*7c478bd9Sstevel@tonic-gate 411*7c478bd9Sstevel@tonic-gate return (ans); 412*7c478bd9Sstevel@tonic-gate } 413*7c478bd9Sstevel@tonic-gate 414*7c478bd9Sstevel@tonic-gate /* 415*7c478bd9Sstevel@tonic-gate * FUNCTION: proc_map_list() 416*7c478bd9Sstevel@tonic-gate * 417*7c478bd9Sstevel@tonic-gate * DESCRIPTION: Finds entries in one list of map that need to be updated. 418*7c478bd9Sstevel@tonic-gate * updates them and writes them back. 419*7c478bd9Sstevel@tonic-gate * 420*7c478bd9Sstevel@tonic-gate * INPUTS: Null terminated list of maps to process. 421*7c478bd9Sstevel@tonic-gate * Domain name 422*7c478bd9Sstevel@tonic-gate * Information to write (including user name) 423*7c478bd9Sstevel@tonic-gate * Flag indicating if this is the adjunct list 424*7c478bd9Sstevel@tonic-gate * 425*7c478bd9Sstevel@tonic-gate * OUTPUTS: An error code 426*7c478bd9Sstevel@tonic-gate */ 427*7c478bd9Sstevel@tonic-gate int 428*7c478bd9Sstevel@tonic-gate proc_map_list(char **map_list, char *domain, 429*7c478bd9Sstevel@tonic-gate struct passwd_entry *pwd, bool_t adjunct_flag) 430*7c478bd9Sstevel@tonic-gate { 431*7c478bd9Sstevel@tonic-gate char *myself = "proc_map_list"; 432*7c478bd9Sstevel@tonic-gate char *map_name; 433*7c478bd9Sstevel@tonic-gate char cmdbuf[BUFSIZ]; 434*7c478bd9Sstevel@tonic-gate int map_name_len = 0; 435*7c478bd9Sstevel@tonic-gate int index, ans = 0; 436*7c478bd9Sstevel@tonic-gate int res; 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate /* If this is a adjunct list check LDAP had some adjunct info */ 439*7c478bd9Sstevel@tonic-gate if ((adjunct_flag) && (!pwd->adjunct)) { 440*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 441*7c478bd9Sstevel@tonic-gate "Have adjunct map list but no adjunct data in DIT"); 442*7c478bd9Sstevel@tonic-gate /* Not a disaster */ 443*7c478bd9Sstevel@tonic-gate return (0); 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate /* Allocate enough buffer to take longest map name */ 447*7c478bd9Sstevel@tonic-gate for (index = 0; map_list[index] != NULL; index ++) 448*7c478bd9Sstevel@tonic-gate if (map_name_len < strlen(map_list[index])) 449*7c478bd9Sstevel@tonic-gate map_name_len = strlen(map_list[index]); 450*7c478bd9Sstevel@tonic-gate map_name_len += strlen(YPDBPATH); 451*7c478bd9Sstevel@tonic-gate map_name_len += strlen(NTOL_PREFIX); 452*7c478bd9Sstevel@tonic-gate map_name_len += strlen(domain); 453*7c478bd9Sstevel@tonic-gate map_name_len += 3; 454*7c478bd9Sstevel@tonic-gate if (NULL == (map_name = am(myself, map_name_len))) { 455*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, "Could not alloc map name"); 456*7c478bd9Sstevel@tonic-gate return (2); 457*7c478bd9Sstevel@tonic-gate } 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate /* For all maps in list */ 460*7c478bd9Sstevel@tonic-gate for (index = 0; map_list[index] != NULL; index ++) { 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate /* Generate full map name */ 463*7c478bd9Sstevel@tonic-gate strcpy(map_name, YPDBPATH); 464*7c478bd9Sstevel@tonic-gate add_separator(map_name); 465*7c478bd9Sstevel@tonic-gate strcat(map_name, domain); 466*7c478bd9Sstevel@tonic-gate add_separator(map_name); 467*7c478bd9Sstevel@tonic-gate strcat(map_name, NTOL_PREFIX); 468*7c478bd9Sstevel@tonic-gate strcat(map_name, map_list[index]); 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate if (0 != (ans = update_single_map(map_name, pwd, adjunct_flag))) 471*7c478bd9Sstevel@tonic-gate break; 472*7c478bd9Sstevel@tonic-gate } 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate /* Done with full map path */ 475*7c478bd9Sstevel@tonic-gate sfree(map_name); 476*7c478bd9Sstevel@tonic-gate 477*7c478bd9Sstevel@tonic-gate /* 478*7c478bd9Sstevel@tonic-gate * If (ans != 0) then one more maps have failed. LDAP has however been 479*7c478bd9Sstevel@tonic-gate * updates. This is the definitive source for information there is no 480*7c478bd9Sstevel@tonic-gate * need to unwind. (This was probably due to maps that were already 481*7c478bd9Sstevel@tonic-gate * corrupt). 482*7c478bd9Sstevel@tonic-gate */ 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate /* 485*7c478bd9Sstevel@tonic-gate * If it all worked fork off push operations for the maps. Since we 486*7c478bd9Sstevel@tonic-gate * want the map to end up with it's traditional name on the slave send 487*7c478bd9Sstevel@tonic-gate * the name without its LDAP_ prefix. The slave will call ypxfrd 488*7c478bd9Sstevel@tonic-gate * which, since it is running in N2L mode, will put the prefix back on 489*7c478bd9Sstevel@tonic-gate * before reading the file. 490*7c478bd9Sstevel@tonic-gate */ 491*7c478bd9Sstevel@tonic-gate if (mflag && (0 == ans)) { 492*7c478bd9Sstevel@tonic-gate for (index = 0; (map_name = map_list[index]) != NULL; 493*7c478bd9Sstevel@tonic-gate index ++) { 494*7c478bd9Sstevel@tonic-gate if (fork() == 0) { 495*7c478bd9Sstevel@tonic-gate /* 496*7c478bd9Sstevel@tonic-gate * Define full path to yppush. Probably also 497*7c478bd9Sstevel@tonic-gate * best for security. 498*7c478bd9Sstevel@tonic-gate */ 499*7c478bd9Sstevel@tonic-gate strcpy(cmdbuf, "/usr/lib/netsvc/yp/yppush "); 500*7c478bd9Sstevel@tonic-gate strcat(cmdbuf, map_name); 501*7c478bd9Sstevel@tonic-gate if (0 > system(cmdbuf)) 502*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 503*7c478bd9Sstevel@tonic-gate "Could not initiate yppush"); 504*7c478bd9Sstevel@tonic-gate exit(0); 505*7c478bd9Sstevel@tonic-gate } 506*7c478bd9Sstevel@tonic-gate } 507*7c478bd9Sstevel@tonic-gate } 508*7c478bd9Sstevel@tonic-gate return (ans); 509*7c478bd9Sstevel@tonic-gate } 510*7c478bd9Sstevel@tonic-gate 511*7c478bd9Sstevel@tonic-gate /* 512*7c478bd9Sstevel@tonic-gate * FUNCTION : update_single_map() 513*7c478bd9Sstevel@tonic-gate * 514*7c478bd9Sstevel@tonic-gate * DESCRIPTION: Updates one map. This is messy because we want to lock the map 515*7c478bd9Sstevel@tonic-gate * to prevent other processes from updating it at the same time. 516*7c478bd9Sstevel@tonic-gate * This mandates that we open it using the shim. When we 517*7c478bd9Sstevel@tonic-gate * write to it however we DO NOT want to write through to LDAP 518*7c478bd9Sstevel@tonic-gate * i.e. do not want to use the shim. 519*7c478bd9Sstevel@tonic-gate * 520*7c478bd9Sstevel@tonic-gate * Solution : Do not include shim_hooks.h but call the shim 521*7c478bd9Sstevel@tonic-gate * versions of dbm_functions explicitly where needed. 522*7c478bd9Sstevel@tonic-gate * 523*7c478bd9Sstevel@tonic-gate * INPUT : Full name of map 524*7c478bd9Sstevel@tonic-gate * Information to write (including user name) 525*7c478bd9Sstevel@tonic-gate * Flag indicating if this is an adjunct map. 526*7c478bd9Sstevel@tonic-gate * 527*7c478bd9Sstevel@tonic-gate * OUTPUT : Answer code 528*7c478bd9Sstevel@tonic-gate * 529*7c478bd9Sstevel@tonic-gate */ 530*7c478bd9Sstevel@tonic-gate int 531*7c478bd9Sstevel@tonic-gate update_single_map(char *map_name, struct passwd_entry *pwd, bool_t adjunct_flag) 532*7c478bd9Sstevel@tonic-gate { 533*7c478bd9Sstevel@tonic-gate DBM *map; 534*7c478bd9Sstevel@tonic-gate int res; 535*7c478bd9Sstevel@tonic-gate datum data, key; 536*7c478bd9Sstevel@tonic-gate 537*7c478bd9Sstevel@tonic-gate /* Set up data */ 538*7c478bd9Sstevel@tonic-gate if (adjunct_flag) 539*7c478bd9Sstevel@tonic-gate data.dptr = pwd->adjunct_str; 540*7c478bd9Sstevel@tonic-gate else 541*7c478bd9Sstevel@tonic-gate data.dptr = pwd->pwd_str; 542*7c478bd9Sstevel@tonic-gate data.dsize = strlen(data.dptr); 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate /* Set up key dependent on which type of map this is */ 545*7c478bd9Sstevel@tonic-gate key.dptr = NULL; 546*7c478bd9Sstevel@tonic-gate if (strend(map_name, BYNAME)) 547*7c478bd9Sstevel@tonic-gate key.dptr = pwd->pw_name; 548*7c478bd9Sstevel@tonic-gate if (strend(map_name, BYUID)) 549*7c478bd9Sstevel@tonic-gate key.dptr = pwd->pw_uid; 550*7c478bd9Sstevel@tonic-gate if (strend(map_name, BYGID)) 551*7c478bd9Sstevel@tonic-gate key.dptr = pwd->pw_gid; 552*7c478bd9Sstevel@tonic-gate 553*7c478bd9Sstevel@tonic-gate if (NULL == key.dptr) { 554*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 555*7c478bd9Sstevel@tonic-gate "Unrecognized map type %s", map_name); 556*7c478bd9Sstevel@tonic-gate return (0); /* Next map */ 557*7c478bd9Sstevel@tonic-gate } 558*7c478bd9Sstevel@tonic-gate key.dsize = strlen(key.dptr); 559*7c478bd9Sstevel@tonic-gate 560*7c478bd9Sstevel@tonic-gate /* Open the map */ 561*7c478bd9Sstevel@tonic-gate map = shim_dbm_open(map_name, O_RDWR, 0600); 562*7c478bd9Sstevel@tonic-gate if (NULL == map) { 563*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, "Could not open %s", map_name); 564*7c478bd9Sstevel@tonic-gate return (0); /* Next map */ 565*7c478bd9Sstevel@tonic-gate } 566*7c478bd9Sstevel@tonic-gate 567*7c478bd9Sstevel@tonic-gate /* Lock map for update. Painful and may block but have to do it */ 568*7c478bd9Sstevel@tonic-gate if (SUCCESS != lock_map_update((map_ctrl *)map)) { 569*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 570*7c478bd9Sstevel@tonic-gate "Could not lock map %s for update", map_name); 571*7c478bd9Sstevel@tonic-gate shim_dbm_close(map); 572*7c478bd9Sstevel@tonic-gate return (2); 573*7c478bd9Sstevel@tonic-gate } 574*7c478bd9Sstevel@tonic-gate 575*7c478bd9Sstevel@tonic-gate /* Do the update use simple DBM operation */ 576*7c478bd9Sstevel@tonic-gate res = dbm_store(((map_ctrl *)map)->entries, key, data, DBM_REPLACE); 577*7c478bd9Sstevel@tonic-gate 578*7c478bd9Sstevel@tonic-gate /* update entry TTL. If we fail not a problem will just timeout early */ 579*7c478bd9Sstevel@tonic-gate update_entry_ttl((map_ctrl *)map, &key, TTL_RAND); 580*7c478bd9Sstevel@tonic-gate 581*7c478bd9Sstevel@tonic-gate /* 582*7c478bd9Sstevel@tonic-gate * Map has been modified so update YP_LAST_MODIFIED. In the vanilla 583*7c478bd9Sstevel@tonic-gate * NIS case this would have been done by the ypmake done after updating 584*7c478bd9Sstevel@tonic-gate * the passwd source file. If this fails not a great problem the map 585*7c478bd9Sstevel@tonic-gate */ 586*7c478bd9Sstevel@tonic-gate if (FAILURE == update_timestamp(((map_ctrl *)map)->entries)) { 587*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, "Could not update " 588*7c478bd9Sstevel@tonic-gate "YP_LAST_MODIFIED %s will not be pushed this time", 589*7c478bd9Sstevel@tonic-gate map_name); 590*7c478bd9Sstevel@tonic-gate } 591*7c478bd9Sstevel@tonic-gate 592*7c478bd9Sstevel@tonic-gate /* 593*7c478bd9Sstevel@tonic-gate * Possibly should hold the lock until after push is complete 594*7c478bd9Sstevel@tonic-gate * but this could deadlock if client is slow and ypxfrd also 595*7c478bd9Sstevel@tonic-gate * decides to do an update. 596*7c478bd9Sstevel@tonic-gate */ 597*7c478bd9Sstevel@tonic-gate unlock_map_update((map_ctrl *)map); 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate /* Close the map */ 600*7c478bd9Sstevel@tonic-gate shim_dbm_close(map); 601*7c478bd9Sstevel@tonic-gate 602*7c478bd9Sstevel@tonic-gate if (0 != res) { 603*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 604*7c478bd9Sstevel@tonic-gate "Could not update map %s", map_name); 605*7c478bd9Sstevel@tonic-gate return (2); 606*7c478bd9Sstevel@tonic-gate } 607*7c478bd9Sstevel@tonic-gate 608*7c478bd9Sstevel@tonic-gate return (0); 609*7c478bd9Sstevel@tonic-gate } 610*7c478bd9Sstevel@tonic-gate 611*7c478bd9Sstevel@tonic-gate /* 612*7c478bd9Sstevel@tonic-gate * FUNCTION : strend() 613*7c478bd9Sstevel@tonic-gate * 614*7c478bd9Sstevel@tonic-gate * DESCRIPTION: Determines if one string ends with another. 615*7c478bd9Sstevel@tonic-gate */ 616*7c478bd9Sstevel@tonic-gate bool_t 617*7c478bd9Sstevel@tonic-gate strend(char *s1, char *s2) 618*7c478bd9Sstevel@tonic-gate { 619*7c478bd9Sstevel@tonic-gate int len_dif; 620*7c478bd9Sstevel@tonic-gate 621*7c478bd9Sstevel@tonic-gate len_dif = strlen(s1) - strlen(s2); 622*7c478bd9Sstevel@tonic-gate if (0 > len_dif) 623*7c478bd9Sstevel@tonic-gate return (FALSE); 624*7c478bd9Sstevel@tonic-gate if (0 == strcmp(s1 + len_dif, s2)) 625*7c478bd9Sstevel@tonic-gate return (TRUE); 626*7c478bd9Sstevel@tonic-gate return (FALSE); 627*7c478bd9Sstevel@tonic-gate } 628*7c478bd9Sstevel@tonic-gate 629*7c478bd9Sstevel@tonic-gate /* 630*7c478bd9Sstevel@tonic-gate * FUNCTION: modify_ent() 631*7c478bd9Sstevel@tonic-gate * 632*7c478bd9Sstevel@tonic-gate * DESCRIPTION: Modify an entry to reflect a request. 633*7c478bd9Sstevel@tonic-gate * 634*7c478bd9Sstevel@tonic-gate * INPUT: Pointer to the request. 635*7c478bd9Sstevel@tonic-gate * Pointer to the entry to modify. 636*7c478bd9Sstevel@tonic-gate * Flag indication if we are root on master 637*7c478bd9Sstevel@tonic-gate * Domain 638*7c478bd9Sstevel@tonic-gate * 639*7c478bd9Sstevel@tonic-gate * OUTPUT: Error code 640*7c478bd9Sstevel@tonic-gate */ 641*7c478bd9Sstevel@tonic-gate int 642*7c478bd9Sstevel@tonic-gate modify_ent(struct yppasswd *yppwd, struct passwd_entry *old_ent, 643*7c478bd9Sstevel@tonic-gate bool_t root_on_master, char *domain) 644*7c478bd9Sstevel@tonic-gate { 645*7c478bd9Sstevel@tonic-gate int change_list; 646*7c478bd9Sstevel@tonic-gate struct spwd *shadow; 647*7c478bd9Sstevel@tonic-gate time_t now; 648*7c478bd9Sstevel@tonic-gate 649*7c478bd9Sstevel@tonic-gate /* Get list of changes */ 650*7c478bd9Sstevel@tonic-gate change_list = get_change_list(yppwd, old_ent); 651*7c478bd9Sstevel@tonic-gate 652*7c478bd9Sstevel@tonic-gate if (!change_list) { 653*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_NOTICE, 654*7c478bd9Sstevel@tonic-gate "No change for %s", yppwd->newpw.pw_name); 655*7c478bd9Sstevel@tonic-gate return (3); 656*7c478bd9Sstevel@tonic-gate } 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate /* Check that the shell we have been given is acceptable. */ 659*7c478bd9Sstevel@tonic-gate if ((change_list & CNG_SH) && (!validloginshell(old_ent->pw_shell, 660*7c478bd9Sstevel@tonic-gate yppwd->newpw.pw_shell, root_on_master))) 661*7c478bd9Sstevel@tonic-gate return (2); 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate /* 664*7c478bd9Sstevel@tonic-gate * If changing the password do any aging checks. 665*7c478bd9Sstevel@tonic-gate * Since there are no shadow maps this is done by accessing 666*7c478bd9Sstevel@tonic-gate * attributes in the DIT via the mapping system. 667*7c478bd9Sstevel@tonic-gate */ 668*7c478bd9Sstevel@tonic-gate if (change_list & CNG_PASSWD) { 669*7c478bd9Sstevel@tonic-gate 670*7c478bd9Sstevel@tonic-gate /* Try to get shadow information */ 671*7c478bd9Sstevel@tonic-gate shadow = get_old_shadow(yppwd->newpw.pw_name, domain); 672*7c478bd9Sstevel@tonic-gate 673*7c478bd9Sstevel@tonic-gate /* If there is shadow information make password aging checks */ 674*7c478bd9Sstevel@tonic-gate if (NULL != shadow) { 675*7c478bd9Sstevel@tonic-gate now = DAY_NOW; 676*7c478bd9Sstevel@tonic-gate /* password aging - bug for bug compatibility */ 677*7c478bd9Sstevel@tonic-gate if (shadow->sp_max != -1) { 678*7c478bd9Sstevel@tonic-gate if (now < shadow->sp_lstchg + shadow->sp_min) { 679*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 680*7c478bd9Sstevel@tonic-gate "Sorry: < %ld days since " 681*7c478bd9Sstevel@tonic-gate "the last change", shadow->sp_min); 682*7c478bd9Sstevel@tonic-gate free_shadow_entry(shadow); 683*7c478bd9Sstevel@tonic-gate return (2); 684*7c478bd9Sstevel@tonic-gate } 685*7c478bd9Sstevel@tonic-gate } 686*7c478bd9Sstevel@tonic-gate 687*7c478bd9Sstevel@tonic-gate /* Update time of change */ 688*7c478bd9Sstevel@tonic-gate shadow->sp_lstchg = now; 689*7c478bd9Sstevel@tonic-gate 690*7c478bd9Sstevel@tonic-gate /* Write it back */ 691*7c478bd9Sstevel@tonic-gate write_shadow_info(domain, shadow); 692*7c478bd9Sstevel@tonic-gate 693*7c478bd9Sstevel@tonic-gate free_shadow_entry(shadow); 694*7c478bd9Sstevel@tonic-gate } 695*7c478bd9Sstevel@tonic-gate } 696*7c478bd9Sstevel@tonic-gate 697*7c478bd9Sstevel@tonic-gate /* Make changes to old entity */ 698*7c478bd9Sstevel@tonic-gate if (change_list & CNG_GECOS) { 699*7c478bd9Sstevel@tonic-gate if (NULL != old_ent->pw_gecos) 700*7c478bd9Sstevel@tonic-gate sfree(old_ent->pw_gecos); 701*7c478bd9Sstevel@tonic-gate old_ent->pw_gecos = strdup(yppwd->newpw.pw_gecos); 702*7c478bd9Sstevel@tonic-gate if (NULL == old_ent->pw_gecos) { 703*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, "Could not allocate gecos"); 704*7c478bd9Sstevel@tonic-gate return (2); 705*7c478bd9Sstevel@tonic-gate } 706*7c478bd9Sstevel@tonic-gate } 707*7c478bd9Sstevel@tonic-gate 708*7c478bd9Sstevel@tonic-gate if (change_list & CNG_SH) { 709*7c478bd9Sstevel@tonic-gate if (NULL != old_ent->pw_shell) 710*7c478bd9Sstevel@tonic-gate sfree(old_ent->pw_shell); 711*7c478bd9Sstevel@tonic-gate old_ent->pw_shell = strdup(yppwd->newpw.pw_shell); 712*7c478bd9Sstevel@tonic-gate if (NULL == old_ent->pw_shell) { 713*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, "Could not allocate shell"); 714*7c478bd9Sstevel@tonic-gate return (2); 715*7c478bd9Sstevel@tonic-gate } 716*7c478bd9Sstevel@tonic-gate } 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate if (change_list & CNG_PASSWD) { 719*7c478bd9Sstevel@tonic-gate if (NULL != old_ent->pw_passwd) 720*7c478bd9Sstevel@tonic-gate sfree(old_ent->pw_passwd); 721*7c478bd9Sstevel@tonic-gate old_ent->pw_passwd = strdup(yppwd->newpw.pw_passwd); 722*7c478bd9Sstevel@tonic-gate if (NULL == old_ent->pw_passwd) { 723*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, "Could not allocate passwd"); 724*7c478bd9Sstevel@tonic-gate return (2); 725*7c478bd9Sstevel@tonic-gate } 726*7c478bd9Sstevel@tonic-gate } 727*7c478bd9Sstevel@tonic-gate 728*7c478bd9Sstevel@tonic-gate return (0); 729*7c478bd9Sstevel@tonic-gate } 730*7c478bd9Sstevel@tonic-gate 731*7c478bd9Sstevel@tonic-gate /* 732*7c478bd9Sstevel@tonic-gate * FUNCTION : get_change_list() 733*7c478bd9Sstevel@tonic-gate * 734*7c478bd9Sstevel@tonic-gate * DESCRIPTION: Works out what we have to change. 735*7c478bd9Sstevel@tonic-gate * 736*7c478bd9Sstevel@tonic-gate * INPUTS : Request. 737*7c478bd9Sstevel@tonic-gate * Structure containing current state of entry 738*7c478bd9Sstevel@tonic-gate * 739*7c478bd9Sstevel@tonic-gate * OUTPUTS : A bitmask signaling what to change. (Implemented in this 740*7c478bd9Sstevel@tonic-gate * way to make it easy to pass between functions). 741*7c478bd9Sstevel@tonic-gate */ 742*7c478bd9Sstevel@tonic-gate int 743*7c478bd9Sstevel@tonic-gate get_change_list(struct yppasswd *yppwd, struct passwd_entry *old_ent) 744*7c478bd9Sstevel@tonic-gate { 745*7c478bd9Sstevel@tonic-gate int list = 0; 746*7c478bd9Sstevel@tonic-gate char *p; 747*7c478bd9Sstevel@tonic-gate 748*7c478bd9Sstevel@tonic-gate p = yppwd->newpw.pw_passwd; 749*7c478bd9Sstevel@tonic-gate if ((!nopw) && 750*7c478bd9Sstevel@tonic-gate p && *p && 751*7c478bd9Sstevel@tonic-gate !(*p++ == '#' && *p++ == '#' && 752*7c478bd9Sstevel@tonic-gate (strcmp(p, old_ent->pw_name) == 0)) && 753*7c478bd9Sstevel@tonic-gate (strcmp(crypt(old_ent->pw_passwd, 754*7c478bd9Sstevel@tonic-gate yppwd->newpw.pw_passwd), yppwd->newpw.pw_passwd) != 0)) 755*7c478bd9Sstevel@tonic-gate list |= CNG_PASSWD; 756*7c478bd9Sstevel@tonic-gate 757*7c478bd9Sstevel@tonic-gate if ((NULL != old_ent->pw_shell) && 758*7c478bd9Sstevel@tonic-gate (!noshell) && 759*7c478bd9Sstevel@tonic-gate (strcmp(old_ent->pw_shell, yppwd->newpw.pw_shell) != 0)) { 760*7c478bd9Sstevel@tonic-gate if (single) 761*7c478bd9Sstevel@tonic-gate list = 0; 762*7c478bd9Sstevel@tonic-gate list |= CNG_SH; 763*7c478bd9Sstevel@tonic-gate } 764*7c478bd9Sstevel@tonic-gate 765*7c478bd9Sstevel@tonic-gate if ((NULL != old_ent->pw_gecos) && 766*7c478bd9Sstevel@tonic-gate (!nogecos) && 767*7c478bd9Sstevel@tonic-gate (strcmp(old_ent->pw_gecos, yppwd->newpw.pw_gecos) != 0)) { 768*7c478bd9Sstevel@tonic-gate if (single) 769*7c478bd9Sstevel@tonic-gate list = 0; 770*7c478bd9Sstevel@tonic-gate list |= CNG_GECOS; 771*7c478bd9Sstevel@tonic-gate } 772*7c478bd9Sstevel@tonic-gate 773*7c478bd9Sstevel@tonic-gate return (list); 774*7c478bd9Sstevel@tonic-gate } 775*7c478bd9Sstevel@tonic-gate 776*7c478bd9Sstevel@tonic-gate /* 777*7c478bd9Sstevel@tonic-gate * FUNCTION : decode_pwd_entry() 778*7c478bd9Sstevel@tonic-gate * 779*7c478bd9Sstevel@tonic-gate * DESCRIPTION: Pulls apart a password entry. Because the password entry has 780*7c478bd9Sstevel@tonic-gate * come from the mapping system it can be assumed to be correctly 781*7c478bd9Sstevel@tonic-gate * formatted and relatively simple parsing can be done. 782*7c478bd9Sstevel@tonic-gate * 783*7c478bd9Sstevel@tonic-gate * Substrings are put into malloced memory. Caller to free. 784*7c478bd9Sstevel@tonic-gate * 785*7c478bd9Sstevel@tonic-gate * For adjunct files most of it is left empty. 786*7c478bd9Sstevel@tonic-gate * 787*7c478bd9Sstevel@tonic-gate * It would be nice to use getpwent and friends for this work but 788*7c478bd9Sstevel@tonic-gate * these only seem to exist for files and it seems excessive to 789*7c478bd9Sstevel@tonic-gate * create a temporary file for this operation. 790*7c478bd9Sstevel@tonic-gate * 791*7c478bd9Sstevel@tonic-gate * INPUTS: Pointer to datum containing password string. 792*7c478bd9Sstevel@tonic-gate * Pointer to structure in which to return results 793*7c478bd9Sstevel@tonic-gate * Flag indicating if we are decoding passwd or passwd.adjunct 794*7c478bd9Sstevel@tonic-gate * 795*7c478bd9Sstevel@tonic-gate * OUTPUTS: SUCCESS = Decoded successfully 796*7c478bd9Sstevel@tonic-gate * FAILURE = Not decoded successfully. Caller to tidy up. 797*7c478bd9Sstevel@tonic-gate */ 798*7c478bd9Sstevel@tonic-gate suc_code 799*7c478bd9Sstevel@tonic-gate decode_pwd_entry(datum *data, struct passwd_entry *pwd, bool_t adjunct) 800*7c478bd9Sstevel@tonic-gate { 801*7c478bd9Sstevel@tonic-gate char *myself = "decode_pwd_entry"; 802*7c478bd9Sstevel@tonic-gate char *p, *str_end, *temp; 803*7c478bd9Sstevel@tonic-gate 804*7c478bd9Sstevel@tonic-gate /* Work out last location in string */ 805*7c478bd9Sstevel@tonic-gate str_end = data->dptr + data->dsize; 806*7c478bd9Sstevel@tonic-gate 807*7c478bd9Sstevel@tonic-gate /* Name */ 808*7c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(data->dptr, &temp, str_end))) 809*7c478bd9Sstevel@tonic-gate return (FAILURE); 810*7c478bd9Sstevel@tonic-gate if (adjunct) { 811*7c478bd9Sstevel@tonic-gate /* If we found an adjunct version this is the one to use */ 812*7c478bd9Sstevel@tonic-gate if (NULL != pwd->pw_name) 813*7c478bd9Sstevel@tonic-gate sfree(pwd->pw_name); 814*7c478bd9Sstevel@tonic-gate } 815*7c478bd9Sstevel@tonic-gate pwd->pw_name = temp; 816*7c478bd9Sstevel@tonic-gate 817*7c478bd9Sstevel@tonic-gate /* Password */ 818*7c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(p, &temp, str_end))) 819*7c478bd9Sstevel@tonic-gate return (FAILURE); 820*7c478bd9Sstevel@tonic-gate if (adjunct) { 821*7c478bd9Sstevel@tonic-gate /* If we found an adjunct version this is the one to use */ 822*7c478bd9Sstevel@tonic-gate if (NULL != pwd->pw_passwd) 823*7c478bd9Sstevel@tonic-gate sfree(pwd->pw_passwd); 824*7c478bd9Sstevel@tonic-gate } 825*7c478bd9Sstevel@tonic-gate pwd->pw_passwd = temp; 826*7c478bd9Sstevel@tonic-gate 827*7c478bd9Sstevel@tonic-gate if (adjunct) { 828*7c478bd9Sstevel@tonic-gate /* Store adjunct information in opaque string */ 829*7c478bd9Sstevel@tonic-gate pwd->adjunct_tail = am(myself, str_end - p + 1); 830*7c478bd9Sstevel@tonic-gate if (NULL == pwd->adjunct_tail) 831*7c478bd9Sstevel@tonic-gate return (FAILURE); 832*7c478bd9Sstevel@tonic-gate strncpy(pwd->adjunct_tail, p, str_end - p); 833*7c478bd9Sstevel@tonic-gate pwd->adjunct_tail[str_end - p] = '\0'; 834*7c478bd9Sstevel@tonic-gate 835*7c478bd9Sstevel@tonic-gate /* Remember that LDAP contained adjunct data */ 836*7c478bd9Sstevel@tonic-gate pwd->adjunct = TRUE; 837*7c478bd9Sstevel@tonic-gate return (SUCCESS); 838*7c478bd9Sstevel@tonic-gate } 839*7c478bd9Sstevel@tonic-gate 840*7c478bd9Sstevel@tonic-gate /* If we get here not adjunct. Decode rest of passwd */ 841*7c478bd9Sstevel@tonic-gate 842*7c478bd9Sstevel@tonic-gate /* UID */ 843*7c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(p, &(pwd->pw_uid), str_end))) 844*7c478bd9Sstevel@tonic-gate return (FAILURE); 845*7c478bd9Sstevel@tonic-gate 846*7c478bd9Sstevel@tonic-gate /* GID */ 847*7c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(p, &(pwd->pw_gid), str_end))) 848*7c478bd9Sstevel@tonic-gate return (FAILURE); 849*7c478bd9Sstevel@tonic-gate 850*7c478bd9Sstevel@tonic-gate /* Gecos */ 851*7c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(p, &(pwd->pw_gecos), str_end))) 852*7c478bd9Sstevel@tonic-gate return (FAILURE); 853*7c478bd9Sstevel@tonic-gate 854*7c478bd9Sstevel@tonic-gate /* Home dir */ 855*7c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(p, &(pwd->pw_dir), str_end))) 856*7c478bd9Sstevel@tonic-gate return (FAILURE); 857*7c478bd9Sstevel@tonic-gate 858*7c478bd9Sstevel@tonic-gate /* Shell may not be present so don't check return */ 859*7c478bd9Sstevel@tonic-gate get_next_token(p, &(pwd->pw_shell), str_end); 860*7c478bd9Sstevel@tonic-gate 861*7c478bd9Sstevel@tonic-gate if (NULL == pwd->pw_shell) 862*7c478bd9Sstevel@tonic-gate return (FAILURE); 863*7c478bd9Sstevel@tonic-gate 864*7c478bd9Sstevel@tonic-gate return (SUCCESS); 865*7c478bd9Sstevel@tonic-gate } 866*7c478bd9Sstevel@tonic-gate 867*7c478bd9Sstevel@tonic-gate /* 868*7c478bd9Sstevel@tonic-gate * FUNCTION : get_next_token() 869*7c478bd9Sstevel@tonic-gate * 870*7c478bd9Sstevel@tonic-gate * DESCRIPTION: Gets the next token from a string upto the next colon or the 871*7c478bd9Sstevel@tonic-gate * end of the string. The duplicates this token into malloced 872*7c478bd9Sstevel@tonic-gate * memory removing any spaces. 873*7c478bd9Sstevel@tonic-gate * 874*7c478bd9Sstevel@tonic-gate * INPUTS : String to search for token. NOT NULL TERMINATED 875*7c478bd9Sstevel@tonic-gate * Location to return result (NULL if result not required) 876*7c478bd9Sstevel@tonic-gate * Last location in string 877*7c478bd9Sstevel@tonic-gate * 878*7c478bd9Sstevel@tonic-gate * OUTPUT : Pointer into the string immediately after the token. 879*7c478bd9Sstevel@tonic-gate * NULL if end of string reached or error. 880*7c478bd9Sstevel@tonic-gate */ 881*7c478bd9Sstevel@tonic-gate static char * 882*7c478bd9Sstevel@tonic-gate get_next_token(char *str, char **op, char *str_end) 883*7c478bd9Sstevel@tonic-gate { 884*7c478bd9Sstevel@tonic-gate char *myself = "get_next_token"; 885*7c478bd9Sstevel@tonic-gate char *p, *tok_start, *tok_end; 886*7c478bd9Sstevel@tonic-gate 887*7c478bd9Sstevel@tonic-gate p = str; 888*7c478bd9Sstevel@tonic-gate /* Skip leading whitespace */ 889*7c478bd9Sstevel@tonic-gate while (' ' == *p) 890*7c478bd9Sstevel@tonic-gate p++; 891*7c478bd9Sstevel@tonic-gate tok_start = p; 892*7c478bd9Sstevel@tonic-gate tok_end = p; 893*7c478bd9Sstevel@tonic-gate 894*7c478bd9Sstevel@tonic-gate while ((str_end + 1 != p) && (COLON_CHAR != *p)) { 895*7c478bd9Sstevel@tonic-gate if (' ' != *p) 896*7c478bd9Sstevel@tonic-gate tok_end = p; 897*7c478bd9Sstevel@tonic-gate p++; 898*7c478bd9Sstevel@tonic-gate } 899*7c478bd9Sstevel@tonic-gate 900*7c478bd9Sstevel@tonic-gate /* Required string is now between start and end */ 901*7c478bd9Sstevel@tonic-gate if (NULL != op) { 902*7c478bd9Sstevel@tonic-gate *op = am(myself, tok_end - tok_start + 2); 903*7c478bd9Sstevel@tonic-gate if (NULL == *op) { 904*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, 905*7c478bd9Sstevel@tonic-gate "Could not alloc memory for token"); 906*7c478bd9Sstevel@tonic-gate return (NULL); 907*7c478bd9Sstevel@tonic-gate } 908*7c478bd9Sstevel@tonic-gate strncpy(*op, tok_start, tok_end - tok_start + 1); 909*7c478bd9Sstevel@tonic-gate 910*7c478bd9Sstevel@tonic-gate /* Terminate token */ 911*7c478bd9Sstevel@tonic-gate (*op)[tok_end - tok_start + 1] = '\0'; 912*7c478bd9Sstevel@tonic-gate 913*7c478bd9Sstevel@tonic-gate } 914*7c478bd9Sstevel@tonic-gate 915*7c478bd9Sstevel@tonic-gate /* Check if we reached the end of the input string */ 916*7c478bd9Sstevel@tonic-gate if ('\0' == *p) 917*7c478bd9Sstevel@tonic-gate return (NULL); 918*7c478bd9Sstevel@tonic-gate 919*7c478bd9Sstevel@tonic-gate /* There is some more */ 920*7c478bd9Sstevel@tonic-gate p++; 921*7c478bd9Sstevel@tonic-gate return (p); 922*7c478bd9Sstevel@tonic-gate } 923*7c478bd9Sstevel@tonic-gate 924*7c478bd9Sstevel@tonic-gate /* 925*7c478bd9Sstevel@tonic-gate * FUNCTION : free_pwd_entry() 926*7c478bd9Sstevel@tonic-gate * 927*7c478bd9Sstevel@tonic-gate * DESCRIPTION: Frees up a pwd_entry structure and its contents. 928*7c478bd9Sstevel@tonic-gate * 929*7c478bd9Sstevel@tonic-gate * INPUTS: Pointer to the structure to free. 930*7c478bd9Sstevel@tonic-gate * 931*7c478bd9Sstevel@tonic-gate * OUTPUT: Nothing 932*7c478bd9Sstevel@tonic-gate */ 933*7c478bd9Sstevel@tonic-gate void 934*7c478bd9Sstevel@tonic-gate free_pwd_entry(struct passwd_entry *pwd) 935*7c478bd9Sstevel@tonic-gate { 936*7c478bd9Sstevel@tonic-gate /* Free up strings */ 937*7c478bd9Sstevel@tonic-gate if (NULL != pwd->pw_name) 938*7c478bd9Sstevel@tonic-gate sfree(pwd->pw_name); 939*7c478bd9Sstevel@tonic-gate 940*7c478bd9Sstevel@tonic-gate if (NULL != pwd->pw_passwd) 941*7c478bd9Sstevel@tonic-gate sfree(pwd->pw_passwd); 942*7c478bd9Sstevel@tonic-gate 943*7c478bd9Sstevel@tonic-gate if (NULL != pwd->pw_gecos) 944*7c478bd9Sstevel@tonic-gate sfree(pwd->pw_gecos); 945*7c478bd9Sstevel@tonic-gate 946*7c478bd9Sstevel@tonic-gate if (NULL != pwd->pw_shell) 947*7c478bd9Sstevel@tonic-gate sfree(pwd->pw_shell); 948*7c478bd9Sstevel@tonic-gate 949*7c478bd9Sstevel@tonic-gate if (NULL != pwd->pw_dir) 950*7c478bd9Sstevel@tonic-gate sfree(pwd->pw_dir); 951*7c478bd9Sstevel@tonic-gate 952*7c478bd9Sstevel@tonic-gate if (NULL != pwd->adjunct_tail) 953*7c478bd9Sstevel@tonic-gate sfree(pwd->adjunct_tail); 954*7c478bd9Sstevel@tonic-gate 955*7c478bd9Sstevel@tonic-gate if (NULL != pwd->pwd_str) 956*7c478bd9Sstevel@tonic-gate sfree(pwd->pwd_str); 957*7c478bd9Sstevel@tonic-gate 958*7c478bd9Sstevel@tonic-gate if (NULL != pwd->adjunct_str) 959*7c478bd9Sstevel@tonic-gate sfree(pwd->adjunct_str); 960*7c478bd9Sstevel@tonic-gate 961*7c478bd9Sstevel@tonic-gate /* Free up structure */ 962*7c478bd9Sstevel@tonic-gate sfree(pwd); 963*7c478bd9Sstevel@tonic-gate } 964*7c478bd9Sstevel@tonic-gate 965*7c478bd9Sstevel@tonic-gate /* 966*7c478bd9Sstevel@tonic-gate * FUNCTION : create_pwd_str() 967*7c478bd9Sstevel@tonic-gate * 968*7c478bd9Sstevel@tonic-gate * DESCRIPTION: Builds up a new password entity string from a passwd structure. 969*7c478bd9Sstevel@tonic-gate * 970*7c478bd9Sstevel@tonic-gate * INPUTS : Structure containing password details 971*7c478bd9Sstevel@tonic-gate * Flag indicating if we should create an adjunct or passwd string. 972*7c478bd9Sstevel@tonic-gate * 973*7c478bd9Sstevel@tonic-gate * OUTPUTS : String in malloced memory (to be freed by caller). 974*7c478bd9Sstevel@tonic-gate * NULL on failure. 975*7c478bd9Sstevel@tonic-gate */ 976*7c478bd9Sstevel@tonic-gate char * 977*7c478bd9Sstevel@tonic-gate create_pwd_str(struct passwd_entry *pwd, bool_t adjunct) 978*7c478bd9Sstevel@tonic-gate { 979*7c478bd9Sstevel@tonic-gate char *myself = "create_pwd_str"; 980*7c478bd9Sstevel@tonic-gate char *s; 981*7c478bd9Sstevel@tonic-gate int len; 982*7c478bd9Sstevel@tonic-gate 983*7c478bd9Sstevel@tonic-gate /* Separator string so we can strcat separator onto things */ 984*7c478bd9Sstevel@tonic-gate char sep_str[2] = {COLON_CHAR, '\0'}; 985*7c478bd9Sstevel@tonic-gate 986*7c478bd9Sstevel@tonic-gate /* Work out the size */ 987*7c478bd9Sstevel@tonic-gate len = strlen(pwd->pw_name) + 1; 988*7c478bd9Sstevel@tonic-gate len += strlen(pwd->pw_passwd) + 1; 989*7c478bd9Sstevel@tonic-gate if (adjunct) { 990*7c478bd9Sstevel@tonic-gate len += strlen(pwd->adjunct_tail) + 1; 991*7c478bd9Sstevel@tonic-gate } else { 992*7c478bd9Sstevel@tonic-gate len += strlen(pwd->pw_uid) + 1; 993*7c478bd9Sstevel@tonic-gate len += strlen(pwd->pw_gid) + 1; 994*7c478bd9Sstevel@tonic-gate len += strlen(pwd->pw_gecos) + 1; 995*7c478bd9Sstevel@tonic-gate len += strlen(pwd->pw_dir) + 1; 996*7c478bd9Sstevel@tonic-gate len += strlen(pwd->pw_shell) + 1; 997*7c478bd9Sstevel@tonic-gate } 998*7c478bd9Sstevel@tonic-gate 999*7c478bd9Sstevel@tonic-gate /* Allocate some memory for it */ 1000*7c478bd9Sstevel@tonic-gate s = am(myself, len); 1001*7c478bd9Sstevel@tonic-gate if (NULL == s) 1002*7c478bd9Sstevel@tonic-gate return (NULL); 1003*7c478bd9Sstevel@tonic-gate 1004*7c478bd9Sstevel@tonic-gate strcpy(s, pwd->pw_name); 1005*7c478bd9Sstevel@tonic-gate strcat(s, sep_str); 1006*7c478bd9Sstevel@tonic-gate if (!adjunct) { 1007*7c478bd9Sstevel@tonic-gate /* Build up a passwd string */ 1008*7c478bd9Sstevel@tonic-gate 1009*7c478bd9Sstevel@tonic-gate /* If LDAP contains adjunct info then passwd is 'x' */ 1010*7c478bd9Sstevel@tonic-gate if (pwd->adjunct) { 1011*7c478bd9Sstevel@tonic-gate strcat(s, "##"); 1012*7c478bd9Sstevel@tonic-gate strcat(s, pwd->pw_name); 1013*7c478bd9Sstevel@tonic-gate } else { 1014*7c478bd9Sstevel@tonic-gate strcat(s, pwd->pw_passwd); 1015*7c478bd9Sstevel@tonic-gate } 1016*7c478bd9Sstevel@tonic-gate strcat(s, sep_str); 1017*7c478bd9Sstevel@tonic-gate strcat(s, pwd->pw_uid); 1018*7c478bd9Sstevel@tonic-gate strcat(s, sep_str); 1019*7c478bd9Sstevel@tonic-gate strcat(s, pwd->pw_gid); 1020*7c478bd9Sstevel@tonic-gate strcat(s, sep_str); 1021*7c478bd9Sstevel@tonic-gate strcat(s, pwd->pw_gecos); 1022*7c478bd9Sstevel@tonic-gate strcat(s, sep_str); 1023*7c478bd9Sstevel@tonic-gate strcat(s, pwd->pw_dir); 1024*7c478bd9Sstevel@tonic-gate strcat(s, sep_str); 1025*7c478bd9Sstevel@tonic-gate strcat(s, pwd->pw_shell); 1026*7c478bd9Sstevel@tonic-gate } else { 1027*7c478bd9Sstevel@tonic-gate /* Build up a passwd_adjunct string */ 1028*7c478bd9Sstevel@tonic-gate strcat(s, pwd->pw_passwd); 1029*7c478bd9Sstevel@tonic-gate strcat(s, sep_str); 1030*7c478bd9Sstevel@tonic-gate strcat(s, pwd->adjunct_tail); 1031*7c478bd9Sstevel@tonic-gate } 1032*7c478bd9Sstevel@tonic-gate 1033*7c478bd9Sstevel@tonic-gate return (s); 1034*7c478bd9Sstevel@tonic-gate } 1035*7c478bd9Sstevel@tonic-gate 1036*7c478bd9Sstevel@tonic-gate /* 1037*7c478bd9Sstevel@tonic-gate * FUNCTION: get_old_info() 1038*7c478bd9Sstevel@tonic-gate * 1039*7c478bd9Sstevel@tonic-gate * DESCRIPTION: Gets as much information as possible from LDAP about one user. 1040*7c478bd9Sstevel@tonic-gate * 1041*7c478bd9Sstevel@tonic-gate * This goes through the mapping system. This is messy because 1042*7c478bd9Sstevel@tonic-gate * them mapping system will build up a password entry from the 1043*7c478bd9Sstevel@tonic-gate * contents of the DIT. We then have to parse this to recover 1044*7c478bd9Sstevel@tonic-gate * it's individual fields. 1045*7c478bd9Sstevel@tonic-gate * 1046*7c478bd9Sstevel@tonic-gate * INPUT: Pointer to user name 1047*7c478bd9Sstevel@tonic-gate * Domain 1048*7c478bd9Sstevel@tonic-gate * 1049*7c478bd9Sstevel@tonic-gate * OUTPUT: The info in malloced space. To be freed by caller. 1050*7c478bd9Sstevel@tonic-gate * NULL on failure. 1051*7c478bd9Sstevel@tonic-gate */ 1052*7c478bd9Sstevel@tonic-gate struct passwd_entry * 1053*7c478bd9Sstevel@tonic-gate get_old_info(char *name, char *domain) 1054*7c478bd9Sstevel@tonic-gate { 1055*7c478bd9Sstevel@tonic-gate char *myself = "get_old_info"; 1056*7c478bd9Sstevel@tonic-gate struct passwd_entry *old_passwd; 1057*7c478bd9Sstevel@tonic-gate char *p; 1058*7c478bd9Sstevel@tonic-gate datum key, data; 1059*7c478bd9Sstevel@tonic-gate suc_code res; 1060*7c478bd9Sstevel@tonic-gate 1061*7c478bd9Sstevel@tonic-gate /* Get the password entry */ 1062*7c478bd9Sstevel@tonic-gate key.dptr = name; 1063*7c478bd9Sstevel@tonic-gate key.dsize = strlen(key.dptr); 1064*7c478bd9Sstevel@tonic-gate read_from_dit(PASSWD_MAPPING, domain, &key, &data); 1065*7c478bd9Sstevel@tonic-gate if (NULL == data.dptr) { 1066*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 1067*7c478bd9Sstevel@tonic-gate "Could not read old pwd for %s", name); 1068*7c478bd9Sstevel@tonic-gate return (NULL); 1069*7c478bd9Sstevel@tonic-gate } 1070*7c478bd9Sstevel@tonic-gate 1071*7c478bd9Sstevel@tonic-gate /* Pull password apart */ 1072*7c478bd9Sstevel@tonic-gate old_passwd = am(myself, sizeof (struct passwd_entry)); 1073*7c478bd9Sstevel@tonic-gate if (NULL == old_passwd) { 1074*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, "Could not alloc for pwd decode"); 1075*7c478bd9Sstevel@tonic-gate sfree(data.dptr); 1076*7c478bd9Sstevel@tonic-gate return (NULL); 1077*7c478bd9Sstevel@tonic-gate } 1078*7c478bd9Sstevel@tonic-gate 1079*7c478bd9Sstevel@tonic-gate /* No data yet */ 1080*7c478bd9Sstevel@tonic-gate old_passwd->pw_name = NULL; 1081*7c478bd9Sstevel@tonic-gate old_passwd->pw_passwd = NULL; 1082*7c478bd9Sstevel@tonic-gate old_passwd->pw_uid = NULL; 1083*7c478bd9Sstevel@tonic-gate old_passwd->pw_gid = NULL; 1084*7c478bd9Sstevel@tonic-gate old_passwd->pw_gecos = NULL; 1085*7c478bd9Sstevel@tonic-gate old_passwd->pw_dir = NULL; 1086*7c478bd9Sstevel@tonic-gate old_passwd->pw_shell = NULL; 1087*7c478bd9Sstevel@tonic-gate old_passwd->adjunct_tail = NULL; 1088*7c478bd9Sstevel@tonic-gate old_passwd->pwd_str = NULL; 1089*7c478bd9Sstevel@tonic-gate old_passwd->adjunct_str = NULL; 1090*7c478bd9Sstevel@tonic-gate old_passwd->adjunct = FALSE; 1091*7c478bd9Sstevel@tonic-gate 1092*7c478bd9Sstevel@tonic-gate res = decode_pwd_entry(&data, old_passwd, FALSE); 1093*7c478bd9Sstevel@tonic-gate sfree(data.dptr); 1094*7c478bd9Sstevel@tonic-gate if (SUCCESS != res) { 1095*7c478bd9Sstevel@tonic-gate free_pwd_entry(old_passwd); 1096*7c478bd9Sstevel@tonic-gate return (NULL); 1097*7c478bd9Sstevel@tonic-gate } 1098*7c478bd9Sstevel@tonic-gate 1099*7c478bd9Sstevel@tonic-gate /* Try to get the adjunct entry */ 1100*7c478bd9Sstevel@tonic-gate read_from_dit(PASSWD_ADJUNCT_MAPPING, domain, &key, &data); 1101*7c478bd9Sstevel@tonic-gate if (NULL == data.dptr) { 1102*7c478bd9Sstevel@tonic-gate /* Fine just no adjunct data */ 1103*7c478bd9Sstevel@tonic-gate old_passwd->adjunct = FALSE; 1104*7c478bd9Sstevel@tonic-gate } else { 1105*7c478bd9Sstevel@tonic-gate res = decode_pwd_entry(&data, old_passwd, TRUE); 1106*7c478bd9Sstevel@tonic-gate sfree(data.dptr); 1107*7c478bd9Sstevel@tonic-gate if (SUCCESS != res) { 1108*7c478bd9Sstevel@tonic-gate free_pwd_entry(old_passwd); 1109*7c478bd9Sstevel@tonic-gate return (NULL); 1110*7c478bd9Sstevel@tonic-gate } 1111*7c478bd9Sstevel@tonic-gate } 1112*7c478bd9Sstevel@tonic-gate 1113*7c478bd9Sstevel@tonic-gate return (old_passwd); 1114*7c478bd9Sstevel@tonic-gate } 1115*7c478bd9Sstevel@tonic-gate 1116*7c478bd9Sstevel@tonic-gate /* 1117*7c478bd9Sstevel@tonic-gate * FUNCTION : put_new_info() 1118*7c478bd9Sstevel@tonic-gate * 1119*7c478bd9Sstevel@tonic-gate * DESCRIPTION: Generates new map strings and puts them back to LDAP 1120*7c478bd9Sstevel@tonic-gate * 1121*7c478bd9Sstevel@tonic-gate * INPUTS: Info to put back 1122*7c478bd9Sstevel@tonic-gate * Domain 1123*7c478bd9Sstevel@tonic-gate * 1124*7c478bd9Sstevel@tonic-gate * OUTPUT: Answer code. 1125*7c478bd9Sstevel@tonic-gate */ 1126*7c478bd9Sstevel@tonic-gate int 1127*7c478bd9Sstevel@tonic-gate put_new_info(struct passwd_entry *pwd, char *domain) 1128*7c478bd9Sstevel@tonic-gate { 1129*7c478bd9Sstevel@tonic-gate datum key, data; 1130*7c478bd9Sstevel@tonic-gate 1131*7c478bd9Sstevel@tonic-gate /* Write it back to LDAP */ 1132*7c478bd9Sstevel@tonic-gate data.dptr = pwd->pwd_str; 1133*7c478bd9Sstevel@tonic-gate data.dsize = strlen(data.dptr); 1134*7c478bd9Sstevel@tonic-gate key.dptr = pwd->pw_name; 1135*7c478bd9Sstevel@tonic-gate key.dsize = strlen(key.dptr); 1136*7c478bd9Sstevel@tonic-gate if (SUCCESS != write_to_dit(PASSWD_MAPPING, domain, key, data, 1137*7c478bd9Sstevel@tonic-gate TRUE, FALSE)) 1138*7c478bd9Sstevel@tonic-gate return (2); 1139*7c478bd9Sstevel@tonic-gate 1140*7c478bd9Sstevel@tonic-gate 1141*7c478bd9Sstevel@tonic-gate /* If DIT contains adjunct information do the same for adjunct */ 1142*7c478bd9Sstevel@tonic-gate if (pwd->adjunct) { 1143*7c478bd9Sstevel@tonic-gate data.dptr = pwd->adjunct_str; 1144*7c478bd9Sstevel@tonic-gate data.dsize = strlen(data.dptr); 1145*7c478bd9Sstevel@tonic-gate key.dptr = pwd->pw_name; 1146*7c478bd9Sstevel@tonic-gate key.dsize = strlen(key.dptr); 1147*7c478bd9Sstevel@tonic-gate if (SUCCESS != write_to_dit(PASSWD_ADJUNCT_MAPPING, domain, 1148*7c478bd9Sstevel@tonic-gate key, data, TRUE, FALSE)) 1149*7c478bd9Sstevel@tonic-gate return (2); 1150*7c478bd9Sstevel@tonic-gate } 1151*7c478bd9Sstevel@tonic-gate 1152*7c478bd9Sstevel@tonic-gate return (0); 1153*7c478bd9Sstevel@tonic-gate 1154*7c478bd9Sstevel@tonic-gate } 1155*7c478bd9Sstevel@tonic-gate 1156*7c478bd9Sstevel@tonic-gate /* 1157*7c478bd9Sstevel@tonic-gate * FUNCTION : get_old_shadow() 1158*7c478bd9Sstevel@tonic-gate * 1159*7c478bd9Sstevel@tonic-gate * DESCRIPTION :Extracts and decodes shadow information from the DIT 1160*7c478bd9Sstevel@tonic-gate * See also comments under decode_pwd_entry(). 1161*7c478bd9Sstevel@tonic-gate * 1162*7c478bd9Sstevel@tonic-gate * INPUTS : User name 1163*7c478bd9Sstevel@tonic-gate * Domain name 1164*7c478bd9Sstevel@tonic-gate * 1165*7c478bd9Sstevel@tonic-gate * OUTPUT : Shadow information in malloced memory. To be freed by caller. 1166*7c478bd9Sstevel@tonic-gate */ 1167*7c478bd9Sstevel@tonic-gate struct spwd * 1168*7c478bd9Sstevel@tonic-gate get_old_shadow(char *name, char *domain) 1169*7c478bd9Sstevel@tonic-gate { 1170*7c478bd9Sstevel@tonic-gate char *myself = "get_old_shadow"; 1171*7c478bd9Sstevel@tonic-gate struct spwd *sp; 1172*7c478bd9Sstevel@tonic-gate datum key, data; 1173*7c478bd9Sstevel@tonic-gate suc_code res; 1174*7c478bd9Sstevel@tonic-gate 1175*7c478bd9Sstevel@tonic-gate /* Get the info */ 1176*7c478bd9Sstevel@tonic-gate key.dptr = name; 1177*7c478bd9Sstevel@tonic-gate key.dsize = strlen(key.dptr); /* Len excluding terminator */ 1178*7c478bd9Sstevel@tonic-gate read_from_dit(AGEING_MAPPING, domain, &key, &data); 1179*7c478bd9Sstevel@tonic-gate 1180*7c478bd9Sstevel@tonic-gate if (NULL == data.dptr) { 1181*7c478bd9Sstevel@tonic-gate /* OK just have no shadow info in DIT */ 1182*7c478bd9Sstevel@tonic-gate return (NULL); 1183*7c478bd9Sstevel@tonic-gate } 1184*7c478bd9Sstevel@tonic-gate 1185*7c478bd9Sstevel@tonic-gate /* Pull shadow apart */ 1186*7c478bd9Sstevel@tonic-gate if (NULL == (sp = am(myself, sizeof (struct spwd)))) { 1187*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, 1188*7c478bd9Sstevel@tonic-gate "Could not alloc for shadow decode"); 1189*7c478bd9Sstevel@tonic-gate sfree(data.dptr); 1190*7c478bd9Sstevel@tonic-gate return (NULL); 1191*7c478bd9Sstevel@tonic-gate } 1192*7c478bd9Sstevel@tonic-gate sp->sp_namp = NULL; 1193*7c478bd9Sstevel@tonic-gate sp->sp_pwdp = NULL; 1194*7c478bd9Sstevel@tonic-gate 1195*7c478bd9Sstevel@tonic-gate res = decode_shadow_entry(&data, sp); 1196*7c478bd9Sstevel@tonic-gate sfree(data.dptr); 1197*7c478bd9Sstevel@tonic-gate if (SUCCESS != res) { 1198*7c478bd9Sstevel@tonic-gate free_shadow_entry(sp); 1199*7c478bd9Sstevel@tonic-gate return (NULL); 1200*7c478bd9Sstevel@tonic-gate } 1201*7c478bd9Sstevel@tonic-gate 1202*7c478bd9Sstevel@tonic-gate return (sp); 1203*7c478bd9Sstevel@tonic-gate } 1204*7c478bd9Sstevel@tonic-gate 1205*7c478bd9Sstevel@tonic-gate /* 1206*7c478bd9Sstevel@tonic-gate * FUNCTION : decode_shadow_entry() 1207*7c478bd9Sstevel@tonic-gate * 1208*7c478bd9Sstevel@tonic-gate * DESCRIPTION: Pulls apart ageing information. For convenience this is stored 1209*7c478bd9Sstevel@tonic-gate * in a partially filled spwd structure. 1210*7c478bd9Sstevel@tonic-gate * 1211*7c478bd9Sstevel@tonic-gate * SEE COMMENTS FOR decode_pwd_entry() 1212*7c478bd9Sstevel@tonic-gate */ 1213*7c478bd9Sstevel@tonic-gate suc_code 1214*7c478bd9Sstevel@tonic-gate decode_shadow_entry(datum *data, struct spwd *sp) 1215*7c478bd9Sstevel@tonic-gate { 1216*7c478bd9Sstevel@tonic-gate char *p, *str_end, *temp; 1217*7c478bd9Sstevel@tonic-gate 1218*7c478bd9Sstevel@tonic-gate /* Work out last location in string */ 1219*7c478bd9Sstevel@tonic-gate str_end = data->dptr + data->dsize; 1220*7c478bd9Sstevel@tonic-gate 1221*7c478bd9Sstevel@tonic-gate /* Name */ 1222*7c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(data->dptr, &(sp->sp_namp), str_end))) 1223*7c478bd9Sstevel@tonic-gate return (FAILURE); 1224*7c478bd9Sstevel@tonic-gate 1225*7c478bd9Sstevel@tonic-gate /* date of last change */ 1226*7c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(p, &temp, str_end))) 1227*7c478bd9Sstevel@tonic-gate return (FAILURE); 1228*7c478bd9Sstevel@tonic-gate sp->sp_lstchg = atoi(temp); 1229*7c478bd9Sstevel@tonic-gate 1230*7c478bd9Sstevel@tonic-gate /* min days to passwd change */ 1231*7c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(p, &temp, str_end))) 1232*7c478bd9Sstevel@tonic-gate return (FAILURE); 1233*7c478bd9Sstevel@tonic-gate sp->sp_min = atoi(temp); 1234*7c478bd9Sstevel@tonic-gate 1235*7c478bd9Sstevel@tonic-gate /* max days to passwd change */ 1236*7c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(p, &temp, str_end))) 1237*7c478bd9Sstevel@tonic-gate return (FAILURE); 1238*7c478bd9Sstevel@tonic-gate sp->sp_max = atoi(temp); 1239*7c478bd9Sstevel@tonic-gate 1240*7c478bd9Sstevel@tonic-gate /* warning period */ 1241*7c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(p, &temp, str_end))) 1242*7c478bd9Sstevel@tonic-gate return (FAILURE); 1243*7c478bd9Sstevel@tonic-gate sp->sp_warn = atoi(temp); 1244*7c478bd9Sstevel@tonic-gate 1245*7c478bd9Sstevel@tonic-gate /* max days inactive */ 1246*7c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(p, &temp, str_end))) 1247*7c478bd9Sstevel@tonic-gate return (FAILURE); 1248*7c478bd9Sstevel@tonic-gate sp->sp_inact = atoi(temp); 1249*7c478bd9Sstevel@tonic-gate 1250*7c478bd9Sstevel@tonic-gate /* account expiry date */ 1251*7c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(p, &temp, str_end))) 1252*7c478bd9Sstevel@tonic-gate return (FAILURE); 1253*7c478bd9Sstevel@tonic-gate sp->sp_expire = atoi(temp); 1254*7c478bd9Sstevel@tonic-gate 1255*7c478bd9Sstevel@tonic-gate /* flag */ 1256*7c478bd9Sstevel@tonic-gate if (NULL != (p = get_next_token(p, &temp, str_end))) 1257*7c478bd9Sstevel@tonic-gate return (FAILURE); 1258*7c478bd9Sstevel@tonic-gate sp->sp_flag = atoi(temp); 1259*7c478bd9Sstevel@tonic-gate 1260*7c478bd9Sstevel@tonic-gate return (SUCCESS); 1261*7c478bd9Sstevel@tonic-gate } 1262*7c478bd9Sstevel@tonic-gate 1263*7c478bd9Sstevel@tonic-gate /* 1264*7c478bd9Sstevel@tonic-gate * FUNCTION : write_shadow_info() 1265*7c478bd9Sstevel@tonic-gate * 1266*7c478bd9Sstevel@tonic-gate * DESCRIPTION: Writes shadow information back to the DIT. 1267*7c478bd9Sstevel@tonic-gate * 1268*7c478bd9Sstevel@tonic-gate * INPUTS : Domain 1269*7c478bd9Sstevel@tonic-gate * Information to write 1270*7c478bd9Sstevel@tonic-gate * 1271*7c478bd9Sstevel@tonic-gate * OUTPUT : Success code 1272*7c478bd9Sstevel@tonic-gate * 1273*7c478bd9Sstevel@tonic-gate */ 1274*7c478bd9Sstevel@tonic-gate suc_code 1275*7c478bd9Sstevel@tonic-gate write_shadow_info(char *domain, struct spwd *sp) 1276*7c478bd9Sstevel@tonic-gate { 1277*7c478bd9Sstevel@tonic-gate char *myself = "write_shadow_info"; 1278*7c478bd9Sstevel@tonic-gate datum key, data; 1279*7c478bd9Sstevel@tonic-gate char *str; 1280*7c478bd9Sstevel@tonic-gate suc_code res; 1281*7c478bd9Sstevel@tonic-gate int len; 1282*7c478bd9Sstevel@tonic-gate 1283*7c478bd9Sstevel@tonic-gate /* Work out how long string will be */ 1284*7c478bd9Sstevel@tonic-gate len = strlen(sp->sp_namp) + 1; 1285*7c478bd9Sstevel@tonic-gate 1286*7c478bd9Sstevel@tonic-gate /* 1287*7c478bd9Sstevel@tonic-gate * Bit crude but if we assume 1 byte is 3 decimal characters 1288*7c478bd9Sstevel@tonic-gate * will get enough buffer for the longs and some spare. 1289*7c478bd9Sstevel@tonic-gate */ 1290*7c478bd9Sstevel@tonic-gate len += 7 * (3 * sizeof (long) + 1); 1291*7c478bd9Sstevel@tonic-gate 1292*7c478bd9Sstevel@tonic-gate /* Allocate some memory */ 1293*7c478bd9Sstevel@tonic-gate str = am(myself, len); 1294*7c478bd9Sstevel@tonic-gate if (NULL == str) { 1295*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, "Could not aloc for shadow write"); 1296*7c478bd9Sstevel@tonic-gate return (FAILURE); 1297*7c478bd9Sstevel@tonic-gate } 1298*7c478bd9Sstevel@tonic-gate 1299*7c478bd9Sstevel@tonic-gate /* Build up shadow string */ 1300*7c478bd9Sstevel@tonic-gate sprintf(str, "%s%c%d%c%d%c%d%c%d%c%d%c%d%c%d", 1301*7c478bd9Sstevel@tonic-gate sp->sp_namp, COLON_CHAR, 1302*7c478bd9Sstevel@tonic-gate sp->sp_lstchg, COLON_CHAR, 1303*7c478bd9Sstevel@tonic-gate sp->sp_min, COLON_CHAR, 1304*7c478bd9Sstevel@tonic-gate sp->sp_max, COLON_CHAR, 1305*7c478bd9Sstevel@tonic-gate sp->sp_warn, COLON_CHAR, 1306*7c478bd9Sstevel@tonic-gate sp->sp_inact, COLON_CHAR, 1307*7c478bd9Sstevel@tonic-gate sp->sp_expire, COLON_CHAR, 1308*7c478bd9Sstevel@tonic-gate sp->sp_flag); 1309*7c478bd9Sstevel@tonic-gate 1310*7c478bd9Sstevel@tonic-gate /* Write it */ 1311*7c478bd9Sstevel@tonic-gate data.dptr = str; 1312*7c478bd9Sstevel@tonic-gate data.dsize = strlen(data.dptr); 1313*7c478bd9Sstevel@tonic-gate key.dptr = sp->sp_namp; 1314*7c478bd9Sstevel@tonic-gate key.dsize = strlen(key.dptr); 1315*7c478bd9Sstevel@tonic-gate res = write_to_dit(AGEING_MAPPING, domain, key, data, TRUE, FALSE); 1316*7c478bd9Sstevel@tonic-gate 1317*7c478bd9Sstevel@tonic-gate sfree(str); 1318*7c478bd9Sstevel@tonic-gate return (res); 1319*7c478bd9Sstevel@tonic-gate } 1320*7c478bd9Sstevel@tonic-gate 1321*7c478bd9Sstevel@tonic-gate /* 1322*7c478bd9Sstevel@tonic-gate * FUNCTION : free_shadow_entry() 1323*7c478bd9Sstevel@tonic-gate * 1324*7c478bd9Sstevel@tonic-gate * DESCRIPTION: Frees up a shadow information structure 1325*7c478bd9Sstevel@tonic-gate * 1326*7c478bd9Sstevel@tonic-gate * INPUTS : Structure to free 1327*7c478bd9Sstevel@tonic-gate * 1328*7c478bd9Sstevel@tonic-gate * OUTPUTS : Nothing 1329*7c478bd9Sstevel@tonic-gate */ 1330*7c478bd9Sstevel@tonic-gate void 1331*7c478bd9Sstevel@tonic-gate free_shadow_entry(struct spwd *spwd) 1332*7c478bd9Sstevel@tonic-gate { 1333*7c478bd9Sstevel@tonic-gate if (NULL != spwd->sp_namp) 1334*7c478bd9Sstevel@tonic-gate sfree(spwd->sp_namp); 1335*7c478bd9Sstevel@tonic-gate 1336*7c478bd9Sstevel@tonic-gate if (NULL != spwd->sp_pwdp) 1337*7c478bd9Sstevel@tonic-gate sfree(spwd->sp_pwdp); 1338*7c478bd9Sstevel@tonic-gate 1339*7c478bd9Sstevel@tonic-gate /* No need to free numerics */ 1340*7c478bd9Sstevel@tonic-gate 1341*7c478bd9Sstevel@tonic-gate /* Free up structure */ 1342*7c478bd9Sstevel@tonic-gate sfree(spwd); 1343*7c478bd9Sstevel@tonic-gate } 1344