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 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright (c) 2016 by Delphix. All rights reserved.
28 #pragma ident "%Z%%M% %I% %E% SMI"
32 #include <sys/types.h>
36 #include <nss_dbdefs.h>
40 int str2spwd(const char *, int, void *,
43 static DEFINE_NSS_DB_ROOT(db_root
);
44 static DEFINE_NSS_GETENT(context
);
47 _nss_initf_shadow(nss_db_params_t
*p
)
49 p
->name
= NSS_DBNAM_SHADOW
;
50 p
->config_name
= NSS_DBNAM_PASSWD
; /* Use config for "passwd" */
51 p
->default_config
= NSS_DEFCONF_PASSWD
;
55 getspnam_r(const char *name
, struct spwd
*result
, char *buffer
, int buflen
)
59 NSS_XbyY_INIT(&arg
, result
, buffer
, buflen
, str2spwd
);
61 (void) nss_search(&db_root
, _nss_initf_shadow
,
62 NSS_DBOP_SHADOW_BYNAME
, &arg
);
63 return ((struct spwd
*)NSS_XbyY_FINI(&arg
));
69 nss_setent(&db_root
, _nss_initf_shadow
, &context
);
75 nss_endent(&db_root
, _nss_initf_shadow
, &context
);
80 getspent_r(struct spwd
*result
, char *buffer
, int buflen
)
85 /* In getXXent_r(), protect the unsuspecting caller from +/- entries */
88 NSS_XbyY_INIT(&arg
, result
, buffer
, buflen
, str2spwd
);
89 /* No key to fill in */
90 (void) nss_getent(&db_root
, _nss_initf_shadow
, &context
, &arg
);
91 } while (arg
.returnval
!= 0 &&
92 (nam
= ((struct spwd
*)arg
.returnval
)->sp_namp
) != 0 &&
93 (*nam
== '+' || *nam
== '-'));
95 return (struct spwd
*)NSS_XbyY_FINI(&arg
);
99 fgetspent_r(FILE *f
, struct spwd
*result
, char *buffer
, int buflen
)
101 extern void _nss_XbyY_fgets(FILE *, nss_XbyY_args_t
*);
104 /* ... but in fgetXXent_r, the caller deserves any +/- entry it gets */
106 /* No key to fill in */
107 NSS_XbyY_INIT(&arg
, result
, buffer
, buflen
, str2spwd
);
108 _nss_XbyY_fgets(f
, &arg
);
109 return (struct spwd
*)NSS_XbyY_FINI(&arg
);
112 typedef const char *constp
;
114 static int /* 1 means success and more input, 0 means error or no more */
115 getfield(constp
*nextp
, constp limit
, int uns
, void *valp
)
119 char numbuf
[12]; /* Holds -2^31 and trailing ':' */
122 if (p
== 0 || p
>= limit
) {
130 if ((len
= limit
- p
) > sizeof (numbuf
) - 1) {
131 len
= sizeof (numbuf
) - 1;
134 * We want to use strtol() and we have a readonly non-zero-terminated
135 * string, so first we copy and terminate the interesting bit.
136 * Ugh. (It's convenient to terminate with a colon rather than \0).
138 if ((endfield
= memccpy(numbuf
, p
, ':', len
)) == 0) {
139 if (len
!= limit
- p
) {
140 /* Error -- field is too big to be a legit number */
146 p
+= (endfield
- numbuf
);
149 unsigned long ux
= strtoul(numbuf
, &endfield
, 10);
150 if (*endfield
!= ':') {
151 /* Error -- expected <integer><colon> */
154 *((unsigned int *)valp
) = (unsigned int)ux
;
156 long x
= strtol(numbuf
, &endfield
, 10);
157 if (*endfield
!= ':') {
158 /* Error -- expected <integer><colon> */
161 *((int *)valp
) = (int)x
;
168 * str2spwd() -- convert a string to a shadow passwd entry. The parser is
169 * more liberal than the passwd or group parsers; since it's legitimate
170 * for almost all the fields here to be blank, the parser lets one omit
171 * any number of blank fields at the end of the entry. The acceptable
172 * forms for '+' and '-' entries are the same as those for normal entries.
173 * === Is this likely to do more harm than good?
175 * Return values: 0 = success, 1 = parse error, 2 = erange ...
176 * The structure pointer passed in is a structure in the caller's space
177 * wherein the field pointers would be set to areas in the buffer if
178 * need be. instring and buffer should be separate areas.
181 str2spwd(const char *instr
, int lenstr
, void *ent
, char *buffer
, int buflen
)
183 struct spwd
*shadow
= (struct spwd
*)ent
;
184 const char *p
= instr
, *limit
;
190 if ((p
= memchr(instr
, ':', lenstr
)) == 0 ||
192 (p
= memchr(p
, ':', limit
- p
)) == 0) {
193 lencopy
= (size_t)lenstr
;
199 if (lencopy
+ 1 > buflen
) {
200 return (NSS_STR_PARSE_ERANGE
);
203 if (instr
!= buffer
) {
204 /* Overlapping buffer copies are OK */
205 (void) memmove(buffer
, instr
, lencopy
);
209 /* quick exit do not entry fill if not needed */
210 if (ent
== (void *)NULL
)
211 return (NSS_STR_PARSE_SUCCESS
);
213 black_magic
= (*instr
== '+' || *instr
== '-');
214 shadow
->sp_namp
= bufp
= buffer
;
216 shadow
->sp_lstchg
= -1;
219 shadow
->sp_warn
= -1;
220 shadow
->sp_inact
= -1;
221 shadow
->sp_expire
= -1;
224 if ((bufp
= strchr(bufp
, ':')) == 0) {
226 return (NSS_STR_PARSE_SUCCESS
);
228 return (NSS_STR_PARSE_PARSE
);
232 shadow
->sp_pwdp
= bufp
;
234 if ((bufp
= strchr(bufp
, ':')) == 0) {
236 return (NSS_STR_PARSE_SUCCESS
);
238 return (NSS_STR_PARSE_PARSE
);
242 } /* else p was set when we copied name and passwd into the buffer */
244 if (!getfield(&p
, limit
, 0, &shadow
->sp_lstchg
))
245 return (NSS_STR_PARSE_SUCCESS
);
246 if (!getfield(&p
, limit
, 0, &shadow
->sp_min
))
247 return (NSS_STR_PARSE_SUCCESS
);
248 if (!getfield(&p
, limit
, 0, &shadow
->sp_max
))
249 return (NSS_STR_PARSE_SUCCESS
);
250 if (!getfield(&p
, limit
, 0, &shadow
->sp_warn
))
251 return (NSS_STR_PARSE_SUCCESS
);
252 if (!getfield(&p
, limit
, 0, &shadow
->sp_inact
))
253 return (NSS_STR_PARSE_SUCCESS
);
254 if (!getfield(&p
, limit
, 0, &shadow
->sp_expire
))
255 return (NSS_STR_PARSE_SUCCESS
);
256 if (!getfield(&p
, limit
, 1, &shadow
->sp_flag
))
257 return (NSS_STR_PARSE_SUCCESS
);
259 /* Syntax error -- garbage at end of line */
260 return (NSS_STR_PARSE_PARSE
);
262 return (NSS_STR_PARSE_SUCCESS
);