xref: /illumos-gate/usr/src/lib/nsswitch/files/common/getpwnam.c (revision d2ec54f7875f7e05edd56195adbeb593c947763f)
1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  *
25  * files/getpwnam.c -- "files" backend for nsswitch "passwd" database
26  */
27 
28 #pragma ident	"%Z%%M%	%I%	%E% SMI"
29 
30 #include <pwd.h>
31 #include <shadow.h>
32 #include <unistd.h>		/* for PF_PATH */
33 #include "files_common.h"
34 #include <strings.h>
35 #include <stdlib.h>
36 
37 static uint_t
38 hash_pwname(nss_XbyY_args_t *argp, int keyhash, const char *line,
39 	int linelen)
40 {
41 	const char	*name;
42 	int		namelen, i;
43 	uint_t 		hash = 0;
44 
45 	if (keyhash) {
46 		name = argp->key.name;
47 		namelen = strlen(name);
48 	} else {
49 		name = line;
50 		namelen = 0;
51 		while (linelen-- && *line++ != ':')
52 			namelen++;
53 	}
54 
55 	for (i = 0; i < namelen; i++)
56 		hash = hash * 15 + name[i];
57 	return (hash);
58 }
59 
60 static uint_t
61 hash_pwuid(nss_XbyY_args_t *argp, int keyhash, const char *line,
62 	int linelen)
63 {
64 	uint_t		id;
65 	const char	*linep, *limit, *end;
66 
67 	linep = line;
68 	limit = line + linelen;
69 
70 	if (keyhash)
71 		return ((uint_t)argp->key.uid);
72 
73 	/* skip username */
74 	while (linep < limit && *linep++ != ':');
75 	/* skip password */
76 	while (linep < limit && *linep++ != ':');
77 	if (linep == limit)
78 		return (UID_NOBODY);
79 
80 	/* uid */
81 	end = linep;
82 	id = (uint_t)strtol(linep, (char **)&end, 10);
83 
84 	/* empty uid */
85 	if (linep == end)
86 		return (UID_NOBODY);
87 
88 	return (id);
89 }
90 
91 static files_hash_func hash_pw[2] = { hash_pwname, hash_pwuid };
92 
93 static files_hash_t hashinfo = {
94 	DEFAULTMUTEX,
95 	sizeof (struct passwd),
96 	NSS_BUFLEN_PASSWD,
97 	2,
98 	hash_pw
99 };
100 
101 static int
102 check_pwname(nss_XbyY_args_t *argp, const char *line, int linelen)
103 {
104 	const char	*linep, *limit;
105 	const char *keyp = argp->key.name;
106 
107 	linep = line;
108 	limit = line + linelen;
109 
110 	/* +/- entries valid for compat source only */
111 	if (linelen == 0 || *line == '+' || *line == '-')
112 		return (0);
113 	while (*keyp && linep < limit && *keyp == *linep) {
114 		keyp++;
115 		linep++;
116 	}
117 	return (linep < limit && *keyp == '\0' && *linep == ':');
118 }
119 
120 static nss_status_t
121 getbyname(be, a)
122 	files_backend_ptr_t	be;
123 	void			*a;
124 {
125 	return (_nss_files_XY_hash(be, a, 0, &hashinfo, 0, check_pwname));
126 }
127 
128 static int
129 check_pwuid(nss_XbyY_args_t *argp, const char *line, int linelen)
130 {
131 	const char	*linep, *limit, *end;
132 	uid_t		pw_uid;
133 
134 	linep = line;
135 	limit = line + linelen;
136 
137 	/* +/- entries valid for compat source only */
138 	if (linelen == 0 || *line == '+' || *line == '-')
139 		return (0);
140 
141 	/* skip username */
142 	while (linep < limit && *linep++ != ':');
143 	/* skip password */
144 	while (linep < limit && *linep++ != ':');
145 	if (linep == limit)
146 		return (0);
147 
148 	/* uid */
149 	end = linep;
150 	pw_uid = (uid_t)strtol(linep, (char **)&end, 10);
151 
152 	/* empty uid is not valid */
153 	if (linep == end)
154 		return (0);
155 
156 	return (pw_uid == argp->key.uid);
157 }
158 
159 static nss_status_t
160 getbyuid(be, a)
161 	files_backend_ptr_t	be;
162 	void			*a;
163 {
164 	return (_nss_files_XY_hash(be, a, 0, &hashinfo, 1, check_pwuid));
165 }
166 
167 static files_backend_op_t passwd_ops[] = {
168 	_nss_files_destr,
169 	_nss_files_endent,
170 	_nss_files_setent,
171 	_nss_files_getent_rigid,
172 	getbyname,
173 	getbyuid
174 };
175 
176 /*ARGSUSED*/
177 nss_backend_t *
178 _nss_files_passwd_constr(dummy1, dummy2, dummy3)
179 	const char	*dummy1, *dummy2, *dummy3;
180 {
181 	return (_nss_files_constr(passwd_ops,
182 				sizeof (passwd_ops) / sizeof (passwd_ops[0]),
183 				PF_PATH,
184 				NSS_LINELEN_PASSWD,
185 				&hashinfo));
186 }
187