xref: /illumos-gate/usr/src/lib/passwdutil/utils.c (revision 1a5e258f5471356ca102c7176637cdce45bac147)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <sys/types.h>
27 #include <sys/time.h>
28 #include <string.h>
29 #include <thread.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include <crypt.h>
33 #include <pwd.h>
34 #include <shadow.h>
35 
36 #include <deflt.h>
37 
38 #include "passwdutil.h"
39 
40 #define	PWADMIN "/etc/default/passwd"
41 
42 #define	MINWEEKS	-1
43 #define	MAXWEEKS	-1
44 #define	WARNWEEKS	-1
45 
46 extern repops_t files_repops, nis_repops, ldap_repops, nss_repops;
47 
48 repops_t *rops[REP_LAST+1] = {
49 	NULL,
50 	&files_repops,
51 	&nis_repops,
52 	NULL,
53 	&ldap_repops,
54 	NULL,
55 	NULL,
56 	NULL,
57 	&nss_repops,
58 };
59 
60 void
61 free_pwd(struct passwd *pw)
62 {
63 	if (pw->pw_name) free(pw->pw_name);
64 	if (pw->pw_passwd) free(pw->pw_passwd);
65 	if (pw->pw_gecos) free(pw->pw_gecos);
66 	if (pw->pw_dir) free(pw->pw_dir);
67 	if (pw->pw_shell) free(pw->pw_shell);
68 	free(pw);
69 }
70 
71 void
72 free_spwd(struct spwd *spw)
73 {
74 	if (spw->sp_namp) free(spw->sp_namp);
75 	if (spw->sp_pwdp) free(spw->sp_pwdp);
76 	free(spw);
77 }
78 
79 int
80 dup_pw(struct passwd **d, struct passwd *s)
81 {
82 	if (s == NULL) {
83 		*d = NULL;
84 		return (PWU_NOT_FOUND);
85 	}
86 	if ((*d = calloc(1, sizeof (**d))) == NULL)
87 		return (PWU_NOMEM);
88 
89 	if (s->pw_name) {
90 		if (((*d)->pw_name = strdup(s->pw_name)) == NULL)
91 			goto no_mem;
92 	}
93 	if (s->pw_passwd) {
94 		if (((*d)->pw_passwd = strdup(s->pw_passwd)) == NULL)
95 			goto no_mem;
96 	}
97 	(*d)->pw_uid = s->pw_uid;
98 	(*d)->pw_gid = s->pw_gid;
99 
100 	if (s->pw_gecos) {
101 		if (((*d)->pw_gecos = strdup(s->pw_gecos)) == NULL)
102 			goto no_mem;
103 	}
104 	if (s->pw_dir) {
105 		if (((*d)->pw_dir = strdup(s->pw_dir)) == NULL)
106 			goto no_mem;
107 	}
108 	if (s->pw_shell) {
109 		if (((*d)->pw_shell = strdup(s->pw_shell)) == NULL)
110 			goto no_mem;
111 	}
112 
113 	return (PWU_SUCCESS);
114 
115 no_mem:
116 	free_pwd(*d);
117 	*d = NULL;
118 	return (PWU_NOMEM);
119 }
120 
121 int
122 dup_spw(struct spwd **d, struct spwd *s)
123 {
124 	if (s == NULL) {
125 		*d = NULL;
126 		return (PWU_NOT_FOUND);
127 	}
128 	if ((*d = calloc(1, sizeof (**d))) == NULL)
129 		return (PWU_NOMEM);
130 
131 	**d = *s;
132 
133 	if (s->sp_namp)
134 		if (((*d)->sp_namp = strdup(s->sp_namp)) == NULL)
135 			goto no_mem;
136 	if (s->sp_pwdp)
137 		if (((*d)->sp_pwdp = strdup(s->sp_pwdp)) == NULL)
138 			goto no_mem;
139 	return (PWU_SUCCESS);
140 
141 no_mem:
142 	free_spwd(*d);
143 	return (PWU_NOMEM);
144 }
145 
146 /*
147  * read a value from the defaults file, and return it if it is
148  * a positive integer. If the value is not defined, or negative,
149  * return the supplied default value
150  */
151 int
152 def_getuint(char *name, int defvalue, void *defp)
153 {
154 	char *p;
155 	int val = -1;	/* -1 is a guard to catch undefined values */
156 
157 	if ((p = defread_r(name, defp)) != NULL)
158 		val = atoi(p);
159 
160 	return (val >= 0 ? val : defvalue);
161 }
162 
163 void
164 turn_on_default_aging(struct spwd *spw)
165 {
166 	int minweeks;
167 	int maxweeks;
168 	int warnweeks;
169 	void	*defp;
170 
171 	if ((defp = defopen_r(PWADMIN)) == NULL) {
172 		minweeks = MINWEEKS;
173 		maxweeks = MAXWEEKS;
174 		warnweeks = WARNWEEKS;
175 	} else {
176 		minweeks = def_getuint("MINWEEKS=", MINWEEKS, defp);
177 		maxweeks = def_getuint("MAXWEEKS=", MAXWEEKS, defp);
178 		warnweeks = def_getuint("WARNWEEKS=", WARNWEEKS, defp);
179 		defclose_r(defp);
180 	}
181 
182 	/*
183 	 * The values specified in /etc/default/passwd are interpreted
184 	 * in a specific way. Special cases are
185 	 *   MINWEEKS==0 (results in sp_min = -1)
186 	 *   MAXWEEKS==0 (results in sp_max = default)
187 	 */
188 	spw->sp_min = 7 * minweeks;
189 	if (spw->sp_min <= 0)
190 		spw->sp_min = -1;
191 
192 	spw->sp_max = 7 * maxweeks;
193 	if (spw->sp_max == 0)
194 		spw->sp_max = 7 * MAXWEEKS;
195 	if (spw->sp_max < 0)
196 		spw->sp_max = -1;
197 
198 	spw->sp_warn = 7 * warnweeks;
199 	if (spw->sp_warn <= 0)
200 		spw->sp_warn = -1;
201 }
202 
203 /*
204  * open and read a value from the defaults file,
205  * return value found or default value if not found.
206  */
207 int
208 def_getint(char *name, int defvalue)
209 {
210 	int	val;
211 	void	*defp;
212 
213 	if ((defp = defopen_r(PWADMIN)) == NULL) {
214 		val = defvalue;
215 	} else {
216 		val = def_getuint(name, defvalue, defp);
217 		defclose_r(defp);
218 	}
219 
220 	return (val);
221 }
222