xref: /onnv-gate/usr/src/lib/nsswitch/files/common/getpwnam.c (revision 8040:42abce45ef67)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52830Sdjl  * Common Development and Distribution License (the "License").
62830Sdjl  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*8040SBaban.Kenkre@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
232830Sdjl  * Use is subject to license terms.
240Sstevel@tonic-gate  *
252830Sdjl  * files/getpwnam.c -- "files" backend for nsswitch "passwd" database
260Sstevel@tonic-gate  */
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <pwd.h>
290Sstevel@tonic-gate #include <shadow.h>
300Sstevel@tonic-gate #include <unistd.h>		/* for PF_PATH */
310Sstevel@tonic-gate #include "files_common.h"
320Sstevel@tonic-gate #include <strings.h>
332830Sdjl #include <stdlib.h>
340Sstevel@tonic-gate 
352830Sdjl static uint_t
hash_pwname(nss_XbyY_args_t * argp,int keyhash,const char * line,int linelen)362830Sdjl hash_pwname(nss_XbyY_args_t *argp, int keyhash, const char *line,
372830Sdjl 	int linelen)
380Sstevel@tonic-gate {
392830Sdjl 	const char	*name;
402830Sdjl 	int		namelen, i;
412830Sdjl 	uint_t 		hash = 0;
420Sstevel@tonic-gate 
432830Sdjl 	if (keyhash) {
442830Sdjl 		name = argp->key.name;
452830Sdjl 		namelen = strlen(name);
462830Sdjl 	} else {
472830Sdjl 		name = line;
482830Sdjl 		namelen = 0;
492830Sdjl 		while (linelen-- && *line++ != ':')
502830Sdjl 			namelen++;
512830Sdjl 	}
520Sstevel@tonic-gate 
532830Sdjl 	for (i = 0; i < namelen; i++)
542830Sdjl 		hash = hash * 15 + name[i];
550Sstevel@tonic-gate 	return (hash);
560Sstevel@tonic-gate }
570Sstevel@tonic-gate 
582830Sdjl static uint_t
hash_pwuid(nss_XbyY_args_t * argp,int keyhash,const char * line,int linelen)592830Sdjl hash_pwuid(nss_XbyY_args_t *argp, int keyhash, const char *line,
602830Sdjl 	int linelen)
610Sstevel@tonic-gate {
622830Sdjl 	uint_t		id;
632830Sdjl 	const char	*linep, *limit, *end;
642830Sdjl 
652830Sdjl 	linep = line;
662830Sdjl 	limit = line + linelen;
672830Sdjl 
682830Sdjl 	if (keyhash)
692830Sdjl 		return ((uint_t)argp->key.uid);
702830Sdjl 
71*8040SBaban.Kenkre@Sun.COM 	while (linep < limit && *linep++ != ':') /* skip username */
72*8040SBaban.Kenkre@Sun.COM 		continue;
73*8040SBaban.Kenkre@Sun.COM 	while (linep < limit && *linep++ != ':') /* skip password */
74*8040SBaban.Kenkre@Sun.COM 		continue;
752830Sdjl 	if (linep == limit)
762830Sdjl 		return (UID_NOBODY);
772830Sdjl 
782830Sdjl 	/* uid */
792830Sdjl 	end = linep;
80*8040SBaban.Kenkre@Sun.COM 	id = (uint_t)strtoul(linep, (char **)&end, 10);
812830Sdjl 
822830Sdjl 	/* empty uid */
832830Sdjl 	if (linep == end)
842830Sdjl 		return (UID_NOBODY);
852830Sdjl 
862830Sdjl 	return (id);
870Sstevel@tonic-gate }
880Sstevel@tonic-gate 
890Sstevel@tonic-gate static files_hash_func hash_pw[2] = { hash_pwname, hash_pwuid };
900Sstevel@tonic-gate 
910Sstevel@tonic-gate static files_hash_t hashinfo = {
920Sstevel@tonic-gate 	DEFAULTMUTEX,
930Sstevel@tonic-gate 	sizeof (struct passwd),
940Sstevel@tonic-gate 	NSS_BUFLEN_PASSWD,
950Sstevel@tonic-gate 	2,
960Sstevel@tonic-gate 	hash_pw
970Sstevel@tonic-gate };
980Sstevel@tonic-gate 
990Sstevel@tonic-gate static int
check_pwname(nss_XbyY_args_t * argp,const char * line,int linelen)1002830Sdjl check_pwname(nss_XbyY_args_t *argp, const char *line, int linelen)
1010Sstevel@tonic-gate {
1022830Sdjl 	const char	*linep, *limit;
1032830Sdjl 	const char *keyp = argp->key.name;
1042830Sdjl 
1052830Sdjl 	linep = line;
1062830Sdjl 	limit = line + linelen;
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate 	/* +/- entries valid for compat source only */
1092830Sdjl 	if (linelen == 0 || *line == '+' || *line == '-')
1100Sstevel@tonic-gate 		return (0);
1112830Sdjl 	while (*keyp && linep < limit && *keyp == *linep) {
1122830Sdjl 		keyp++;
1132830Sdjl 		linep++;
1142830Sdjl 	}
1152830Sdjl 	return (linep < limit && *keyp == '\0' && *linep == ':');
1160Sstevel@tonic-gate }
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate static nss_status_t
getbyname(be,a)1190Sstevel@tonic-gate getbyname(be, a)
1200Sstevel@tonic-gate 	files_backend_ptr_t	be;
1210Sstevel@tonic-gate 	void			*a;
1220Sstevel@tonic-gate {
1230Sstevel@tonic-gate 	return (_nss_files_XY_hash(be, a, 0, &hashinfo, 0, check_pwname));
1240Sstevel@tonic-gate }
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate static int
check_pwuid(nss_XbyY_args_t * argp,const char * line,int linelen)1272830Sdjl check_pwuid(nss_XbyY_args_t *argp, const char *line, int linelen)
1280Sstevel@tonic-gate {
1292830Sdjl 	const char	*linep, *limit, *end;
130*8040SBaban.Kenkre@Sun.COM 	ulong_t		pw_uid;
1312830Sdjl 
1322830Sdjl 	linep = line;
1332830Sdjl 	limit = line + linelen;
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate 	/* +/- entries valid for compat source only */
1362830Sdjl 	if (linelen == 0 || *line == '+' || *line == '-')
1372830Sdjl 		return (0);
1382830Sdjl 
139*8040SBaban.Kenkre@Sun.COM 	while (linep < limit && *linep++ != ':') /* skip username */
140*8040SBaban.Kenkre@Sun.COM 		continue;
141*8040SBaban.Kenkre@Sun.COM 	while (linep < limit && *linep++ != ':') /* skip password */
142*8040SBaban.Kenkre@Sun.COM 		continue;
1432830Sdjl 	if (linep == limit)
1440Sstevel@tonic-gate 		return (0);
1452830Sdjl 
1462830Sdjl 	/* uid */
1472830Sdjl 	end = linep;
148*8040SBaban.Kenkre@Sun.COM 	pw_uid = strtoul(linep, (char **)&end, 10);
1492830Sdjl 
150*8040SBaban.Kenkre@Sun.COM 	/* check if the uid is empty or overflows */
151*8040SBaban.Kenkre@Sun.COM 	if (linep == end || pw_uid > UINT32_MAX)
1522830Sdjl 		return (0);
1532830Sdjl 
154*8040SBaban.Kenkre@Sun.COM 	return ((uid_t)pw_uid == argp->key.uid);
1550Sstevel@tonic-gate }
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate static nss_status_t
getbyuid(be,a)1580Sstevel@tonic-gate getbyuid(be, a)
1590Sstevel@tonic-gate 	files_backend_ptr_t	be;
1600Sstevel@tonic-gate 	void			*a;
1610Sstevel@tonic-gate {
162*8040SBaban.Kenkre@Sun.COM 	nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
163*8040SBaban.Kenkre@Sun.COM 
164*8040SBaban.Kenkre@Sun.COM 	if (argp->key.uid > MAXUID)
165*8040SBaban.Kenkre@Sun.COM 		return (NSS_NOTFOUND);
166*8040SBaban.Kenkre@Sun.COM 	return (_nss_files_XY_hash(be, argp, 0, &hashinfo, 1, check_pwuid));
167*8040SBaban.Kenkre@Sun.COM }
168*8040SBaban.Kenkre@Sun.COM 
169*8040SBaban.Kenkre@Sun.COM /*
170*8040SBaban.Kenkre@Sun.COM  * Validates passwd entry replacing uid/gid > MAXUID by ID_NOBODY.
171*8040SBaban.Kenkre@Sun.COM  */
172*8040SBaban.Kenkre@Sun.COM int
validate_passwd_ids(char * line,int * linelenp,int buflen,int extra_chars)173*8040SBaban.Kenkre@Sun.COM validate_passwd_ids(char *line, int *linelenp, int buflen, int extra_chars)
174*8040SBaban.Kenkre@Sun.COM {
175*8040SBaban.Kenkre@Sun.COM 	char	*linep, *limit, *uidp, *gidp;
176*8040SBaban.Kenkre@Sun.COM 	uid_t	uid;
177*8040SBaban.Kenkre@Sun.COM 	gid_t	gid;
178*8040SBaban.Kenkre@Sun.COM 	ulong_t	uidl, gidl;
179*8040SBaban.Kenkre@Sun.COM 	int	olduidlen, oldgidlen, idlen;
180*8040SBaban.Kenkre@Sun.COM 	int	linelen = *linelenp, newlinelen;
181*8040SBaban.Kenkre@Sun.COM 
182*8040SBaban.Kenkre@Sun.COM 	/*
183*8040SBaban.Kenkre@Sun.COM 	 * +name entries in passwd(4) do not override uid and gid
184*8040SBaban.Kenkre@Sun.COM 	 * values. Therefore no need to validate the ids in these
185*8040SBaban.Kenkre@Sun.COM 	 * entries.
186*8040SBaban.Kenkre@Sun.COM 	 */
187*8040SBaban.Kenkre@Sun.COM 	if (linelen == 0 || *line == '+' || *line == '-')
188*8040SBaban.Kenkre@Sun.COM 		return (NSS_STR_PARSE_SUCCESS);
189*8040SBaban.Kenkre@Sun.COM 
190*8040SBaban.Kenkre@Sun.COM 	linep = line;
191*8040SBaban.Kenkre@Sun.COM 	limit = line + linelen;
192*8040SBaban.Kenkre@Sun.COM 
193*8040SBaban.Kenkre@Sun.COM 	while (linep < limit && *linep++ != ':') /* skip username */
194*8040SBaban.Kenkre@Sun.COM 		continue;
195*8040SBaban.Kenkre@Sun.COM 	while (linep < limit && *linep++ != ':') /* skip password */
196*8040SBaban.Kenkre@Sun.COM 		continue;
197*8040SBaban.Kenkre@Sun.COM 	if (linep == limit)
198*8040SBaban.Kenkre@Sun.COM 		return (NSS_STR_PARSE_PARSE);
199*8040SBaban.Kenkre@Sun.COM 
200*8040SBaban.Kenkre@Sun.COM 	uidp = linep;
201*8040SBaban.Kenkre@Sun.COM 	uidl = strtoul(uidp, (char **)&linep, 10); /* grab uid */
202*8040SBaban.Kenkre@Sun.COM 	olduidlen = linep - uidp;
203*8040SBaban.Kenkre@Sun.COM 	if (++linep >= limit || olduidlen == 0)
204*8040SBaban.Kenkre@Sun.COM 		return (NSS_STR_PARSE_PARSE);
205*8040SBaban.Kenkre@Sun.COM 
206*8040SBaban.Kenkre@Sun.COM 	gidp = linep;
207*8040SBaban.Kenkre@Sun.COM 	gidl = strtoul(gidp, (char **)&linep, 10); /* grab gid */
208*8040SBaban.Kenkre@Sun.COM 	oldgidlen = linep - gidp;
209*8040SBaban.Kenkre@Sun.COM 	if (linep >= limit || oldgidlen == 0)
210*8040SBaban.Kenkre@Sun.COM 		return (NSS_STR_PARSE_PARSE);
211*8040SBaban.Kenkre@Sun.COM 
212*8040SBaban.Kenkre@Sun.COM 	if (uidl <= MAXUID && gidl <= MAXUID)
213*8040SBaban.Kenkre@Sun.COM 		return (NSS_STR_PARSE_SUCCESS);
214*8040SBaban.Kenkre@Sun.COM 	uid = (uidl > MAXUID) ? UID_NOBODY : (uid_t)uidl;
215*8040SBaban.Kenkre@Sun.COM 	gid = (gidl > MAXUID) ? GID_NOBODY : (gid_t)gidl;
216*8040SBaban.Kenkre@Sun.COM 
217*8040SBaban.Kenkre@Sun.COM 	/* Check if we have enough space in the buffer */
218*8040SBaban.Kenkre@Sun.COM 	idlen = snprintf(NULL, 0, "%u:%u", uid, gid);
219*8040SBaban.Kenkre@Sun.COM 	newlinelen = linelen + idlen - olduidlen - oldgidlen - 1;
220*8040SBaban.Kenkre@Sun.COM 	if (newlinelen + extra_chars > buflen)
221*8040SBaban.Kenkre@Sun.COM 		return (NSS_STR_PARSE_ERANGE);
222*8040SBaban.Kenkre@Sun.COM 
223*8040SBaban.Kenkre@Sun.COM 	/* Replace ephemeral ids by ID_NOBODY */
224*8040SBaban.Kenkre@Sun.COM 	(void) bcopy(linep, uidp + idlen, limit - linep + extra_chars);
225*8040SBaban.Kenkre@Sun.COM 	(void) snprintf(uidp, idlen + 1, "%u:%u", uid, gid);
226*8040SBaban.Kenkre@Sun.COM 	*(uidp + idlen) = ':'; /* restore : that was overwritten by snprintf */
227*8040SBaban.Kenkre@Sun.COM 	*linelenp = newlinelen;
228*8040SBaban.Kenkre@Sun.COM 	return (NSS_STR_PARSE_SUCCESS);
2290Sstevel@tonic-gate }
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate static files_backend_op_t passwd_ops[] = {
2320Sstevel@tonic-gate 	_nss_files_destr,
2330Sstevel@tonic-gate 	_nss_files_endent,
2340Sstevel@tonic-gate 	_nss_files_setent,
2350Sstevel@tonic-gate 	_nss_files_getent_rigid,
2360Sstevel@tonic-gate 	getbyname,
2370Sstevel@tonic-gate 	getbyuid
2380Sstevel@tonic-gate };
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate /*ARGSUSED*/
2410Sstevel@tonic-gate nss_backend_t *
_nss_files_passwd_constr(dummy1,dummy2,dummy3)2420Sstevel@tonic-gate _nss_files_passwd_constr(dummy1, dummy2, dummy3)
2430Sstevel@tonic-gate 	const char	*dummy1, *dummy2, *dummy3;
2440Sstevel@tonic-gate {
2450Sstevel@tonic-gate 	return (_nss_files_constr(passwd_ops,
2460Sstevel@tonic-gate 				sizeof (passwd_ops) / sizeof (passwd_ops[0]),
2470Sstevel@tonic-gate 				PF_PATH,
2480Sstevel@tonic-gate 				NSS_LINELEN_PASSWD,
2490Sstevel@tonic-gate 				&hashinfo));
2500Sstevel@tonic-gate }
251