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]
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.
29 #include <sys/types.h>
31 #include <nss_dbdefs.h>
34 #include <sys/param.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
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
);
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>
65 getpwnam_r(const char *name
, struct passwd
*pwd
, char *buffer
, size_t bufsize
,
66 struct passwd
**result
)
74 NSS_XbyY_INIT(&arg
, pwd
, buffer
, bufsize
, str2passwd
);
76 (void) nss_search(&db_root
, _nss_initf_passwd
, NSS_DBOP_PASSWD_BYNAME
,
78 *result
= ((struct passwd
*)NSS_XbyY_FINI(&arg
));
86 getpwuid_r(uid_t uid
, struct passwd
*pwd
, char *buffer
, size_t bufsize
,
87 struct passwd
**result
)
91 NSS_XbyY_INIT(&arg
, pwd
, buffer
, bufsize
, str2passwd
);
93 (void) nss_search(&db_root
, _nss_initf_passwd
, NSS_DBOP_PASSWD_BYUID
,
95 *result
= ((struct passwd
*)NSS_XbyY_FINI(&arg
));
102 _uncached_getpwnam_r(const char *name
, struct passwd
*pwd
, char *buffer
,
107 NSS_XbyY_INIT(&arg
, pwd
, buffer
, buflen
, str2passwd
);
109 (void) nss_search(&db_root
, _nss_initf_passwd
, NSS_DBOP_PASSWD_BYNAME
,
111 return ((struct passwd
*)NSS_XbyY_FINI(&arg
));
115 _uncached_getpwuid_r(uid_t uid
, struct passwd
*pwd
, char *buffer
,
120 NSS_XbyY_INIT(&arg
, pwd
, buffer
, buflen
, str2passwd
);
122 (void) nss_search(&db_root
, _nss_initf_passwd
, NSS_DBOP_PASSWD_BYUID
,
124 return ((struct passwd
*)NSS_XbyY_FINI(&arg
));
130 nss_setent(&db_root
, _nss_initf_passwd
, &context
);
136 nss_endent(&db_root
, _nss_initf_passwd
, &context
);
137 nss_delete(&db_root
);
141 gettok(char **nextpp
)
150 while ((c
= *q
) != '\0' && c
!= ':')
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
;
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 */
190 return (NSS_STR_PARSE_SUCCESS
);
194 passwd
->pw_name
= p
= gettok(&next
); /* username */
196 /* Empty username; not allowed */
197 return (NSS_STR_PARSE_PARSE
);
200 passwd
->pw_passwd
= p
= gettok(&next
); /* password */
202 return (NSS_STR_PARSE_PARSE
);
203 for (; *p
!= '\0'; p
++) { /* age */
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.
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
;
241 passwd
->pw_uid
= (uid_t
)tmp
;
244 return (NSS_STR_PARSE_PARSE
);
246 if (p
== 0 || *p
== '\0')
247 return (NSS_STR_PARSE_PARSE
);
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
;
263 passwd
->pw_gid
= (gid_t
)tmp
;
266 return (NSS_STR_PARSE_PARSE
);
268 passwd
->pw_gecos
= passwd
->pw_comment
= p
= gettok(&next
);
270 return (NSS_STR_PARSE_PARSE
);
272 passwd
->pw_dir
= p
= gettok(&next
);
274 return (NSS_STR_PARSE_PARSE
);
276 passwd
->pw_shell
= p
= gettok(&next
);
278 return (NSS_STR_PARSE_PARSE
);
280 /* Better not be any more fields... */
282 /* Successfully parsed and stored */
283 return (NSS_STR_PARSE_SUCCESS
);
285 return (NSS_STR_PARSE_PARSE
);