xref: /titanic_52/usr/src/lib/passwdutil/nss_attr.c (revision 36e852a172cba914383d7341c988128b2c667fbd)
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 <errno.h>
28  #include <stdlib.h>
29  #include <pwd.h>
30  #include <shadow.h>
31  #include <string.h>
32  #include <stdlib.h>
33  #include <unistd.h>
34  #include <nss_dbdefs.h>
35  
36  #include "passwdutil.h"
37  
38  /* from files_attr.c */
39  struct passwd *private_getpwnam_r(const char *name, struct passwd *result,
40      char *buffer, int buflen);
41  
42  int nss_getattr(char *name, attrlist *item, pwu_repository_t *rep);
43  int nss_getpwnam(char *name, attrlist *items, pwu_repository_t *rep,
44      void **buf);
45  
46  /*
47   * nss function pointer table, used by passwdutil_init to initialize
48   * the global Repository-OPerations table "rops"
49   */
50  struct repops nss_repops = {
51  	NULL,		/* checkhistory */
52  	nss_getattr,
53  	nss_getpwnam,
54  	NULL,		/* update */
55  	NULL,		/* putpwnam */
56  	NULL,		/* user_to_authenticate */
57  	NULL,		/* lock */
58  	NULL		/* unlock */
59  };
60  
61  /*
62   * this structure defines the buffer used to keep state between
63   * get/update/put calls
64   */
65  struct pwbuf {
66  	struct passwd *pwd;
67  	char   *pwd_scratch;
68  	struct spwd *spwd;
69  	char   *spwd_scratch;
70  	char   *rep_name;
71  };
72  
73  /*
74   * We should use sysconf, but there is no sysconf name for SHADOW
75   * so we use these from nss_dbdefs
76   */
77  #define	PWD_SCRATCH_SIZE NSS_LINELEN_PASSWD
78  #define	SPW_SCRATCH_SIZE NSS_LINELEN_SHADOW
79  
80  
81  /*
82   * nss_getpwnam(name, items, rep, buf)
83   *
84   */
85  /*ARGSUSED*/
86  int
87  nss_getpwnam(char *name, attrlist *items, pwu_repository_t *rep, void **buf)
88  {
89  	attrlist *p;
90  	struct pwbuf *pwbuf;
91  	int repositories = REP_ERANGE;	/* changed if ATTR_REP_NAME is set */
92  	int err = PWU_SUCCESS;
93  
94  	*buf = calloc(1, sizeof (struct pwbuf));
95  	pwbuf = (struct pwbuf *)*buf;
96  	if (pwbuf == NULL)
97  		return (PWU_NOMEM);
98  
99  	/*
100  	 * determine which password structure (/etc/passwd or /etc/shadow)
101  	 * we need for the items we need to update
102  	 */
103  	for (p = items; p != NULL; p = p->next) {
104  		switch (p->type) {
105  		case ATTR_NAME:
106  		case ATTR_UID:
107  		case ATTR_GID:
108  		case ATTR_AGE:
109  		case ATTR_COMMENT:
110  		case ATTR_GECOS:
111  		case ATTR_HOMEDIR:
112  		case ATTR_SHELL:
113  			if (pwbuf->pwd == NULL)
114  				pwbuf->pwd = (struct passwd *)
115  				    malloc(sizeof (struct passwd));
116  			if (pwbuf->pwd == NULL) {
117  				errno = ENOMEM;
118  				if (pwbuf->spwd)
119  					free(pwbuf->spwd);
120  				return (PWU_NOMEM);
121  			}
122  			break;
123  		case ATTR_PASSWD:
124  		case ATTR_PASSWD_SERVER_POLICY:
125  		case ATTR_LSTCHG:
126  		case ATTR_MIN:
127  		case ATTR_MAX:
128  		case ATTR_WARN:
129  		case ATTR_INACT:
130  		case ATTR_EXPIRE:
131  		case ATTR_FLAG:
132  		case ATTR_LOCK_ACCOUNT:
133  		case ATTR_EXPIRE_PASSWORD:
134  		case ATTR_FAILED_LOGINS:
135  			if (pwbuf->spwd == NULL)
136  				pwbuf->spwd = (struct spwd *)
137  				    malloc(sizeof (struct spwd));
138  			if (pwbuf->spwd == NULL) {
139  				errno = ENOMEM;
140  				if (pwbuf->pwd)
141  					free(pwbuf->pwd);
142  				return (PWU_NOMEM);
143  			}
144  			break;
145  		case ATTR_REP_NAME:
146  			/* get the compat names (REP_COMPAT_*) */
147  			repositories = get_ns(rep, PWU_READ);
148  			break;
149  		default:
150  			/*
151  			 * Some other repository might have different values
152  			 * so we ignore those.
153  			 */
154  			break;
155  		}
156  	}
157  
158  	if (pwbuf->pwd) {
159  		if ((pwbuf->pwd_scratch = malloc(PWD_SCRATCH_SIZE)) == NULL) {
160  			err = PWU_NOMEM;
161  			goto error;
162  		}
163  		if (getpwnam_r(name, pwbuf->pwd, pwbuf->pwd_scratch,
164  		    PWD_SCRATCH_SIZE) == NULL) {
165  			err = PWU_NOT_FOUND;
166  			goto error;
167  		}
168  	}
169  
170  	if (pwbuf->spwd) {
171  		if ((pwbuf->spwd_scratch = malloc(SPW_SCRATCH_SIZE)) == NULL) {
172  			err = PWU_NOMEM;
173  			goto error;
174  		}
175  		if (getspnam_r(name, pwbuf->spwd, pwbuf->spwd_scratch,
176  		    SPW_SCRATCH_SIZE) == NULL) {
177  			err = PWU_NOT_FOUND;
178  			goto error;
179  		}
180  	}
181  
182  	/* pwbuf->rep_name tells us where the user in fact comes from */
183  	if (repositories != REP_ERANGE) {
184  		struct passwd pwd;
185  		char pwd_scratch[PWD_SCRATCH_SIZE];
186  
187  		/* can we find the user locally? */
188  		if (private_getpwnam_r(name, &pwd, pwd_scratch,
189  		    PWD_SCRATCH_SIZE) != NULL)
190  			pwbuf->rep_name = "files";
191  		else if (repositories & REP_COMPAT_LDAP)
192  			pwbuf->rep_name = "ldap";
193  		else if (repositories & REP_COMPAT_NIS)
194  			pwbuf->rep_name = "nis";
195  		else
196  			pwbuf->rep_name = "nss";
197  	} else
198  		pwbuf->rep_name = "nss";
199  
200  	return (PWU_SUCCESS);
201  error:
202  	if (pwbuf->pwd) free(pwbuf->pwd);
203  	if (pwbuf->pwd_scratch) free(pwbuf->pwd_scratch);
204  	if (pwbuf->spwd) free(pwbuf->spwd);
205  	if (pwbuf->spwd_scratch) free(pwbuf->spwd_scratch);
206  	free(pwbuf);
207  	*buf = NULL;
208  
209  	return (err);
210  }
211  
212  
213  /*
214   * nss_getattr(name, items, rep)
215   *
216   * Get attributes specified in list 'items'
217   */
218  int
219  nss_getattr(char *name, attrlist *items, pwu_repository_t *rep)
220  {
221  	struct pwbuf *pwbuf;
222  	struct passwd *pw;
223  	struct spwd *spw;
224  	attrlist *w;
225  	int res = 0;
226  
227  	res = nss_getpwnam(name, items, rep, (void **)&pwbuf);
228  	if (res != PWU_SUCCESS)
229  		return (res);
230  
231  	pw = pwbuf->pwd;
232  	spw = pwbuf->spwd;
233  
234  	for (w = items; res == PWU_SUCCESS && w != NULL; w = w->next) {
235  		switch (w->type) {
236  		case ATTR_NAME:
237  			if ((w->data.val_s = strdup(pw->pw_name)) == NULL)
238  				res = PWU_NOMEM;
239  			break;
240  		case ATTR_COMMENT:
241  			if ((w->data.val_s = strdup(pw->pw_comment)) == NULL)
242  				res = PWU_NOMEM;
243  			break;
244  		case ATTR_GECOS:
245  			if ((w->data.val_s = strdup(pw->pw_gecos)) == NULL)
246  				res = PWU_NOMEM;
247  			break;
248  		case ATTR_HOMEDIR:
249  			if ((w->data.val_s = strdup(pw->pw_dir)) == NULL)
250  				res = PWU_NOMEM;
251  			break;
252  		case ATTR_SHELL:
253  			if ((w->data.val_s = strdup(pw->pw_shell)) == NULL)
254  				res = PWU_NOMEM;
255  			break;
256  		/*
257  		 * Nothing special needs to be done for
258  		 * server policy
259  		 */
260  		case ATTR_PASSWD:
261  		case ATTR_PASSWD_SERVER_POLICY:
262  			if ((w->data.val_s = strdup(spw->sp_pwdp)) == NULL)
263  				res = PWU_NOMEM;
264  			break;
265  		case ATTR_AGE:
266  			if ((w->data.val_s = strdup(pw->pw_age)) == NULL)
267  				res = PWU_NOMEM;
268  			break;
269  		case ATTR_REP_NAME:
270  			if ((w->data.val_s = strdup(pwbuf->rep_name)) == NULL)
271  				res = PWU_NOMEM;
272  			break;
273  
274  		/* integer values */
275  		case ATTR_UID:
276  			w->data.val_i = pw->pw_uid;
277  			break;
278  		case ATTR_GID:
279  			w->data.val_i = pw->pw_gid;
280  			break;
281  		case ATTR_LSTCHG:
282  			w->data.val_i = spw->sp_lstchg;
283  			break;
284  		case ATTR_MIN:
285  			w->data.val_i = spw->sp_min;
286  			break;
287  		case ATTR_MAX:
288  			w->data.val_i = spw->sp_max;
289  			break;
290  		case ATTR_WARN:
291  			w->data.val_i = spw->sp_warn;
292  			break;
293  		case ATTR_INACT:
294  			w->data.val_i = spw->sp_inact;
295  			break;
296  		case ATTR_EXPIRE:
297  			w->data.val_i = spw->sp_expire;
298  			break;
299  		case ATTR_FLAG:
300  			w->data.val_i = spw->sp_flag;
301  			break;
302  		case ATTR_FAILED_LOGINS:
303  			w->data.val_i = spw->sp_flag & FAILCOUNT_MASK;
304  			break;
305  		default:
306  			break;
307  		}
308  	}
309  
310  	if (pwbuf->pwd) free(pwbuf->pwd);
311  	if (pwbuf->pwd_scratch) free(pwbuf->pwd_scratch);
312  	if (pwbuf->spwd) free(pwbuf->spwd);
313  	if (pwbuf->spwd_scratch) free(pwbuf->spwd_scratch);
314  	free(pwbuf);
315  
316  	return (res);
317  }
318