Merge illumos-gate
[unleashed.git] / usr / src / lib / passwdutil / nss_attr.c
blobf97c140e3e68549a138c7f8783637e37724747de
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
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>
36 #include "passwdutil.h"
38 /* from files_attr.c */
39 struct passwd *private_getpwnam_r(const char *name, struct passwd *result,
40 char *buffer, int buflen);
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);
47 * nss function pointer table, used by passwdutil_init to initialize
48 * the global Repository-OPerations table "rops"
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 */
62 * this structure defines the buffer used to keep state between
63 * get/update/put calls
65 struct pwbuf {
66 struct passwd *pwd;
67 char *pwd_scratch;
68 struct spwd *spwd;
69 char *spwd_scratch;
70 char *rep_name;
74 * We should use sysconf, but there is no sysconf name for SHADOW
75 * so we use these from nss_dbdefs
77 #define PWD_SCRATCH_SIZE NSS_LINELEN_PASSWD
78 #define SPW_SCRATCH_SIZE NSS_LINELEN_SHADOW
82 * nss_getpwnam(name, items, rep, buf)
85 /*ARGSUSED*/
86 int
87 nss_getpwnam(char *name, attrlist *items, pwu_repository_t *rep, void **buf)
89 attrlist *p;
90 struct pwbuf *pwbuf;
91 int repositories = REP_ERANGE; /* changed if ATTR_REP_NAME is set */
92 int err = PWU_SUCCESS;
94 *buf = calloc(1, sizeof (struct pwbuf));
95 pwbuf = (struct pwbuf *)*buf;
96 if (pwbuf == NULL)
97 return (PWU_NOMEM);
100 * determine which password structure (/etc/passwd or /etc/shadow)
101 * we need for the items we need to update
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 free(pwbuf->spwd);
119 return (PWU_NOMEM);
121 break;
122 case ATTR_PASSWD:
123 case ATTR_PASSWD_SERVER_POLICY:
124 case ATTR_LSTCHG:
125 case ATTR_MIN:
126 case ATTR_MAX:
127 case ATTR_WARN:
128 case ATTR_INACT:
129 case ATTR_EXPIRE:
130 case ATTR_FLAG:
131 case ATTR_LOCK_ACCOUNT:
132 case ATTR_EXPIRE_PASSWORD:
133 case ATTR_FAILED_LOGINS:
134 if (pwbuf->spwd == NULL)
135 pwbuf->spwd = (struct spwd *)
136 malloc(sizeof (struct spwd));
137 if (pwbuf->spwd == NULL) {
138 errno = ENOMEM;
139 free(pwbuf->pwd);
140 return (PWU_NOMEM);
142 break;
143 case ATTR_REP_NAME:
144 /* get the compat names (REP_COMPAT_*) */
145 repositories = get_ns(rep, PWU_READ);
146 break;
147 default:
149 * Some other repository might have different values
150 * so we ignore those.
152 break;
156 if (pwbuf->pwd) {
157 struct passwd *pwdp;
158 if ((pwbuf->pwd_scratch = malloc(PWD_SCRATCH_SIZE)) == NULL) {
159 err = PWU_NOMEM;
160 goto error;
162 getpwnam_r(name, pwbuf->pwd, pwbuf->pwd_scratch,
163 PWD_SCRATCH_SIZE, &pwdp);
164 if (!pwdp) {
165 err = PWU_NOT_FOUND;
166 goto error;
170 if (pwbuf->spwd) {
171 if ((pwbuf->spwd_scratch = malloc(SPW_SCRATCH_SIZE)) == NULL) {
172 err = PWU_NOMEM;
173 goto error;
175 if (getspnam_r(name, pwbuf->spwd, pwbuf->spwd_scratch,
176 SPW_SCRATCH_SIZE) == NULL) {
177 err = PWU_NOT_FOUND;
178 goto error;
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];
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";
200 return (PWU_SUCCESS);
201 error:
202 free(pwbuf->pwd);
203 free(pwbuf->pwd_scratch);
204 free(pwbuf->spwd);
205 free(pwbuf->spwd_scratch);
206 free(pwbuf);
207 *buf = NULL;
209 return (err);
214 * nss_getattr(name, items, rep)
216 * Get attributes specified in list 'items'
219 nss_getattr(char *name, attrlist *items, pwu_repository_t *rep)
221 struct pwbuf *pwbuf;
222 struct passwd *pw;
223 struct spwd *spw;
224 attrlist *w;
225 int res = 0;
227 res = nss_getpwnam(name, items, rep, (void **)&pwbuf);
228 if (res != PWU_SUCCESS)
229 return (res);
231 pw = pwbuf->pwd;
232 spw = pwbuf->spwd;
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;
257 * Nothing special needs to be done for
258 * server policy
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;
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;
310 free(pwbuf->pwd);
311 free(pwbuf->pwd_scratch);
312 free(pwbuf->spwd);
313 free(pwbuf->spwd_scratch);
314 free(pwbuf);
316 return (res);