17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*350f572aSsdussud * Common Development and Distribution License (the "License"). 6*350f572aSsdussud * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*350f572aSsdussud * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * DESCRIPTION: This is the N2L equivalent of changepasswd.c. The traditional 307c478bd9Sstevel@tonic-gate * version modifies the NIS source files and then initiates a 317c478bd9Sstevel@tonic-gate * ypmake to make the maps and push them. 327c478bd9Sstevel@tonic-gate * 337c478bd9Sstevel@tonic-gate * For N2L there are no source files and the policy is that the 347c478bd9Sstevel@tonic-gate * definitive information is that contained in the DIT. Old 357c478bd9Sstevel@tonic-gate * information is read from LDAP. Assuming this authenticates, and 367c478bd9Sstevel@tonic-gate * the change is acceptable, this information is modified and 377c478bd9Sstevel@tonic-gate * written back to LDAP. 387c478bd9Sstevel@tonic-gate * 397c478bd9Sstevel@tonic-gate * Related map entries are then found and updated finally 407c478bd9Sstevel@tonic-gate * yppushes of the changed maps are initiated. Since the 417c478bd9Sstevel@tonic-gate * definitive information has already correctly been updated the 427c478bd9Sstevel@tonic-gate * code is tolerant of some errors during this operation. 437c478bd9Sstevel@tonic-gate * 447c478bd9Sstevel@tonic-gate * What was previously in the maps is irrelevant. 457c478bd9Sstevel@tonic-gate * 467c478bd9Sstevel@tonic-gate * Some less than perfect code (like inline constants for 477c478bd9Sstevel@tonic-gate * return values and a few globals) is retained from the original. 487c478bd9Sstevel@tonic-gate */ 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate #include <sys/types.h> 517c478bd9Sstevel@tonic-gate #include <sys/stat.h> 527c478bd9Sstevel@tonic-gate #include <ctype.h> 537c478bd9Sstevel@tonic-gate #include <unistd.h> 547c478bd9Sstevel@tonic-gate #include <stdlib.h> 557c478bd9Sstevel@tonic-gate #include <string.h> 567c478bd9Sstevel@tonic-gate #include <stdio.h> 577c478bd9Sstevel@tonic-gate #include <errno.h> 587c478bd9Sstevel@tonic-gate #include <syslog.h> 597c478bd9Sstevel@tonic-gate #include <pwd.h> 607c478bd9Sstevel@tonic-gate #include <signal.h> 617c478bd9Sstevel@tonic-gate #include <crypt.h> 627c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 637c478bd9Sstevel@tonic-gate #include <rpcsvc/yppasswd.h> 647c478bd9Sstevel@tonic-gate #include <utmpx.h> 657c478bd9Sstevel@tonic-gate #include <shadow.h> 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate #include <ndbm.h> 687c478bd9Sstevel@tonic-gate /* DO NOT INCLUDE SHIM_HOOKS.H */ 697c478bd9Sstevel@tonic-gate #include "shim.h" 707c478bd9Sstevel@tonic-gate #include "yptol.h" 717c478bd9Sstevel@tonic-gate #include "../ldap_util.h" 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate /* Constants */ 747c478bd9Sstevel@tonic-gate #define CRYPTPWSIZE CRYPT_MAXCIPHERTEXTLEN 757c478bd9Sstevel@tonic-gate #define STRSIZE 100 767c478bd9Sstevel@tonic-gate #define FINGERSIZE (4 * STRSIZE - 4) 777c478bd9Sstevel@tonic-gate #define SHELLSIZE (STRSIZE - 2) 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate #define UTUSERLEN (sizeof (((struct utmpx *)0)->ut_user)) 807c478bd9Sstevel@tonic-gate #define COLON_CHAR ':' 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate /* 837c478bd9Sstevel@tonic-gate * Path to DBM files. This is only required for N2L mode. Traditional mode 847c478bd9Sstevel@tonic-gate * works with the source files and uses the NIS Makefile to generate the maps. 857c478bd9Sstevel@tonic-gate * Seems to be hard coded in the rest of NIS so same is done here. 867c478bd9Sstevel@tonic-gate */ 877c478bd9Sstevel@tonic-gate #define YPDBPATH "/var/yp" 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate /* Names of password and adjunct mappings. Used to access DIT */ 907c478bd9Sstevel@tonic-gate #define BYNAME ".byname" 917c478bd9Sstevel@tonic-gate #define BYUID ".byuid" 927c478bd9Sstevel@tonic-gate #define BYGID ".bygid" 937c478bd9Sstevel@tonic-gate #define PASSWD_MAPPING "passwd" BYNAME 947c478bd9Sstevel@tonic-gate #define PASSWD_ADJUNCT_MAPPING "passwd.adjunct" BYNAME 957c478bd9Sstevel@tonic-gate #define AGEING_MAPPING "ageing" BYNAME 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate /* Bitmasks used in list of fields to change */ 987c478bd9Sstevel@tonic-gate #define CNG_PASSWD 0x0001 997c478bd9Sstevel@tonic-gate #define CNG_SH 0x0002 1007c478bd9Sstevel@tonic-gate #define CNG_GECOS 0x0004 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate /* Globals :-( */ 1037c478bd9Sstevel@tonic-gate extern int single, nogecos, noshell, nopw, mflag; 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate /* 1067c478bd9Sstevel@tonic-gate * Structure for containing the information is currently in the DIT. This is 1077c478bd9Sstevel@tonic-gate * similar to the passwd structure defined in getpwent(3C) apart from. 1087c478bd9Sstevel@tonic-gate * 1097c478bd9Sstevel@tonic-gate * 1. Since GID and UID are never changed they are not converted to integers. 1107c478bd9Sstevel@tonic-gate * 2. There are extra fields to hold adjunct information. 1117c478bd9Sstevel@tonic-gate * 3. There are extra fields to hold widely used information. 1127c478bd9Sstevel@tonic-gate */ 1137c478bd9Sstevel@tonic-gate struct passwd_entry { 1147c478bd9Sstevel@tonic-gate char *pw_name; 1157c478bd9Sstevel@tonic-gate char *pw_passwd; 1167c478bd9Sstevel@tonic-gate char *pw_uid; 1177c478bd9Sstevel@tonic-gate char *pw_gid; 1187c478bd9Sstevel@tonic-gate char *pw_gecos; 1197c478bd9Sstevel@tonic-gate char *pw_dir; 1207c478bd9Sstevel@tonic-gate char *pw_shell; 1217c478bd9Sstevel@tonic-gate char *adjunct_tail; /* Tail of adjunct entry (opaque) */ 1227c478bd9Sstevel@tonic-gate bool_t adjunct; /* Flag indicating if DIT has adjunct info */ 1237c478bd9Sstevel@tonic-gate char *pwd_str; /* New password string */ 1247c478bd9Sstevel@tonic-gate char *adjunct_str; /* New adjunct string */ 1257c478bd9Sstevel@tonic-gate }; 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate /* Prototypes */ 1287c478bd9Sstevel@tonic-gate extern bool_t validloginshell(char *sh, char *arg, int); 1297c478bd9Sstevel@tonic-gate extern int validstr(char *str, size_t size); 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate suc_code write_shadow_info(char *, struct spwd *); 1327c478bd9Sstevel@tonic-gate int put_new_info(struct passwd_entry *, char *); 1337c478bd9Sstevel@tonic-gate char *create_pwd_str(struct passwd_entry *, bool_t); 1347c478bd9Sstevel@tonic-gate int proc_domain(struct yppasswd *, bool_t, char *); 1357c478bd9Sstevel@tonic-gate int proc_request(struct yppasswd *, struct passwd_entry *, bool_t, char *); 1367c478bd9Sstevel@tonic-gate int modify_ent(struct yppasswd *, struct passwd_entry *t, bool_t, char *); 1377c478bd9Sstevel@tonic-gate int get_change_list(struct yppasswd *, struct passwd_entry *); 1387c478bd9Sstevel@tonic-gate struct passwd_entry *get_old_info(char *, char *); 1397c478bd9Sstevel@tonic-gate static char *get_next_token(char *, char **, char *); 1407c478bd9Sstevel@tonic-gate void free_pwd_entry(struct passwd_entry *); 1417c478bd9Sstevel@tonic-gate struct spwd *get_old_shadow(char *, char *); 1427c478bd9Sstevel@tonic-gate suc_code decode_shadow_entry(datum *, struct spwd *); 1437c478bd9Sstevel@tonic-gate void free_shadow_entry(struct spwd *); 1447c478bd9Sstevel@tonic-gate int proc_maps(char *, struct passwd_entry *); 1457c478bd9Sstevel@tonic-gate int proc_map_list(char **, char *, struct passwd_entry *, bool_t); 1467c478bd9Sstevel@tonic-gate int update_single_map(char *, struct passwd_entry *, bool_t); 1477c478bd9Sstevel@tonic-gate bool_t strend(char *s1, char *s2); 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate /* 1507c478bd9Sstevel@tonic-gate * FUNCTION: shim_changepasswd() 1517c478bd9Sstevel@tonic-gate * 1527c478bd9Sstevel@tonic-gate * DESCRIPTION: N2L version of changepasswd(). When this is called 'useshadow' 1537c478bd9Sstevel@tonic-gate * etc. will have been set up but are meaningless. We work out 1547c478bd9Sstevel@tonic-gate * what to change based on information from the DIT. 1557c478bd9Sstevel@tonic-gate * 1567c478bd9Sstevel@tonic-gate * INPUTS: Identical to changepasswd() 1577c478bd9Sstevel@tonic-gate * 1587c478bd9Sstevel@tonic-gate * OUTPUTS: Identical to changepasswd() 1597c478bd9Sstevel@tonic-gate */ 1607c478bd9Sstevel@tonic-gate void 1617c478bd9Sstevel@tonic-gate shim_changepasswd(SVCXPRT *transp) 1627c478bd9Sstevel@tonic-gate { 1637c478bd9Sstevel@tonic-gate struct yppasswd yppwd; 1647c478bd9Sstevel@tonic-gate bool_t root_on_master = FALSE; 1657c478bd9Sstevel@tonic-gate char domain[MAXNETNAMELEN+1]; 1667c478bd9Sstevel@tonic-gate char **domain_list; 1677c478bd9Sstevel@tonic-gate int dom_count, i; 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate int ret, ans = 2; /* Answer codes */ 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate /* Clean out yppwd ... maybe we don't trust RPC */ 1727c478bd9Sstevel@tonic-gate memset(&yppwd, 0, sizeof (struct yppasswd)); 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate /* Get the RPC args */ 1757c478bd9Sstevel@tonic-gate if (!svc_getargs(transp, xdr_yppasswd, (caddr_t)&yppwd)) { 1767c478bd9Sstevel@tonic-gate svcerr_decode(transp); 1777c478bd9Sstevel@tonic-gate return; 1787c478bd9Sstevel@tonic-gate } 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate /* Perform basic validation */ 1817c478bd9Sstevel@tonic-gate if ((!validstr(yppwd.newpw.pw_passwd, CRYPTPWSIZE)) || 1827c478bd9Sstevel@tonic-gate (!validstr(yppwd.newpw.pw_name, UTUSERLEN)) || 1837c478bd9Sstevel@tonic-gate (!validstr(yppwd.newpw.pw_gecos, FINGERSIZE)) || 1847c478bd9Sstevel@tonic-gate (!validstr(yppwd.newpw.pw_shell, SHELLSIZE))) { 1857c478bd9Sstevel@tonic-gate svcerr_decode(transp); 1867c478bd9Sstevel@tonic-gate return; 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate /* 1907c478bd9Sstevel@tonic-gate * Special case: root on the master server can change other 1917c478bd9Sstevel@tonic-gate * users' passwords without first entering the old password. 1927c478bd9Sstevel@tonic-gate * We need to ensure that this is indeed root on the master 1937c478bd9Sstevel@tonic-gate * server. (bug 1253949) 1947c478bd9Sstevel@tonic-gate */ 1957c478bd9Sstevel@tonic-gate if (strcmp(transp->xp_netid, "ticlts") == 0) { 1967c478bd9Sstevel@tonic-gate svc_local_cred_t cred; 1977c478bd9Sstevel@tonic-gate if (!svc_get_local_cred(transp, &cred)) { 1987c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 1997c478bd9Sstevel@tonic-gate "Couldn't get local user credentials"); 2007c478bd9Sstevel@tonic-gate } else if (cred.ruid == 0) 2017c478bd9Sstevel@tonic-gate root_on_master = TRUE; 2027c478bd9Sstevel@tonic-gate } 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate /* 2057c478bd9Sstevel@tonic-gate * Get the domain name. This is tricky because a N2L server may be 2067c478bd9Sstevel@tonic-gate * handling multiple domains. There is nothing in the request to 2077c478bd9Sstevel@tonic-gate * indicate which one we are trying to change a passwd for. First 2087c478bd9Sstevel@tonic-gate * we try to get a list of password related domains from the mapping 2097c478bd9Sstevel@tonic-gate * file. 2107c478bd9Sstevel@tonic-gate */ 211*350f572aSsdussud if (0 != 212*350f572aSsdussud (dom_count = get_mapping_yppasswdd_domain_list(&domain_list))) { 2137c478bd9Sstevel@tonic-gate /* Got a domain list ... process all the domains */ 2147c478bd9Sstevel@tonic-gate for (i = 0; i < dom_count; i ++) { 2157c478bd9Sstevel@tonic-gate ret = proc_domain(&yppwd, root_on_master, 2167c478bd9Sstevel@tonic-gate domain_list[i]); 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate /* If one has worked don't care if others fail */ 2197c478bd9Sstevel@tonic-gate if (0 != ans) 2207c478bd9Sstevel@tonic-gate ans = ret; 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate } 2237c478bd9Sstevel@tonic-gate else 2247c478bd9Sstevel@tonic-gate { 2257c478bd9Sstevel@tonic-gate /* 2267c478bd9Sstevel@tonic-gate * There was no domain list in the mapping file. The 2277c478bd9Sstevel@tonic-gate * traditional version of this code calls ypmake which picks 2287c478bd9Sstevel@tonic-gate * up the domain returned by getdomainname(). Fall back to the 2297c478bd9Sstevel@tonic-gate * same mechanism. 2307c478bd9Sstevel@tonic-gate */ 2317c478bd9Sstevel@tonic-gate if (0 > getdomainname(domain, MAXNETNAMELEN+1)) { 2327c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 2337c478bd9Sstevel@tonic-gate "Could not get any domain info"); 2347c478bd9Sstevel@tonic-gate } else { 2357c478bd9Sstevel@tonic-gate /* Got one domain ... process it. */ 2367c478bd9Sstevel@tonic-gate ans = proc_domain(&yppwd, root_on_master, domain); 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate /* Send reply packet */ 2417c478bd9Sstevel@tonic-gate if (!svc_sendreply(transp, xdr_int, (char *)&ans)) 2427c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 2437c478bd9Sstevel@tonic-gate "could not reply to RPC call"); 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate /* 2477c478bd9Sstevel@tonic-gate * FUNCTION : proc_domain() 2487c478bd9Sstevel@tonic-gate * 2497c478bd9Sstevel@tonic-gate * DESCRIPTION: Process a request for one domain 2507c478bd9Sstevel@tonic-gate * 2517c478bd9Sstevel@tonic-gate * GIVEN : Pointer to the request. 2527c478bd9Sstevel@tonic-gate * Root on master flag 2537c478bd9Sstevel@tonic-gate * Domain 2547c478bd9Sstevel@tonic-gate * 2557c478bd9Sstevel@tonic-gate * OUTPUTS : Answer code for reply 2567c478bd9Sstevel@tonic-gate */ 2577c478bd9Sstevel@tonic-gate int 2587c478bd9Sstevel@tonic-gate proc_domain(struct yppasswd *yppwd, bool_t root_on_master, char *domain) 2597c478bd9Sstevel@tonic-gate { 2607c478bd9Sstevel@tonic-gate struct passwd_entry *old_pwd; 2617c478bd9Sstevel@tonic-gate char *p; 2627c478bd9Sstevel@tonic-gate int ans = 2; 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate /* security hole fix from original source */ 2657c478bd9Sstevel@tonic-gate for (p = yppwd->newpw.pw_name; (*p != '\0'); p++) 2667c478bd9Sstevel@tonic-gate if ((*p == ':') || !(isprint(*p))) 2677c478bd9Sstevel@tonic-gate *p = '$'; /* you lose buckwheat */ 2687c478bd9Sstevel@tonic-gate for (p = yppwd->newpw.pw_passwd; (*p != '\0'); p++) 2697c478bd9Sstevel@tonic-gate if ((*p == ':') || !(isprint(*p))) 2707c478bd9Sstevel@tonic-gate *p = '$'; /* you lose buckwheat */ 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate /* Get old info from DIT for this domain */ 2737c478bd9Sstevel@tonic-gate old_pwd = get_old_info(yppwd->newpw.pw_name, domain); 2747c478bd9Sstevel@tonic-gate if (NULL == old_pwd) { 2757c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 2767c478bd9Sstevel@tonic-gate "Could not get old information for %s in " 2777c478bd9Sstevel@tonic-gate "domain %s", yppwd->newpw.pw_name, domain); 2787c478bd9Sstevel@tonic-gate return (ans); 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate /* Have a request that can be replied to */ 2827c478bd9Sstevel@tonic-gate ans = proc_request(yppwd, old_pwd, root_on_master, domain); 2837c478bd9Sstevel@tonic-gate free_pwd_entry(old_pwd); 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate return (ans); 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate /* 2897c478bd9Sstevel@tonic-gate * FUNCTION : proc_request() 2907c478bd9Sstevel@tonic-gate * 2917c478bd9Sstevel@tonic-gate * DESCRIPTION: Process a request 2927c478bd9Sstevel@tonic-gate * 2937c478bd9Sstevel@tonic-gate * GIVEN : Pointer to the request. 2947c478bd9Sstevel@tonic-gate * Pointer to old information from LDAP 2957c478bd9Sstevel@tonic-gate * Root on master flag 2967c478bd9Sstevel@tonic-gate * Domain 2977c478bd9Sstevel@tonic-gate * 2987c478bd9Sstevel@tonic-gate * OUTPUTS : Answer code for reply 2997c478bd9Sstevel@tonic-gate */ 3007c478bd9Sstevel@tonic-gate int 3017c478bd9Sstevel@tonic-gate proc_request(struct yppasswd *yppwd, struct passwd_entry *old_pwd, 3027c478bd9Sstevel@tonic-gate bool_t root_on_master, char *domain) 3037c478bd9Sstevel@tonic-gate { 3047c478bd9Sstevel@tonic-gate struct sigaction sa, osa1, osa2, osa3; 3057c478bd9Sstevel@tonic-gate int ans; 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate /* Authenticate */ 3087c478bd9Sstevel@tonic-gate if ((0 != strcmp(crypt(yppwd->oldpass, old_pwd->pw_passwd), 3097c478bd9Sstevel@tonic-gate old_pwd->pw_passwd)) && !root_on_master) { 3107c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_NOTICE, "Passwd incorrect %s", 3117c478bd9Sstevel@tonic-gate yppwd->newpw.pw_name); 3127c478bd9Sstevel@tonic-gate return (7); 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate /* Work out what we have to change and change it */ 3167c478bd9Sstevel@tonic-gate ans = modify_ent(yppwd, old_pwd, root_on_master, domain); 3177c478bd9Sstevel@tonic-gate if (0 != ans) 3187c478bd9Sstevel@tonic-gate return (ans); 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate /* 3217c478bd9Sstevel@tonic-gate * Generate passwd and adjunct map entries. This creates extra 3227c478bd9Sstevel@tonic-gate * malloced strings in old_pwd. These will be freed when 3237c478bd9Sstevel@tonic-gate * free_pwd_entry() is called to free up the rest of the structure. 3247c478bd9Sstevel@tonic-gate */ 3257c478bd9Sstevel@tonic-gate old_pwd->pwd_str = create_pwd_str(old_pwd, FALSE); 3267c478bd9Sstevel@tonic-gate if (NULL == old_pwd->pwd_str) { 3277c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 3287c478bd9Sstevel@tonic-gate "Could not create passwd entry"); 3297c478bd9Sstevel@tonic-gate return (2); 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate if (old_pwd->adjunct) { 3327c478bd9Sstevel@tonic-gate old_pwd->adjunct_str = create_pwd_str(old_pwd, TRUE); 3337c478bd9Sstevel@tonic-gate if (NULL == old_pwd->adjunct_str) { 3347c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 3357c478bd9Sstevel@tonic-gate "Could not create adjunct entry"); 3367c478bd9Sstevel@tonic-gate return (2); 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate } else { 3397c478bd9Sstevel@tonic-gate old_pwd->adjunct_str = NULL; 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate /* Put the information back to DIT */ 3437c478bd9Sstevel@tonic-gate ans = put_new_info(old_pwd, domain); 3447c478bd9Sstevel@tonic-gate if (0 != ans) { 3457c478bd9Sstevel@tonic-gate return (ans); 3467c478bd9Sstevel@tonic-gate } 3477c478bd9Sstevel@tonic-gate 3487c478bd9Sstevel@tonic-gate /* Are going to be forking pushes, set up signals */ 3497c478bd9Sstevel@tonic-gate memset(&sa, 0, sizeof (struct sigaction)); 3507c478bd9Sstevel@tonic-gate sa.sa_handler = SIG_IGN; 3517c478bd9Sstevel@tonic-gate sigaction(SIGTSTP, &sa, (struct sigaction *)0); 3527c478bd9Sstevel@tonic-gate sigaction(SIGHUP, &sa, &osa1); 3537c478bd9Sstevel@tonic-gate sigaction(SIGINT, &sa, &osa2); 3547c478bd9Sstevel@tonic-gate sigaction(SIGQUIT, &sa, &osa3); 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate /* Update and push all the maps */ 3577c478bd9Sstevel@tonic-gate ans = proc_maps(domain, old_pwd); 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate /* Tidy up signals */ 3607c478bd9Sstevel@tonic-gate sigaction(SIGHUP, &osa1, (struct sigaction *)0); 3617c478bd9Sstevel@tonic-gate sigaction(SIGINT, &osa2, (struct sigaction *)0); 3627c478bd9Sstevel@tonic-gate sigaction(SIGQUIT, &osa3, (struct sigaction *)0); 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate return (ans); 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate /* 3687c478bd9Sstevel@tonic-gate * FUNCTION: proc_maps() 3697c478bd9Sstevel@tonic-gate * 3707c478bd9Sstevel@tonic-gate * DESCRIPTION: Gets all the map lists and processes them. 3717c478bd9Sstevel@tonic-gate * 3727c478bd9Sstevel@tonic-gate * INPUTS: Domain name 3737c478bd9Sstevel@tonic-gate * New info to write into maps 3747c478bd9Sstevel@tonic-gate * 3757c478bd9Sstevel@tonic-gate * OUTPUT : Answer code 3767c478bd9Sstevel@tonic-gate */ 3777c478bd9Sstevel@tonic-gate int 3787c478bd9Sstevel@tonic-gate proc_maps(char *domain, struct passwd_entry *pwd) 3797c478bd9Sstevel@tonic-gate { 3807c478bd9Sstevel@tonic-gate char **map_list; /* Array of passwd or adjunct maps */ 3817c478bd9Sstevel@tonic-gate int ans = 0; 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate /* Get list of passwd maps from mapping file */ 3847c478bd9Sstevel@tonic-gate map_list = get_passwd_list(FALSE, domain); 3857c478bd9Sstevel@tonic-gate if (map_list != NULL) { 3867c478bd9Sstevel@tonic-gate /* Process list of passwd maps */ 3877c478bd9Sstevel@tonic-gate ans = proc_map_list(map_list, domain, pwd, FALSE); 3887c478bd9Sstevel@tonic-gate free_passwd_list(map_list); 3897c478bd9Sstevel@tonic-gate if (0 != ans) 3907c478bd9Sstevel@tonic-gate return (ans); 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate /* 3947c478bd9Sstevel@tonic-gate * If we get here either there were no passwd maps or there were 3957c478bd9Sstevel@tonic-gate * some and they were processed successfully. Either case is good 3967c478bd9Sstevel@tonic-gate * continue and process passwd.adjunct maps. 3977c478bd9Sstevel@tonic-gate */ 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate /* Get list of adjunct maps from mapping file */ 4007c478bd9Sstevel@tonic-gate map_list = get_passwd_list(TRUE, domain); 4017c478bd9Sstevel@tonic-gate if (map_list != NULL) { 4027c478bd9Sstevel@tonic-gate /* 4037c478bd9Sstevel@tonic-gate * Process list of adjunct maps. If the required information 4047c478bd9Sstevel@tonic-gate * is not present in LDAP then the updates attempts will log 4057c478bd9Sstevel@tonic-gate * an error. No need to make the check here 4067c478bd9Sstevel@tonic-gate */ 4077c478bd9Sstevel@tonic-gate ans = proc_map_list(map_list, domain, pwd, TRUE); 4087c478bd9Sstevel@tonic-gate free_passwd_list(map_list); 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate return (ans); 4127c478bd9Sstevel@tonic-gate } 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate /* 4157c478bd9Sstevel@tonic-gate * FUNCTION: proc_map_list() 4167c478bd9Sstevel@tonic-gate * 4177c478bd9Sstevel@tonic-gate * DESCRIPTION: Finds entries in one list of map that need to be updated. 4187c478bd9Sstevel@tonic-gate * updates them and writes them back. 4197c478bd9Sstevel@tonic-gate * 4207c478bd9Sstevel@tonic-gate * INPUTS: Null terminated list of maps to process. 4217c478bd9Sstevel@tonic-gate * Domain name 4227c478bd9Sstevel@tonic-gate * Information to write (including user name) 4237c478bd9Sstevel@tonic-gate * Flag indicating if this is the adjunct list 4247c478bd9Sstevel@tonic-gate * 4257c478bd9Sstevel@tonic-gate * OUTPUTS: An error code 4267c478bd9Sstevel@tonic-gate */ 4277c478bd9Sstevel@tonic-gate int 4287c478bd9Sstevel@tonic-gate proc_map_list(char **map_list, char *domain, 4297c478bd9Sstevel@tonic-gate struct passwd_entry *pwd, bool_t adjunct_flag) 4307c478bd9Sstevel@tonic-gate { 4317c478bd9Sstevel@tonic-gate char *myself = "proc_map_list"; 4327c478bd9Sstevel@tonic-gate char *map_name; 4337c478bd9Sstevel@tonic-gate char cmdbuf[BUFSIZ]; 4347c478bd9Sstevel@tonic-gate int map_name_len = 0; 4357c478bd9Sstevel@tonic-gate int index, ans = 0; 4367c478bd9Sstevel@tonic-gate int res; 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate /* If this is a adjunct list check LDAP had some adjunct info */ 4397c478bd9Sstevel@tonic-gate if ((adjunct_flag) && (!pwd->adjunct)) { 4407c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 4417c478bd9Sstevel@tonic-gate "Have adjunct map list but no adjunct data in DIT"); 4427c478bd9Sstevel@tonic-gate /* Not a disaster */ 4437c478bd9Sstevel@tonic-gate return (0); 4447c478bd9Sstevel@tonic-gate } 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate /* Allocate enough buffer to take longest map name */ 4477c478bd9Sstevel@tonic-gate for (index = 0; map_list[index] != NULL; index ++) 4487c478bd9Sstevel@tonic-gate if (map_name_len < strlen(map_list[index])) 4497c478bd9Sstevel@tonic-gate map_name_len = strlen(map_list[index]); 4507c478bd9Sstevel@tonic-gate map_name_len += strlen(YPDBPATH); 4517c478bd9Sstevel@tonic-gate map_name_len += strlen(NTOL_PREFIX); 4527c478bd9Sstevel@tonic-gate map_name_len += strlen(domain); 4537c478bd9Sstevel@tonic-gate map_name_len += 3; 4547c478bd9Sstevel@tonic-gate if (NULL == (map_name = am(myself, map_name_len))) { 4557c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, "Could not alloc map name"); 4567c478bd9Sstevel@tonic-gate return (2); 4577c478bd9Sstevel@tonic-gate } 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate /* For all maps in list */ 4607c478bd9Sstevel@tonic-gate for (index = 0; map_list[index] != NULL; index ++) { 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate /* Generate full map name */ 4637c478bd9Sstevel@tonic-gate strcpy(map_name, YPDBPATH); 4647c478bd9Sstevel@tonic-gate add_separator(map_name); 4657c478bd9Sstevel@tonic-gate strcat(map_name, domain); 4667c478bd9Sstevel@tonic-gate add_separator(map_name); 4677c478bd9Sstevel@tonic-gate strcat(map_name, NTOL_PREFIX); 4687c478bd9Sstevel@tonic-gate strcat(map_name, map_list[index]); 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate if (0 != (ans = update_single_map(map_name, pwd, adjunct_flag))) 4717c478bd9Sstevel@tonic-gate break; 4727c478bd9Sstevel@tonic-gate } 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate /* Done with full map path */ 4757c478bd9Sstevel@tonic-gate sfree(map_name); 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate /* 4787c478bd9Sstevel@tonic-gate * If (ans != 0) then one more maps have failed. LDAP has however been 4797c478bd9Sstevel@tonic-gate * updates. This is the definitive source for information there is no 4807c478bd9Sstevel@tonic-gate * need to unwind. (This was probably due to maps that were already 4817c478bd9Sstevel@tonic-gate * corrupt). 4827c478bd9Sstevel@tonic-gate */ 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate /* 4857c478bd9Sstevel@tonic-gate * If it all worked fork off push operations for the maps. Since we 4867c478bd9Sstevel@tonic-gate * want the map to end up with it's traditional name on the slave send 4877c478bd9Sstevel@tonic-gate * the name without its LDAP_ prefix. The slave will call ypxfrd 4887c478bd9Sstevel@tonic-gate * which, since it is running in N2L mode, will put the prefix back on 4897c478bd9Sstevel@tonic-gate * before reading the file. 4907c478bd9Sstevel@tonic-gate */ 4917c478bd9Sstevel@tonic-gate if (mflag && (0 == ans)) { 4927c478bd9Sstevel@tonic-gate for (index = 0; (map_name = map_list[index]) != NULL; 4937c478bd9Sstevel@tonic-gate index ++) { 4947c478bd9Sstevel@tonic-gate if (fork() == 0) { 4957c478bd9Sstevel@tonic-gate /* 4967c478bd9Sstevel@tonic-gate * Define full path to yppush. Probably also 4977c478bd9Sstevel@tonic-gate * best for security. 4987c478bd9Sstevel@tonic-gate */ 4997c478bd9Sstevel@tonic-gate strcpy(cmdbuf, "/usr/lib/netsvc/yp/yppush "); 5007c478bd9Sstevel@tonic-gate strcat(cmdbuf, map_name); 5017c478bd9Sstevel@tonic-gate if (0 > system(cmdbuf)) 5027c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 5037c478bd9Sstevel@tonic-gate "Could not initiate yppush"); 5047c478bd9Sstevel@tonic-gate exit(0); 5057c478bd9Sstevel@tonic-gate } 5067c478bd9Sstevel@tonic-gate } 5077c478bd9Sstevel@tonic-gate } 5087c478bd9Sstevel@tonic-gate return (ans); 5097c478bd9Sstevel@tonic-gate } 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate /* 5127c478bd9Sstevel@tonic-gate * FUNCTION : update_single_map() 5137c478bd9Sstevel@tonic-gate * 5147c478bd9Sstevel@tonic-gate * DESCRIPTION: Updates one map. This is messy because we want to lock the map 5157c478bd9Sstevel@tonic-gate * to prevent other processes from updating it at the same time. 5167c478bd9Sstevel@tonic-gate * This mandates that we open it using the shim. When we 5177c478bd9Sstevel@tonic-gate * write to it however we DO NOT want to write through to LDAP 5187c478bd9Sstevel@tonic-gate * i.e. do not want to use the shim. 5197c478bd9Sstevel@tonic-gate * 5207c478bd9Sstevel@tonic-gate * Solution : Do not include shim_hooks.h but call the shim 5217c478bd9Sstevel@tonic-gate * versions of dbm_functions explicitly where needed. 5227c478bd9Sstevel@tonic-gate * 5237c478bd9Sstevel@tonic-gate * INPUT : Full name of map 5247c478bd9Sstevel@tonic-gate * Information to write (including user name) 5257c478bd9Sstevel@tonic-gate * Flag indicating if this is an adjunct map. 5267c478bd9Sstevel@tonic-gate * 5277c478bd9Sstevel@tonic-gate * OUTPUT : Answer code 5287c478bd9Sstevel@tonic-gate * 5297c478bd9Sstevel@tonic-gate */ 5307c478bd9Sstevel@tonic-gate int 5317c478bd9Sstevel@tonic-gate update_single_map(char *map_name, struct passwd_entry *pwd, bool_t adjunct_flag) 5327c478bd9Sstevel@tonic-gate { 5337c478bd9Sstevel@tonic-gate DBM *map; 5347c478bd9Sstevel@tonic-gate int res; 5357c478bd9Sstevel@tonic-gate datum data, key; 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate /* Set up data */ 5387c478bd9Sstevel@tonic-gate if (adjunct_flag) 5397c478bd9Sstevel@tonic-gate data.dptr = pwd->adjunct_str; 5407c478bd9Sstevel@tonic-gate else 5417c478bd9Sstevel@tonic-gate data.dptr = pwd->pwd_str; 5427c478bd9Sstevel@tonic-gate data.dsize = strlen(data.dptr); 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate /* Set up key dependent on which type of map this is */ 5457c478bd9Sstevel@tonic-gate key.dptr = NULL; 5467c478bd9Sstevel@tonic-gate if (strend(map_name, BYNAME)) 5477c478bd9Sstevel@tonic-gate key.dptr = pwd->pw_name; 5487c478bd9Sstevel@tonic-gate if (strend(map_name, BYUID)) 5497c478bd9Sstevel@tonic-gate key.dptr = pwd->pw_uid; 5507c478bd9Sstevel@tonic-gate if (strend(map_name, BYGID)) 5517c478bd9Sstevel@tonic-gate key.dptr = pwd->pw_gid; 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate if (NULL == key.dptr) { 5547c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 5557c478bd9Sstevel@tonic-gate "Unrecognized map type %s", map_name); 5567c478bd9Sstevel@tonic-gate return (0); /* Next map */ 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate key.dsize = strlen(key.dptr); 5597c478bd9Sstevel@tonic-gate 5607c478bd9Sstevel@tonic-gate /* Open the map */ 5617c478bd9Sstevel@tonic-gate map = shim_dbm_open(map_name, O_RDWR, 0600); 5627c478bd9Sstevel@tonic-gate if (NULL == map) { 5637c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, "Could not open %s", map_name); 5647c478bd9Sstevel@tonic-gate return (0); /* Next map */ 5657c478bd9Sstevel@tonic-gate } 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate /* Lock map for update. Painful and may block but have to do it */ 5687c478bd9Sstevel@tonic-gate if (SUCCESS != lock_map_update((map_ctrl *)map)) { 5697c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 5707c478bd9Sstevel@tonic-gate "Could not lock map %s for update", map_name); 5717c478bd9Sstevel@tonic-gate shim_dbm_close(map); 5727c478bd9Sstevel@tonic-gate return (2); 5737c478bd9Sstevel@tonic-gate } 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate /* Do the update use simple DBM operation */ 5767c478bd9Sstevel@tonic-gate res = dbm_store(((map_ctrl *)map)->entries, key, data, DBM_REPLACE); 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate /* update entry TTL. If we fail not a problem will just timeout early */ 5797c478bd9Sstevel@tonic-gate update_entry_ttl((map_ctrl *)map, &key, TTL_RAND); 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate /* 5827c478bd9Sstevel@tonic-gate * Map has been modified so update YP_LAST_MODIFIED. In the vanilla 5837c478bd9Sstevel@tonic-gate * NIS case this would have been done by the ypmake done after updating 5847c478bd9Sstevel@tonic-gate * the passwd source file. If this fails not a great problem the map 5857c478bd9Sstevel@tonic-gate */ 5867c478bd9Sstevel@tonic-gate if (FAILURE == update_timestamp(((map_ctrl *)map)->entries)) { 5877c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, "Could not update " 5887c478bd9Sstevel@tonic-gate "YP_LAST_MODIFIED %s will not be pushed this time", 5897c478bd9Sstevel@tonic-gate map_name); 5907c478bd9Sstevel@tonic-gate } 5917c478bd9Sstevel@tonic-gate 5927c478bd9Sstevel@tonic-gate /* 5937c478bd9Sstevel@tonic-gate * Possibly should hold the lock until after push is complete 5947c478bd9Sstevel@tonic-gate * but this could deadlock if client is slow and ypxfrd also 5957c478bd9Sstevel@tonic-gate * decides to do an update. 5967c478bd9Sstevel@tonic-gate */ 5977c478bd9Sstevel@tonic-gate unlock_map_update((map_ctrl *)map); 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate /* Close the map */ 6007c478bd9Sstevel@tonic-gate shim_dbm_close(map); 6017c478bd9Sstevel@tonic-gate 6027c478bd9Sstevel@tonic-gate if (0 != res) { 6037c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 6047c478bd9Sstevel@tonic-gate "Could not update map %s", map_name); 6057c478bd9Sstevel@tonic-gate return (2); 6067c478bd9Sstevel@tonic-gate } 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate return (0); 6097c478bd9Sstevel@tonic-gate } 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate /* 6127c478bd9Sstevel@tonic-gate * FUNCTION : strend() 6137c478bd9Sstevel@tonic-gate * 6147c478bd9Sstevel@tonic-gate * DESCRIPTION: Determines if one string ends with another. 6157c478bd9Sstevel@tonic-gate */ 6167c478bd9Sstevel@tonic-gate bool_t 6177c478bd9Sstevel@tonic-gate strend(char *s1, char *s2) 6187c478bd9Sstevel@tonic-gate { 6197c478bd9Sstevel@tonic-gate int len_dif; 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate len_dif = strlen(s1) - strlen(s2); 6227c478bd9Sstevel@tonic-gate if (0 > len_dif) 6237c478bd9Sstevel@tonic-gate return (FALSE); 6247c478bd9Sstevel@tonic-gate if (0 == strcmp(s1 + len_dif, s2)) 6257c478bd9Sstevel@tonic-gate return (TRUE); 6267c478bd9Sstevel@tonic-gate return (FALSE); 6277c478bd9Sstevel@tonic-gate } 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate /* 6307c478bd9Sstevel@tonic-gate * FUNCTION: modify_ent() 6317c478bd9Sstevel@tonic-gate * 6327c478bd9Sstevel@tonic-gate * DESCRIPTION: Modify an entry to reflect a request. 6337c478bd9Sstevel@tonic-gate * 6347c478bd9Sstevel@tonic-gate * INPUT: Pointer to the request. 6357c478bd9Sstevel@tonic-gate * Pointer to the entry to modify. 6367c478bd9Sstevel@tonic-gate * Flag indication if we are root on master 6377c478bd9Sstevel@tonic-gate * Domain 6387c478bd9Sstevel@tonic-gate * 6397c478bd9Sstevel@tonic-gate * OUTPUT: Error code 6407c478bd9Sstevel@tonic-gate */ 6417c478bd9Sstevel@tonic-gate int 6427c478bd9Sstevel@tonic-gate modify_ent(struct yppasswd *yppwd, struct passwd_entry *old_ent, 6437c478bd9Sstevel@tonic-gate bool_t root_on_master, char *domain) 6447c478bd9Sstevel@tonic-gate { 6457c478bd9Sstevel@tonic-gate int change_list; 6467c478bd9Sstevel@tonic-gate struct spwd *shadow; 6477c478bd9Sstevel@tonic-gate time_t now; 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate /* Get list of changes */ 6507c478bd9Sstevel@tonic-gate change_list = get_change_list(yppwd, old_ent); 6517c478bd9Sstevel@tonic-gate 6527c478bd9Sstevel@tonic-gate if (!change_list) { 6537c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_NOTICE, 6547c478bd9Sstevel@tonic-gate "No change for %s", yppwd->newpw.pw_name); 6557c478bd9Sstevel@tonic-gate return (3); 6567c478bd9Sstevel@tonic-gate } 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate /* Check that the shell we have been given is acceptable. */ 6597c478bd9Sstevel@tonic-gate if ((change_list & CNG_SH) && (!validloginshell(old_ent->pw_shell, 6607c478bd9Sstevel@tonic-gate yppwd->newpw.pw_shell, root_on_master))) 6617c478bd9Sstevel@tonic-gate return (2); 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate /* 6647c478bd9Sstevel@tonic-gate * If changing the password do any aging checks. 6657c478bd9Sstevel@tonic-gate * Since there are no shadow maps this is done by accessing 6667c478bd9Sstevel@tonic-gate * attributes in the DIT via the mapping system. 6677c478bd9Sstevel@tonic-gate */ 6687c478bd9Sstevel@tonic-gate if (change_list & CNG_PASSWD) { 6697c478bd9Sstevel@tonic-gate 6707c478bd9Sstevel@tonic-gate /* Try to get shadow information */ 6717c478bd9Sstevel@tonic-gate shadow = get_old_shadow(yppwd->newpw.pw_name, domain); 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate /* If there is shadow information make password aging checks */ 6747c478bd9Sstevel@tonic-gate if (NULL != shadow) { 6757c478bd9Sstevel@tonic-gate now = DAY_NOW; 6767c478bd9Sstevel@tonic-gate /* password aging - bug for bug compatibility */ 6777c478bd9Sstevel@tonic-gate if (shadow->sp_max != -1) { 6787c478bd9Sstevel@tonic-gate if (now < shadow->sp_lstchg + shadow->sp_min) { 6797c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 6807c478bd9Sstevel@tonic-gate "Sorry: < %ld days since " 6817c478bd9Sstevel@tonic-gate "the last change", shadow->sp_min); 6827c478bd9Sstevel@tonic-gate free_shadow_entry(shadow); 6837c478bd9Sstevel@tonic-gate return (2); 6847c478bd9Sstevel@tonic-gate } 6857c478bd9Sstevel@tonic-gate } 6867c478bd9Sstevel@tonic-gate 6877c478bd9Sstevel@tonic-gate /* Update time of change */ 6887c478bd9Sstevel@tonic-gate shadow->sp_lstchg = now; 6897c478bd9Sstevel@tonic-gate 6907c478bd9Sstevel@tonic-gate /* Write it back */ 6917c478bd9Sstevel@tonic-gate write_shadow_info(domain, shadow); 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate free_shadow_entry(shadow); 6947c478bd9Sstevel@tonic-gate } 6957c478bd9Sstevel@tonic-gate } 6967c478bd9Sstevel@tonic-gate 6977c478bd9Sstevel@tonic-gate /* Make changes to old entity */ 6987c478bd9Sstevel@tonic-gate if (change_list & CNG_GECOS) { 6997c478bd9Sstevel@tonic-gate if (NULL != old_ent->pw_gecos) 7007c478bd9Sstevel@tonic-gate sfree(old_ent->pw_gecos); 7017c478bd9Sstevel@tonic-gate old_ent->pw_gecos = strdup(yppwd->newpw.pw_gecos); 7027c478bd9Sstevel@tonic-gate if (NULL == old_ent->pw_gecos) { 7037c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, "Could not allocate gecos"); 7047c478bd9Sstevel@tonic-gate return (2); 7057c478bd9Sstevel@tonic-gate } 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate if (change_list & CNG_SH) { 7097c478bd9Sstevel@tonic-gate if (NULL != old_ent->pw_shell) 7107c478bd9Sstevel@tonic-gate sfree(old_ent->pw_shell); 7117c478bd9Sstevel@tonic-gate old_ent->pw_shell = strdup(yppwd->newpw.pw_shell); 7127c478bd9Sstevel@tonic-gate if (NULL == old_ent->pw_shell) { 7137c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, "Could not allocate shell"); 7147c478bd9Sstevel@tonic-gate return (2); 7157c478bd9Sstevel@tonic-gate } 7167c478bd9Sstevel@tonic-gate } 7177c478bd9Sstevel@tonic-gate 7187c478bd9Sstevel@tonic-gate if (change_list & CNG_PASSWD) { 7197c478bd9Sstevel@tonic-gate if (NULL != old_ent->pw_passwd) 7207c478bd9Sstevel@tonic-gate sfree(old_ent->pw_passwd); 7217c478bd9Sstevel@tonic-gate old_ent->pw_passwd = strdup(yppwd->newpw.pw_passwd); 7227c478bd9Sstevel@tonic-gate if (NULL == old_ent->pw_passwd) { 7237c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, "Could not allocate passwd"); 7247c478bd9Sstevel@tonic-gate return (2); 7257c478bd9Sstevel@tonic-gate } 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate return (0); 7297c478bd9Sstevel@tonic-gate } 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate /* 7327c478bd9Sstevel@tonic-gate * FUNCTION : get_change_list() 7337c478bd9Sstevel@tonic-gate * 7347c478bd9Sstevel@tonic-gate * DESCRIPTION: Works out what we have to change. 7357c478bd9Sstevel@tonic-gate * 7367c478bd9Sstevel@tonic-gate * INPUTS : Request. 7377c478bd9Sstevel@tonic-gate * Structure containing current state of entry 7387c478bd9Sstevel@tonic-gate * 7397c478bd9Sstevel@tonic-gate * OUTPUTS : A bitmask signaling what to change. (Implemented in this 7407c478bd9Sstevel@tonic-gate * way to make it easy to pass between functions). 7417c478bd9Sstevel@tonic-gate */ 7427c478bd9Sstevel@tonic-gate int 7437c478bd9Sstevel@tonic-gate get_change_list(struct yppasswd *yppwd, struct passwd_entry *old_ent) 7447c478bd9Sstevel@tonic-gate { 7457c478bd9Sstevel@tonic-gate int list = 0; 7467c478bd9Sstevel@tonic-gate char *p; 7477c478bd9Sstevel@tonic-gate 7487c478bd9Sstevel@tonic-gate p = yppwd->newpw.pw_passwd; 7497c478bd9Sstevel@tonic-gate if ((!nopw) && 7507c478bd9Sstevel@tonic-gate p && *p && 7517c478bd9Sstevel@tonic-gate !(*p++ == '#' && *p++ == '#' && 7527c478bd9Sstevel@tonic-gate (strcmp(p, old_ent->pw_name) == 0)) && 7537c478bd9Sstevel@tonic-gate (strcmp(crypt(old_ent->pw_passwd, 7547c478bd9Sstevel@tonic-gate yppwd->newpw.pw_passwd), yppwd->newpw.pw_passwd) != 0)) 7557c478bd9Sstevel@tonic-gate list |= CNG_PASSWD; 7567c478bd9Sstevel@tonic-gate 7577c478bd9Sstevel@tonic-gate if ((NULL != old_ent->pw_shell) && 7587c478bd9Sstevel@tonic-gate (!noshell) && 7597c478bd9Sstevel@tonic-gate (strcmp(old_ent->pw_shell, yppwd->newpw.pw_shell) != 0)) { 7607c478bd9Sstevel@tonic-gate if (single) 7617c478bd9Sstevel@tonic-gate list = 0; 7627c478bd9Sstevel@tonic-gate list |= CNG_SH; 7637c478bd9Sstevel@tonic-gate } 7647c478bd9Sstevel@tonic-gate 7657c478bd9Sstevel@tonic-gate if ((NULL != old_ent->pw_gecos) && 7667c478bd9Sstevel@tonic-gate (!nogecos) && 7677c478bd9Sstevel@tonic-gate (strcmp(old_ent->pw_gecos, yppwd->newpw.pw_gecos) != 0)) { 7687c478bd9Sstevel@tonic-gate if (single) 7697c478bd9Sstevel@tonic-gate list = 0; 7707c478bd9Sstevel@tonic-gate list |= CNG_GECOS; 7717c478bd9Sstevel@tonic-gate } 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate return (list); 7747c478bd9Sstevel@tonic-gate } 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate /* 7777c478bd9Sstevel@tonic-gate * FUNCTION : decode_pwd_entry() 7787c478bd9Sstevel@tonic-gate * 7797c478bd9Sstevel@tonic-gate * DESCRIPTION: Pulls apart a password entry. Because the password entry has 7807c478bd9Sstevel@tonic-gate * come from the mapping system it can be assumed to be correctly 7817c478bd9Sstevel@tonic-gate * formatted and relatively simple parsing can be done. 7827c478bd9Sstevel@tonic-gate * 7837c478bd9Sstevel@tonic-gate * Substrings are put into malloced memory. Caller to free. 7847c478bd9Sstevel@tonic-gate * 7857c478bd9Sstevel@tonic-gate * For adjunct files most of it is left empty. 7867c478bd9Sstevel@tonic-gate * 7877c478bd9Sstevel@tonic-gate * It would be nice to use getpwent and friends for this work but 7887c478bd9Sstevel@tonic-gate * these only seem to exist for files and it seems excessive to 7897c478bd9Sstevel@tonic-gate * create a temporary file for this operation. 7907c478bd9Sstevel@tonic-gate * 7917c478bd9Sstevel@tonic-gate * INPUTS: Pointer to datum containing password string. 7927c478bd9Sstevel@tonic-gate * Pointer to structure in which to return results 7937c478bd9Sstevel@tonic-gate * Flag indicating if we are decoding passwd or passwd.adjunct 7947c478bd9Sstevel@tonic-gate * 7957c478bd9Sstevel@tonic-gate * OUTPUTS: SUCCESS = Decoded successfully 7967c478bd9Sstevel@tonic-gate * FAILURE = Not decoded successfully. Caller to tidy up. 7977c478bd9Sstevel@tonic-gate */ 7987c478bd9Sstevel@tonic-gate suc_code 7997c478bd9Sstevel@tonic-gate decode_pwd_entry(datum *data, struct passwd_entry *pwd, bool_t adjunct) 8007c478bd9Sstevel@tonic-gate { 8017c478bd9Sstevel@tonic-gate char *myself = "decode_pwd_entry"; 8027c478bd9Sstevel@tonic-gate char *p, *str_end, *temp; 8037c478bd9Sstevel@tonic-gate 8047c478bd9Sstevel@tonic-gate /* Work out last location in string */ 8057c478bd9Sstevel@tonic-gate str_end = data->dptr + data->dsize; 8067c478bd9Sstevel@tonic-gate 8077c478bd9Sstevel@tonic-gate /* Name */ 8087c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(data->dptr, &temp, str_end))) 8097c478bd9Sstevel@tonic-gate return (FAILURE); 8107c478bd9Sstevel@tonic-gate if (adjunct) { 8117c478bd9Sstevel@tonic-gate /* If we found an adjunct version this is the one to use */ 8127c478bd9Sstevel@tonic-gate if (NULL != pwd->pw_name) 8137c478bd9Sstevel@tonic-gate sfree(pwd->pw_name); 8147c478bd9Sstevel@tonic-gate } 8157c478bd9Sstevel@tonic-gate pwd->pw_name = temp; 8167c478bd9Sstevel@tonic-gate 8177c478bd9Sstevel@tonic-gate /* Password */ 8187c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(p, &temp, str_end))) 8197c478bd9Sstevel@tonic-gate return (FAILURE); 8207c478bd9Sstevel@tonic-gate if (adjunct) { 8217c478bd9Sstevel@tonic-gate /* If we found an adjunct version this is the one to use */ 8227c478bd9Sstevel@tonic-gate if (NULL != pwd->pw_passwd) 8237c478bd9Sstevel@tonic-gate sfree(pwd->pw_passwd); 8247c478bd9Sstevel@tonic-gate } 8257c478bd9Sstevel@tonic-gate pwd->pw_passwd = temp; 8267c478bd9Sstevel@tonic-gate 8277c478bd9Sstevel@tonic-gate if (adjunct) { 8287c478bd9Sstevel@tonic-gate /* Store adjunct information in opaque string */ 8297c478bd9Sstevel@tonic-gate pwd->adjunct_tail = am(myself, str_end - p + 1); 8307c478bd9Sstevel@tonic-gate if (NULL == pwd->adjunct_tail) 8317c478bd9Sstevel@tonic-gate return (FAILURE); 8327c478bd9Sstevel@tonic-gate strncpy(pwd->adjunct_tail, p, str_end - p); 8337c478bd9Sstevel@tonic-gate pwd->adjunct_tail[str_end - p] = '\0'; 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate /* Remember that LDAP contained adjunct data */ 8367c478bd9Sstevel@tonic-gate pwd->adjunct = TRUE; 8377c478bd9Sstevel@tonic-gate return (SUCCESS); 8387c478bd9Sstevel@tonic-gate } 8397c478bd9Sstevel@tonic-gate 8407c478bd9Sstevel@tonic-gate /* If we get here not adjunct. Decode rest of passwd */ 8417c478bd9Sstevel@tonic-gate 8427c478bd9Sstevel@tonic-gate /* UID */ 8437c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(p, &(pwd->pw_uid), str_end))) 8447c478bd9Sstevel@tonic-gate return (FAILURE); 8457c478bd9Sstevel@tonic-gate 8467c478bd9Sstevel@tonic-gate /* GID */ 8477c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(p, &(pwd->pw_gid), str_end))) 8487c478bd9Sstevel@tonic-gate return (FAILURE); 8497c478bd9Sstevel@tonic-gate 8507c478bd9Sstevel@tonic-gate /* Gecos */ 8517c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(p, &(pwd->pw_gecos), str_end))) 8527c478bd9Sstevel@tonic-gate return (FAILURE); 8537c478bd9Sstevel@tonic-gate 8547c478bd9Sstevel@tonic-gate /* Home dir */ 8557c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(p, &(pwd->pw_dir), str_end))) 8567c478bd9Sstevel@tonic-gate return (FAILURE); 8577c478bd9Sstevel@tonic-gate 8587c478bd9Sstevel@tonic-gate /* Shell may not be present so don't check return */ 8597c478bd9Sstevel@tonic-gate get_next_token(p, &(pwd->pw_shell), str_end); 8607c478bd9Sstevel@tonic-gate 8617c478bd9Sstevel@tonic-gate if (NULL == pwd->pw_shell) 8627c478bd9Sstevel@tonic-gate return (FAILURE); 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate return (SUCCESS); 8657c478bd9Sstevel@tonic-gate } 8667c478bd9Sstevel@tonic-gate 8677c478bd9Sstevel@tonic-gate /* 8687c478bd9Sstevel@tonic-gate * FUNCTION : get_next_token() 8697c478bd9Sstevel@tonic-gate * 8707c478bd9Sstevel@tonic-gate * DESCRIPTION: Gets the next token from a string upto the next colon or the 8717c478bd9Sstevel@tonic-gate * end of the string. The duplicates this token into malloced 8727c478bd9Sstevel@tonic-gate * memory removing any spaces. 8737c478bd9Sstevel@tonic-gate * 8747c478bd9Sstevel@tonic-gate * INPUTS : String to search for token. NOT NULL TERMINATED 8757c478bd9Sstevel@tonic-gate * Location to return result (NULL if result not required) 8767c478bd9Sstevel@tonic-gate * Last location in string 8777c478bd9Sstevel@tonic-gate * 8787c478bd9Sstevel@tonic-gate * OUTPUT : Pointer into the string immediately after the token. 8797c478bd9Sstevel@tonic-gate * NULL if end of string reached or error. 8807c478bd9Sstevel@tonic-gate */ 8817c478bd9Sstevel@tonic-gate static char * 8827c478bd9Sstevel@tonic-gate get_next_token(char *str, char **op, char *str_end) 8837c478bd9Sstevel@tonic-gate { 8847c478bd9Sstevel@tonic-gate char *myself = "get_next_token"; 8857c478bd9Sstevel@tonic-gate char *p, *tok_start, *tok_end; 8867c478bd9Sstevel@tonic-gate 8877c478bd9Sstevel@tonic-gate p = str; 8887c478bd9Sstevel@tonic-gate /* Skip leading whitespace */ 8897c478bd9Sstevel@tonic-gate while (' ' == *p) 8907c478bd9Sstevel@tonic-gate p++; 8917c478bd9Sstevel@tonic-gate tok_start = p; 8927c478bd9Sstevel@tonic-gate tok_end = p; 8937c478bd9Sstevel@tonic-gate 8947c478bd9Sstevel@tonic-gate while ((str_end + 1 != p) && (COLON_CHAR != *p)) { 8957c478bd9Sstevel@tonic-gate if (' ' != *p) 8967c478bd9Sstevel@tonic-gate tok_end = p; 8977c478bd9Sstevel@tonic-gate p++; 8987c478bd9Sstevel@tonic-gate } 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate /* Required string is now between start and end */ 9017c478bd9Sstevel@tonic-gate if (NULL != op) { 9027c478bd9Sstevel@tonic-gate *op = am(myself, tok_end - tok_start + 2); 9037c478bd9Sstevel@tonic-gate if (NULL == *op) { 9047c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, 9057c478bd9Sstevel@tonic-gate "Could not alloc memory for token"); 9067c478bd9Sstevel@tonic-gate return (NULL); 9077c478bd9Sstevel@tonic-gate } 9087c478bd9Sstevel@tonic-gate strncpy(*op, tok_start, tok_end - tok_start + 1); 9097c478bd9Sstevel@tonic-gate 9107c478bd9Sstevel@tonic-gate /* Terminate token */ 9117c478bd9Sstevel@tonic-gate (*op)[tok_end - tok_start + 1] = '\0'; 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate } 9147c478bd9Sstevel@tonic-gate 9157c478bd9Sstevel@tonic-gate /* Check if we reached the end of the input string */ 9167c478bd9Sstevel@tonic-gate if ('\0' == *p) 9177c478bd9Sstevel@tonic-gate return (NULL); 9187c478bd9Sstevel@tonic-gate 9197c478bd9Sstevel@tonic-gate /* There is some more */ 9207c478bd9Sstevel@tonic-gate p++; 9217c478bd9Sstevel@tonic-gate return (p); 9227c478bd9Sstevel@tonic-gate } 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate /* 9257c478bd9Sstevel@tonic-gate * FUNCTION : free_pwd_entry() 9267c478bd9Sstevel@tonic-gate * 9277c478bd9Sstevel@tonic-gate * DESCRIPTION: Frees up a pwd_entry structure and its contents. 9287c478bd9Sstevel@tonic-gate * 9297c478bd9Sstevel@tonic-gate * INPUTS: Pointer to the structure to free. 9307c478bd9Sstevel@tonic-gate * 9317c478bd9Sstevel@tonic-gate * OUTPUT: Nothing 9327c478bd9Sstevel@tonic-gate */ 9337c478bd9Sstevel@tonic-gate void 9347c478bd9Sstevel@tonic-gate free_pwd_entry(struct passwd_entry *pwd) 9357c478bd9Sstevel@tonic-gate { 9367c478bd9Sstevel@tonic-gate /* Free up strings */ 9377c478bd9Sstevel@tonic-gate if (NULL != pwd->pw_name) 9387c478bd9Sstevel@tonic-gate sfree(pwd->pw_name); 9397c478bd9Sstevel@tonic-gate 9407c478bd9Sstevel@tonic-gate if (NULL != pwd->pw_passwd) 9417c478bd9Sstevel@tonic-gate sfree(pwd->pw_passwd); 9427c478bd9Sstevel@tonic-gate 9437c478bd9Sstevel@tonic-gate if (NULL != pwd->pw_gecos) 9447c478bd9Sstevel@tonic-gate sfree(pwd->pw_gecos); 9457c478bd9Sstevel@tonic-gate 9467c478bd9Sstevel@tonic-gate if (NULL != pwd->pw_shell) 9477c478bd9Sstevel@tonic-gate sfree(pwd->pw_shell); 9487c478bd9Sstevel@tonic-gate 9497c478bd9Sstevel@tonic-gate if (NULL != pwd->pw_dir) 9507c478bd9Sstevel@tonic-gate sfree(pwd->pw_dir); 9517c478bd9Sstevel@tonic-gate 9527c478bd9Sstevel@tonic-gate if (NULL != pwd->adjunct_tail) 9537c478bd9Sstevel@tonic-gate sfree(pwd->adjunct_tail); 9547c478bd9Sstevel@tonic-gate 9557c478bd9Sstevel@tonic-gate if (NULL != pwd->pwd_str) 9567c478bd9Sstevel@tonic-gate sfree(pwd->pwd_str); 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate if (NULL != pwd->adjunct_str) 9597c478bd9Sstevel@tonic-gate sfree(pwd->adjunct_str); 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate /* Free up structure */ 9627c478bd9Sstevel@tonic-gate sfree(pwd); 9637c478bd9Sstevel@tonic-gate } 9647c478bd9Sstevel@tonic-gate 9657c478bd9Sstevel@tonic-gate /* 9667c478bd9Sstevel@tonic-gate * FUNCTION : create_pwd_str() 9677c478bd9Sstevel@tonic-gate * 9687c478bd9Sstevel@tonic-gate * DESCRIPTION: Builds up a new password entity string from a passwd structure. 9697c478bd9Sstevel@tonic-gate * 9707c478bd9Sstevel@tonic-gate * INPUTS : Structure containing password details 9717c478bd9Sstevel@tonic-gate * Flag indicating if we should create an adjunct or passwd string. 9727c478bd9Sstevel@tonic-gate * 9737c478bd9Sstevel@tonic-gate * OUTPUTS : String in malloced memory (to be freed by caller). 9747c478bd9Sstevel@tonic-gate * NULL on failure. 9757c478bd9Sstevel@tonic-gate */ 9767c478bd9Sstevel@tonic-gate char * 9777c478bd9Sstevel@tonic-gate create_pwd_str(struct passwd_entry *pwd, bool_t adjunct) 9787c478bd9Sstevel@tonic-gate { 9797c478bd9Sstevel@tonic-gate char *myself = "create_pwd_str"; 9807c478bd9Sstevel@tonic-gate char *s; 9817c478bd9Sstevel@tonic-gate int len; 9827c478bd9Sstevel@tonic-gate 9837c478bd9Sstevel@tonic-gate /* Separator string so we can strcat separator onto things */ 9847c478bd9Sstevel@tonic-gate char sep_str[2] = {COLON_CHAR, '\0'}; 9857c478bd9Sstevel@tonic-gate 9867c478bd9Sstevel@tonic-gate /* Work out the size */ 9877c478bd9Sstevel@tonic-gate len = strlen(pwd->pw_name) + 1; 9887c478bd9Sstevel@tonic-gate len += strlen(pwd->pw_passwd) + 1; 9897c478bd9Sstevel@tonic-gate if (adjunct) { 9907c478bd9Sstevel@tonic-gate len += strlen(pwd->adjunct_tail) + 1; 9917c478bd9Sstevel@tonic-gate } else { 9927c478bd9Sstevel@tonic-gate len += strlen(pwd->pw_uid) + 1; 9937c478bd9Sstevel@tonic-gate len += strlen(pwd->pw_gid) + 1; 9947c478bd9Sstevel@tonic-gate len += strlen(pwd->pw_gecos) + 1; 9957c478bd9Sstevel@tonic-gate len += strlen(pwd->pw_dir) + 1; 9967c478bd9Sstevel@tonic-gate len += strlen(pwd->pw_shell) + 1; 9977c478bd9Sstevel@tonic-gate } 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate /* Allocate some memory for it */ 10007c478bd9Sstevel@tonic-gate s = am(myself, len); 10017c478bd9Sstevel@tonic-gate if (NULL == s) 10027c478bd9Sstevel@tonic-gate return (NULL); 10037c478bd9Sstevel@tonic-gate 10047c478bd9Sstevel@tonic-gate strcpy(s, pwd->pw_name); 10057c478bd9Sstevel@tonic-gate strcat(s, sep_str); 10067c478bd9Sstevel@tonic-gate if (!adjunct) { 10077c478bd9Sstevel@tonic-gate /* Build up a passwd string */ 10087c478bd9Sstevel@tonic-gate 10097c478bd9Sstevel@tonic-gate /* If LDAP contains adjunct info then passwd is 'x' */ 10107c478bd9Sstevel@tonic-gate if (pwd->adjunct) { 10117c478bd9Sstevel@tonic-gate strcat(s, "##"); 10127c478bd9Sstevel@tonic-gate strcat(s, pwd->pw_name); 10137c478bd9Sstevel@tonic-gate } else { 10147c478bd9Sstevel@tonic-gate strcat(s, pwd->pw_passwd); 10157c478bd9Sstevel@tonic-gate } 10167c478bd9Sstevel@tonic-gate strcat(s, sep_str); 10177c478bd9Sstevel@tonic-gate strcat(s, pwd->pw_uid); 10187c478bd9Sstevel@tonic-gate strcat(s, sep_str); 10197c478bd9Sstevel@tonic-gate strcat(s, pwd->pw_gid); 10207c478bd9Sstevel@tonic-gate strcat(s, sep_str); 10217c478bd9Sstevel@tonic-gate strcat(s, pwd->pw_gecos); 10227c478bd9Sstevel@tonic-gate strcat(s, sep_str); 10237c478bd9Sstevel@tonic-gate strcat(s, pwd->pw_dir); 10247c478bd9Sstevel@tonic-gate strcat(s, sep_str); 10257c478bd9Sstevel@tonic-gate strcat(s, pwd->pw_shell); 10267c478bd9Sstevel@tonic-gate } else { 10277c478bd9Sstevel@tonic-gate /* Build up a passwd_adjunct string */ 10287c478bd9Sstevel@tonic-gate strcat(s, pwd->pw_passwd); 10297c478bd9Sstevel@tonic-gate strcat(s, sep_str); 10307c478bd9Sstevel@tonic-gate strcat(s, pwd->adjunct_tail); 10317c478bd9Sstevel@tonic-gate } 10327c478bd9Sstevel@tonic-gate 10337c478bd9Sstevel@tonic-gate return (s); 10347c478bd9Sstevel@tonic-gate } 10357c478bd9Sstevel@tonic-gate 10367c478bd9Sstevel@tonic-gate /* 10377c478bd9Sstevel@tonic-gate * FUNCTION: get_old_info() 10387c478bd9Sstevel@tonic-gate * 10397c478bd9Sstevel@tonic-gate * DESCRIPTION: Gets as much information as possible from LDAP about one user. 10407c478bd9Sstevel@tonic-gate * 10417c478bd9Sstevel@tonic-gate * This goes through the mapping system. This is messy because 10427c478bd9Sstevel@tonic-gate * them mapping system will build up a password entry from the 10437c478bd9Sstevel@tonic-gate * contents of the DIT. We then have to parse this to recover 10447c478bd9Sstevel@tonic-gate * it's individual fields. 10457c478bd9Sstevel@tonic-gate * 10467c478bd9Sstevel@tonic-gate * INPUT: Pointer to user name 10477c478bd9Sstevel@tonic-gate * Domain 10487c478bd9Sstevel@tonic-gate * 10497c478bd9Sstevel@tonic-gate * OUTPUT: The info in malloced space. To be freed by caller. 10507c478bd9Sstevel@tonic-gate * NULL on failure. 10517c478bd9Sstevel@tonic-gate */ 10527c478bd9Sstevel@tonic-gate struct passwd_entry * 10537c478bd9Sstevel@tonic-gate get_old_info(char *name, char *domain) 10547c478bd9Sstevel@tonic-gate { 10557c478bd9Sstevel@tonic-gate char *myself = "get_old_info"; 10567c478bd9Sstevel@tonic-gate struct passwd_entry *old_passwd; 10577c478bd9Sstevel@tonic-gate char *p; 10587c478bd9Sstevel@tonic-gate datum key, data; 10597c478bd9Sstevel@tonic-gate suc_code res; 10607c478bd9Sstevel@tonic-gate 10617c478bd9Sstevel@tonic-gate /* Get the password entry */ 10627c478bd9Sstevel@tonic-gate key.dptr = name; 10637c478bd9Sstevel@tonic-gate key.dsize = strlen(key.dptr); 10647c478bd9Sstevel@tonic-gate read_from_dit(PASSWD_MAPPING, domain, &key, &data); 10657c478bd9Sstevel@tonic-gate if (NULL == data.dptr) { 10667c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 10677c478bd9Sstevel@tonic-gate "Could not read old pwd for %s", name); 10687c478bd9Sstevel@tonic-gate return (NULL); 10697c478bd9Sstevel@tonic-gate } 10707c478bd9Sstevel@tonic-gate 10717c478bd9Sstevel@tonic-gate /* Pull password apart */ 10727c478bd9Sstevel@tonic-gate old_passwd = am(myself, sizeof (struct passwd_entry)); 10737c478bd9Sstevel@tonic-gate if (NULL == old_passwd) { 10747c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, "Could not alloc for pwd decode"); 10757c478bd9Sstevel@tonic-gate sfree(data.dptr); 10767c478bd9Sstevel@tonic-gate return (NULL); 10777c478bd9Sstevel@tonic-gate } 10787c478bd9Sstevel@tonic-gate 10797c478bd9Sstevel@tonic-gate /* No data yet */ 10807c478bd9Sstevel@tonic-gate old_passwd->pw_name = NULL; 10817c478bd9Sstevel@tonic-gate old_passwd->pw_passwd = NULL; 10827c478bd9Sstevel@tonic-gate old_passwd->pw_uid = NULL; 10837c478bd9Sstevel@tonic-gate old_passwd->pw_gid = NULL; 10847c478bd9Sstevel@tonic-gate old_passwd->pw_gecos = NULL; 10857c478bd9Sstevel@tonic-gate old_passwd->pw_dir = NULL; 10867c478bd9Sstevel@tonic-gate old_passwd->pw_shell = NULL; 10877c478bd9Sstevel@tonic-gate old_passwd->adjunct_tail = NULL; 10887c478bd9Sstevel@tonic-gate old_passwd->pwd_str = NULL; 10897c478bd9Sstevel@tonic-gate old_passwd->adjunct_str = NULL; 10907c478bd9Sstevel@tonic-gate old_passwd->adjunct = FALSE; 10917c478bd9Sstevel@tonic-gate 10927c478bd9Sstevel@tonic-gate res = decode_pwd_entry(&data, old_passwd, FALSE); 10937c478bd9Sstevel@tonic-gate sfree(data.dptr); 10947c478bd9Sstevel@tonic-gate if (SUCCESS != res) { 10957c478bd9Sstevel@tonic-gate free_pwd_entry(old_passwd); 10967c478bd9Sstevel@tonic-gate return (NULL); 10977c478bd9Sstevel@tonic-gate } 10987c478bd9Sstevel@tonic-gate 10997c478bd9Sstevel@tonic-gate /* Try to get the adjunct entry */ 11007c478bd9Sstevel@tonic-gate read_from_dit(PASSWD_ADJUNCT_MAPPING, domain, &key, &data); 11017c478bd9Sstevel@tonic-gate if (NULL == data.dptr) { 11027c478bd9Sstevel@tonic-gate /* Fine just no adjunct data */ 11037c478bd9Sstevel@tonic-gate old_passwd->adjunct = FALSE; 11047c478bd9Sstevel@tonic-gate } else { 11057c478bd9Sstevel@tonic-gate res = decode_pwd_entry(&data, old_passwd, TRUE); 11067c478bd9Sstevel@tonic-gate sfree(data.dptr); 11077c478bd9Sstevel@tonic-gate if (SUCCESS != res) { 11087c478bd9Sstevel@tonic-gate free_pwd_entry(old_passwd); 11097c478bd9Sstevel@tonic-gate return (NULL); 11107c478bd9Sstevel@tonic-gate } 11117c478bd9Sstevel@tonic-gate } 11127c478bd9Sstevel@tonic-gate 11137c478bd9Sstevel@tonic-gate return (old_passwd); 11147c478bd9Sstevel@tonic-gate } 11157c478bd9Sstevel@tonic-gate 11167c478bd9Sstevel@tonic-gate /* 11177c478bd9Sstevel@tonic-gate * FUNCTION : put_new_info() 11187c478bd9Sstevel@tonic-gate * 11197c478bd9Sstevel@tonic-gate * DESCRIPTION: Generates new map strings and puts them back to LDAP 11207c478bd9Sstevel@tonic-gate * 11217c478bd9Sstevel@tonic-gate * INPUTS: Info to put back 11227c478bd9Sstevel@tonic-gate * Domain 11237c478bd9Sstevel@tonic-gate * 11247c478bd9Sstevel@tonic-gate * OUTPUT: Answer code. 11257c478bd9Sstevel@tonic-gate */ 11267c478bd9Sstevel@tonic-gate int 11277c478bd9Sstevel@tonic-gate put_new_info(struct passwd_entry *pwd, char *domain) 11287c478bd9Sstevel@tonic-gate { 11297c478bd9Sstevel@tonic-gate datum key, data; 11307c478bd9Sstevel@tonic-gate 11317c478bd9Sstevel@tonic-gate /* Write it back to LDAP */ 11327c478bd9Sstevel@tonic-gate data.dptr = pwd->pwd_str; 11337c478bd9Sstevel@tonic-gate data.dsize = strlen(data.dptr); 11347c478bd9Sstevel@tonic-gate key.dptr = pwd->pw_name; 11357c478bd9Sstevel@tonic-gate key.dsize = strlen(key.dptr); 11367c478bd9Sstevel@tonic-gate if (SUCCESS != write_to_dit(PASSWD_MAPPING, domain, key, data, 11377c478bd9Sstevel@tonic-gate TRUE, FALSE)) 11387c478bd9Sstevel@tonic-gate return (2); 11397c478bd9Sstevel@tonic-gate 11407c478bd9Sstevel@tonic-gate 11417c478bd9Sstevel@tonic-gate /* If DIT contains adjunct information do the same for adjunct */ 11427c478bd9Sstevel@tonic-gate if (pwd->adjunct) { 11437c478bd9Sstevel@tonic-gate data.dptr = pwd->adjunct_str; 11447c478bd9Sstevel@tonic-gate data.dsize = strlen(data.dptr); 11457c478bd9Sstevel@tonic-gate key.dptr = pwd->pw_name; 11467c478bd9Sstevel@tonic-gate key.dsize = strlen(key.dptr); 11477c478bd9Sstevel@tonic-gate if (SUCCESS != write_to_dit(PASSWD_ADJUNCT_MAPPING, domain, 11487c478bd9Sstevel@tonic-gate key, data, TRUE, FALSE)) 11497c478bd9Sstevel@tonic-gate return (2); 11507c478bd9Sstevel@tonic-gate } 11517c478bd9Sstevel@tonic-gate 11527c478bd9Sstevel@tonic-gate return (0); 11537c478bd9Sstevel@tonic-gate 11547c478bd9Sstevel@tonic-gate } 11557c478bd9Sstevel@tonic-gate 11567c478bd9Sstevel@tonic-gate /* 11577c478bd9Sstevel@tonic-gate * FUNCTION : get_old_shadow() 11587c478bd9Sstevel@tonic-gate * 11597c478bd9Sstevel@tonic-gate * DESCRIPTION :Extracts and decodes shadow information from the DIT 11607c478bd9Sstevel@tonic-gate * See also comments under decode_pwd_entry(). 11617c478bd9Sstevel@tonic-gate * 11627c478bd9Sstevel@tonic-gate * INPUTS : User name 11637c478bd9Sstevel@tonic-gate * Domain name 11647c478bd9Sstevel@tonic-gate * 11657c478bd9Sstevel@tonic-gate * OUTPUT : Shadow information in malloced memory. To be freed by caller. 11667c478bd9Sstevel@tonic-gate */ 11677c478bd9Sstevel@tonic-gate struct spwd * 11687c478bd9Sstevel@tonic-gate get_old_shadow(char *name, char *domain) 11697c478bd9Sstevel@tonic-gate { 11707c478bd9Sstevel@tonic-gate char *myself = "get_old_shadow"; 11717c478bd9Sstevel@tonic-gate struct spwd *sp; 11727c478bd9Sstevel@tonic-gate datum key, data; 11737c478bd9Sstevel@tonic-gate suc_code res; 11747c478bd9Sstevel@tonic-gate 11757c478bd9Sstevel@tonic-gate /* Get the info */ 11767c478bd9Sstevel@tonic-gate key.dptr = name; 11777c478bd9Sstevel@tonic-gate key.dsize = strlen(key.dptr); /* Len excluding terminator */ 11787c478bd9Sstevel@tonic-gate read_from_dit(AGEING_MAPPING, domain, &key, &data); 11797c478bd9Sstevel@tonic-gate 11807c478bd9Sstevel@tonic-gate if (NULL == data.dptr) { 11817c478bd9Sstevel@tonic-gate /* OK just have no shadow info in DIT */ 11827c478bd9Sstevel@tonic-gate return (NULL); 11837c478bd9Sstevel@tonic-gate } 11847c478bd9Sstevel@tonic-gate 11857c478bd9Sstevel@tonic-gate /* Pull shadow apart */ 11867c478bd9Sstevel@tonic-gate if (NULL == (sp = am(myself, sizeof (struct spwd)))) { 11877c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, 11887c478bd9Sstevel@tonic-gate "Could not alloc for shadow decode"); 11897c478bd9Sstevel@tonic-gate sfree(data.dptr); 11907c478bd9Sstevel@tonic-gate return (NULL); 11917c478bd9Sstevel@tonic-gate } 11927c478bd9Sstevel@tonic-gate sp->sp_namp = NULL; 11937c478bd9Sstevel@tonic-gate sp->sp_pwdp = NULL; 11947c478bd9Sstevel@tonic-gate 11957c478bd9Sstevel@tonic-gate res = decode_shadow_entry(&data, sp); 11967c478bd9Sstevel@tonic-gate sfree(data.dptr); 11977c478bd9Sstevel@tonic-gate if (SUCCESS != res) { 11987c478bd9Sstevel@tonic-gate free_shadow_entry(sp); 11997c478bd9Sstevel@tonic-gate return (NULL); 12007c478bd9Sstevel@tonic-gate } 12017c478bd9Sstevel@tonic-gate 12027c478bd9Sstevel@tonic-gate return (sp); 12037c478bd9Sstevel@tonic-gate } 12047c478bd9Sstevel@tonic-gate 12057c478bd9Sstevel@tonic-gate /* 12067c478bd9Sstevel@tonic-gate * FUNCTION : decode_shadow_entry() 12077c478bd9Sstevel@tonic-gate * 12087c478bd9Sstevel@tonic-gate * DESCRIPTION: Pulls apart ageing information. For convenience this is stored 12097c478bd9Sstevel@tonic-gate * in a partially filled spwd structure. 12107c478bd9Sstevel@tonic-gate * 12117c478bd9Sstevel@tonic-gate * SEE COMMENTS FOR decode_pwd_entry() 12127c478bd9Sstevel@tonic-gate */ 12137c478bd9Sstevel@tonic-gate suc_code 12147c478bd9Sstevel@tonic-gate decode_shadow_entry(datum *data, struct spwd *sp) 12157c478bd9Sstevel@tonic-gate { 12167c478bd9Sstevel@tonic-gate char *p, *str_end, *temp; 12177c478bd9Sstevel@tonic-gate 12187c478bd9Sstevel@tonic-gate /* Work out last location in string */ 12197c478bd9Sstevel@tonic-gate str_end = data->dptr + data->dsize; 12207c478bd9Sstevel@tonic-gate 12217c478bd9Sstevel@tonic-gate /* Name */ 12227c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(data->dptr, &(sp->sp_namp), str_end))) 12237c478bd9Sstevel@tonic-gate return (FAILURE); 12247c478bd9Sstevel@tonic-gate 12257c478bd9Sstevel@tonic-gate /* date of last change */ 12267c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(p, &temp, str_end))) 12277c478bd9Sstevel@tonic-gate return (FAILURE); 12287c478bd9Sstevel@tonic-gate sp->sp_lstchg = atoi(temp); 12297c478bd9Sstevel@tonic-gate 12307c478bd9Sstevel@tonic-gate /* min days to passwd change */ 12317c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(p, &temp, str_end))) 12327c478bd9Sstevel@tonic-gate return (FAILURE); 12337c478bd9Sstevel@tonic-gate sp->sp_min = atoi(temp); 12347c478bd9Sstevel@tonic-gate 12357c478bd9Sstevel@tonic-gate /* max days to passwd change */ 12367c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(p, &temp, str_end))) 12377c478bd9Sstevel@tonic-gate return (FAILURE); 12387c478bd9Sstevel@tonic-gate sp->sp_max = atoi(temp); 12397c478bd9Sstevel@tonic-gate 12407c478bd9Sstevel@tonic-gate /* warning period */ 12417c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(p, &temp, str_end))) 12427c478bd9Sstevel@tonic-gate return (FAILURE); 12437c478bd9Sstevel@tonic-gate sp->sp_warn = atoi(temp); 12447c478bd9Sstevel@tonic-gate 12457c478bd9Sstevel@tonic-gate /* max days inactive */ 12467c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(p, &temp, str_end))) 12477c478bd9Sstevel@tonic-gate return (FAILURE); 12487c478bd9Sstevel@tonic-gate sp->sp_inact = atoi(temp); 12497c478bd9Sstevel@tonic-gate 12507c478bd9Sstevel@tonic-gate /* account expiry date */ 12517c478bd9Sstevel@tonic-gate if (NULL == (p = get_next_token(p, &temp, str_end))) 12527c478bd9Sstevel@tonic-gate return (FAILURE); 12537c478bd9Sstevel@tonic-gate sp->sp_expire = atoi(temp); 12547c478bd9Sstevel@tonic-gate 12557c478bd9Sstevel@tonic-gate /* flag */ 12567c478bd9Sstevel@tonic-gate if (NULL != (p = get_next_token(p, &temp, str_end))) 12577c478bd9Sstevel@tonic-gate return (FAILURE); 12587c478bd9Sstevel@tonic-gate sp->sp_flag = atoi(temp); 12597c478bd9Sstevel@tonic-gate 12607c478bd9Sstevel@tonic-gate return (SUCCESS); 12617c478bd9Sstevel@tonic-gate } 12627c478bd9Sstevel@tonic-gate 12637c478bd9Sstevel@tonic-gate /* 12647c478bd9Sstevel@tonic-gate * FUNCTION : write_shadow_info() 12657c478bd9Sstevel@tonic-gate * 12667c478bd9Sstevel@tonic-gate * DESCRIPTION: Writes shadow information back to the DIT. 12677c478bd9Sstevel@tonic-gate * 12687c478bd9Sstevel@tonic-gate * INPUTS : Domain 12697c478bd9Sstevel@tonic-gate * Information to write 12707c478bd9Sstevel@tonic-gate * 12717c478bd9Sstevel@tonic-gate * OUTPUT : Success code 12727c478bd9Sstevel@tonic-gate * 12737c478bd9Sstevel@tonic-gate */ 12747c478bd9Sstevel@tonic-gate suc_code 12757c478bd9Sstevel@tonic-gate write_shadow_info(char *domain, struct spwd *sp) 12767c478bd9Sstevel@tonic-gate { 12777c478bd9Sstevel@tonic-gate char *myself = "write_shadow_info"; 12787c478bd9Sstevel@tonic-gate datum key, data; 12797c478bd9Sstevel@tonic-gate char *str; 12807c478bd9Sstevel@tonic-gate suc_code res; 12817c478bd9Sstevel@tonic-gate int len; 12827c478bd9Sstevel@tonic-gate 12837c478bd9Sstevel@tonic-gate /* Work out how long string will be */ 12847c478bd9Sstevel@tonic-gate len = strlen(sp->sp_namp) + 1; 12857c478bd9Sstevel@tonic-gate 12867c478bd9Sstevel@tonic-gate /* 12877c478bd9Sstevel@tonic-gate * Bit crude but if we assume 1 byte is 3 decimal characters 12887c478bd9Sstevel@tonic-gate * will get enough buffer for the longs and some spare. 12897c478bd9Sstevel@tonic-gate */ 12907c478bd9Sstevel@tonic-gate len += 7 * (3 * sizeof (long) + 1); 12917c478bd9Sstevel@tonic-gate 12927c478bd9Sstevel@tonic-gate /* Allocate some memory */ 12937c478bd9Sstevel@tonic-gate str = am(myself, len); 12947c478bd9Sstevel@tonic-gate if (NULL == str) { 12957c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, "Could not aloc for shadow write"); 12967c478bd9Sstevel@tonic-gate return (FAILURE); 12977c478bd9Sstevel@tonic-gate } 12987c478bd9Sstevel@tonic-gate 12997c478bd9Sstevel@tonic-gate /* Build up shadow string */ 13007c478bd9Sstevel@tonic-gate sprintf(str, "%s%c%d%c%d%c%d%c%d%c%d%c%d%c%d", 13017c478bd9Sstevel@tonic-gate sp->sp_namp, COLON_CHAR, 13027c478bd9Sstevel@tonic-gate sp->sp_lstchg, COLON_CHAR, 13037c478bd9Sstevel@tonic-gate sp->sp_min, COLON_CHAR, 13047c478bd9Sstevel@tonic-gate sp->sp_max, COLON_CHAR, 13057c478bd9Sstevel@tonic-gate sp->sp_warn, COLON_CHAR, 13067c478bd9Sstevel@tonic-gate sp->sp_inact, COLON_CHAR, 13077c478bd9Sstevel@tonic-gate sp->sp_expire, COLON_CHAR, 13087c478bd9Sstevel@tonic-gate sp->sp_flag); 13097c478bd9Sstevel@tonic-gate 13107c478bd9Sstevel@tonic-gate /* Write it */ 13117c478bd9Sstevel@tonic-gate data.dptr = str; 13127c478bd9Sstevel@tonic-gate data.dsize = strlen(data.dptr); 13137c478bd9Sstevel@tonic-gate key.dptr = sp->sp_namp; 13147c478bd9Sstevel@tonic-gate key.dsize = strlen(key.dptr); 13157c478bd9Sstevel@tonic-gate res = write_to_dit(AGEING_MAPPING, domain, key, data, TRUE, FALSE); 13167c478bd9Sstevel@tonic-gate 13177c478bd9Sstevel@tonic-gate sfree(str); 13187c478bd9Sstevel@tonic-gate return (res); 13197c478bd9Sstevel@tonic-gate } 13207c478bd9Sstevel@tonic-gate 13217c478bd9Sstevel@tonic-gate /* 13227c478bd9Sstevel@tonic-gate * FUNCTION : free_shadow_entry() 13237c478bd9Sstevel@tonic-gate * 13247c478bd9Sstevel@tonic-gate * DESCRIPTION: Frees up a shadow information structure 13257c478bd9Sstevel@tonic-gate * 13267c478bd9Sstevel@tonic-gate * INPUTS : Structure to free 13277c478bd9Sstevel@tonic-gate * 13287c478bd9Sstevel@tonic-gate * OUTPUTS : Nothing 13297c478bd9Sstevel@tonic-gate */ 13307c478bd9Sstevel@tonic-gate void 13317c478bd9Sstevel@tonic-gate free_shadow_entry(struct spwd *spwd) 13327c478bd9Sstevel@tonic-gate { 13337c478bd9Sstevel@tonic-gate if (NULL != spwd->sp_namp) 13347c478bd9Sstevel@tonic-gate sfree(spwd->sp_namp); 13357c478bd9Sstevel@tonic-gate 13367c478bd9Sstevel@tonic-gate if (NULL != spwd->sp_pwdp) 13377c478bd9Sstevel@tonic-gate sfree(spwd->sp_pwdp); 13387c478bd9Sstevel@tonic-gate 13397c478bd9Sstevel@tonic-gate /* No need to free numerics */ 13407c478bd9Sstevel@tonic-gate 13417c478bd9Sstevel@tonic-gate /* Free up structure */ 13427c478bd9Sstevel@tonic-gate sfree(spwd); 13437c478bd9Sstevel@tonic-gate } 1344