dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libc / port / gen / getpwnam_r.c
blob4660e266c214dacc3bd6373aae150a8dc147370a
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
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright (c) 2016 by Delphix. All rights reserved.
28 #include "lint.h"
29 #include <sys/types.h>
30 #include <pwd.h>
31 #include <nss_dbdefs.h>
32 #include <stdio.h>
33 #include <synch.h>
34 #include <sys/param.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include <sys/mman.h>
38 #include <errno.h>
41 * Compatibility aliases; Solaris/illumos default to the POSIX.1c Draft 6
42 * versions of these functions and use __posix_*_r for the standard versions.
43 * Our unadorned symbols are the standard versions, but we allow previously
44 * compiled binaries that are using the POSIX version to work with these
45 * aliases.
47 #pragma weak __posix_getpwuid_r = getpwuid_r
48 #pragma weak __posix_getpwnam_r = getpwnam_r
50 int str2passwd(const char *, int, void *, char *, int);
52 static DEFINE_NSS_DB_ROOT(db_root);
53 static DEFINE_NSS_GETENT(context);
55 void
56 _nss_initf_passwd(nss_db_params_t *p)
58 p->name = NSS_DBNAM_PASSWD;
59 p->default_config = NSS_DEFCONF_PASSWD;
62 #include <getxby_door.h>
64 int
65 getpwnam_r(const char *name, struct passwd *pwd, char *buffer, size_t bufsize,
66 struct passwd **result)
68 nss_XbyY_args_t arg;
70 if (!name) {
71 errno = ERANGE;
72 return (errno);
74 NSS_XbyY_INIT(&arg, pwd, buffer, bufsize, str2passwd);
75 arg.key.name = name;
76 (void) nss_search(&db_root, _nss_initf_passwd, NSS_DBOP_PASSWD_BYNAME,
77 &arg);
78 *result = ((struct passwd *)NSS_XbyY_FINI(&arg));
79 if (!*result)
80 return (errno);
81 return (0);
85 int
86 getpwuid_r(uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize,
87 struct passwd **result)
89 nss_XbyY_args_t arg;
91 NSS_XbyY_INIT(&arg, pwd, buffer, bufsize, str2passwd);
92 arg.key.uid = uid;
93 (void) nss_search(&db_root, _nss_initf_passwd, NSS_DBOP_PASSWD_BYUID,
94 &arg);
95 *result = ((struct passwd *)NSS_XbyY_FINI(&arg));
96 if (!*result)
97 return (errno);
98 return (0);
101 struct passwd *
102 _uncached_getpwnam_r(const char *name, struct passwd *pwd, char *buffer,
103 int buflen)
105 nss_XbyY_args_t arg;
107 NSS_XbyY_INIT(&arg, pwd, buffer, buflen, str2passwd);
108 arg.key.name = name;
109 (void) nss_search(&db_root, _nss_initf_passwd, NSS_DBOP_PASSWD_BYNAME,
110 &arg);
111 return ((struct passwd *)NSS_XbyY_FINI(&arg));
114 struct passwd *
115 _uncached_getpwuid_r(uid_t uid, struct passwd *pwd, char *buffer,
116 int buflen)
118 nss_XbyY_args_t arg;
120 NSS_XbyY_INIT(&arg, pwd, buffer, buflen, str2passwd);
121 arg.key.uid = uid;
122 (void) nss_search(&db_root, _nss_initf_passwd, NSS_DBOP_PASSWD_BYUID,
123 &arg);
124 return ((struct passwd *)NSS_XbyY_FINI(&arg));
127 void
128 setpwent(void)
130 nss_setent(&db_root, _nss_initf_passwd, &context);
133 void
134 endpwent(void)
136 nss_endent(&db_root, _nss_initf_passwd, &context);
137 nss_delete(&db_root);
140 static char *
141 gettok(char **nextpp)
143 char *p = *nextpp;
144 char *q = p;
145 char c;
147 if (p == 0)
148 return (0);
150 while ((c = *q) != '\0' && c != ':')
151 q++;
153 if (c == '\0')
154 *nextpp = 0;
155 else {
156 *q++ = '\0';
157 *nextpp = q;
159 return (p);
163 * Return values: 0 = success, 1 = parse error, 2 = erange ...
164 * The structure pointer passed in is a structure in the caller's space
165 * wherein the field pointers would be set to areas in the buffer if
166 * need be. instring and buffer should be separate areas.
169 str2passwd(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
171 struct passwd *passwd = (struct passwd *)ent;
172 char *p, *next;
173 ulong_t tmp;
175 if (lenstr + 1 > buflen)
176 return (NSS_STR_PARSE_ERANGE);
179 * We copy the input string into the output buffer and
180 * operate on it in place.
182 if (instr != buffer) {
183 /* Overlapping buffer copies are OK */
184 (void) memmove(buffer, instr, lenstr);
185 buffer[lenstr] = '\0';
188 /* quick exit do not entry fill if not needed */
189 if (ent == NULL)
190 return (NSS_STR_PARSE_SUCCESS);
192 next = buffer;
194 passwd->pw_name = p = gettok(&next); /* username */
195 if (*p == '\0') {
196 /* Empty username; not allowed */
197 return (NSS_STR_PARSE_PARSE);
200 passwd->pw_passwd = p = gettok(&next); /* password */
201 if (p == 0)
202 return (NSS_STR_PARSE_PARSE);
203 for (; *p != '\0'; p++) { /* age */
204 if (*p == ',') {
205 *p++ = '\0';
206 break;
209 passwd->pw_age = p;
211 p = next; /* uid */
212 if (p == 0 || *p == '\0')
213 return (NSS_STR_PARSE_PARSE);
216 * strtoul returns unsigned long which is
217 * 8 bytes on a 64-bit system. We don't want
218 * to assign it directly to passwd->pw_uid
219 * which is 4 bytes or else we will end up
220 * truncating the value.
222 errno = 0;
223 tmp = strtoul(p, &next, 10);
224 if (next == p || errno != 0) {
225 /* uid field should be nonempty */
226 /* also check errno from strtoul */
227 return (NSS_STR_PARSE_PARSE);
230 * The old code (in 2.0 through 2.5) would check
231 * for the uid being negative, or being greater
232 * than 60001 (the rfs limit). If it met either of
233 * these conditions, the uid was translated to 60001.
235 * Now we just check for -1 (UINT32_MAX); anything else
236 * is administrative policy
238 if (tmp >= UINT32_MAX)
239 passwd->pw_uid = UID_NOBODY;
240 else
241 passwd->pw_uid = (uid_t)tmp;
243 if (*next++ != ':')
244 return (NSS_STR_PARSE_PARSE);
245 p = next; /* gid */
246 if (p == 0 || *p == '\0')
247 return (NSS_STR_PARSE_PARSE);
249 errno = 0;
250 tmp = strtoul(p, &next, 10);
251 if (next == p || errno != 0) {
252 /* gid field should be nonempty */
253 /* also check errno from strtoul */
254 return (NSS_STR_PARSE_PARSE);
257 * gid should not be -1; anything else
258 * is administrative policy.
260 if (tmp >= UINT32_MAX)
261 passwd->pw_gid = GID_NOBODY;
262 else
263 passwd->pw_gid = (gid_t)tmp;
265 if (*next++ != ':')
266 return (NSS_STR_PARSE_PARSE);
268 passwd->pw_gecos = passwd->pw_comment = p = gettok(&next);
269 if (p == 0)
270 return (NSS_STR_PARSE_PARSE);
272 passwd->pw_dir = p = gettok(&next);
273 if (p == 0)
274 return (NSS_STR_PARSE_PARSE);
276 passwd->pw_shell = p = gettok(&next);
277 if (p == 0)
278 return (NSS_STR_PARSE_PARSE);
280 /* Better not be any more fields... */
281 if (next == 0) {
282 /* Successfully parsed and stored */
283 return (NSS_STR_PARSE_SUCCESS);
285 return (NSS_STR_PARSE_PARSE);