passwd.c revision 194093
1230557Sjimharris/*-
2230557Sjimharris * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
3230557Sjimharris * All rights reserved.
4230557Sjimharris *
5230557Sjimharris * Redistribution and use in source and binary forms, with or without
6230557Sjimharris * modification, are permitted provided that the following conditions
7230557Sjimharris * are met:
8230557Sjimharris * 1. Redistributions of source code must retain the above copyright
9230557Sjimharris *    notice, this list of conditions and the following disclaimer.
10230557Sjimharris * 2. Redistributions in binary form must reproduce the above copyright
11230557Sjimharris *    notice, this list of conditions and the following disclaimer in the
12230557Sjimharris *    documentation and/or other materials provided with the distribution.
13230557Sjimharris *
14230557Sjimharris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15230557Sjimharris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16230557Sjimharris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17230557Sjimharris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18230557Sjimharris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19230557Sjimharris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20230557Sjimharris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21230557Sjimharris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22230557Sjimharris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23230557Sjimharris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24230557Sjimharris * SUCH DAMAGE.
25230557Sjimharris *
26230557Sjimharris */
27230557Sjimharris
28230557Sjimharris#include <sys/cdefs.h>
29230557Sjimharris__FBSDID("$FreeBSD: head/usr.sbin/nscd/agents/passwd.c 194093 2009-06-13 00:43:56Z des $");
30230557Sjimharris
31230557Sjimharris#include <sys/types.h>
32230557Sjimharris
33230557Sjimharris#include <assert.h>
34230557Sjimharris#include <nsswitch.h>
35230557Sjimharris#include <pwd.h>
36230557Sjimharris#include <stdlib.h>
37230557Sjimharris#include <string.h>
38230557Sjimharris
39230557Sjimharris#include "../debug.h"
40230557Sjimharris#include "passwd.h"
41230557Sjimharris
42230557Sjimharrisstatic int passwd_marshal_func(struct passwd *, char *, size_t *);
43230557Sjimharrisstatic int passwd_lookup_func(const char *, size_t, char **, size_t *);
44230557Sjimharrisstatic void *passwd_mp_init_func(void);
45230557Sjimharrisstatic int passwd_mp_lookup_func(char **, size_t *, void *);
46230557Sjimharrisstatic void passwd_mp_destroy_func(void *mdata);
47230557Sjimharris
48230557Sjimharrisstatic int
49230557Sjimharrispasswd_marshal_func(struct passwd *pwd, char *buffer, size_t *buffer_size)
50230557Sjimharris{
51230557Sjimharris	char		*p;
52230557Sjimharris	struct passwd	new_pwd;
53230557Sjimharris	size_t		desired_size, size;
54230557Sjimharris
55230557Sjimharris	TRACE_IN(passwd_marshal_func);
56230557Sjimharris	desired_size = sizeof(struct passwd) + sizeof(char *) +
57230557Sjimharris		strlen(pwd->pw_name) + 1;
58230557Sjimharris	if (pwd->pw_passwd != NULL)
59230557Sjimharris		desired_size += strlen(pwd->pw_passwd) + 1;
60230557Sjimharris	if (pwd->pw_class != NULL)
61230557Sjimharris		desired_size += strlen(pwd->pw_class) + 1;
62230557Sjimharris	if (pwd->pw_gecos != NULL)
63230557Sjimharris		desired_size += strlen(pwd->pw_gecos) + 1;
64230557Sjimharris	if (pwd->pw_dir != NULL)
65230557Sjimharris		desired_size += strlen(pwd->pw_dir) + 1;
66230557Sjimharris	if (pwd->pw_shell != NULL)
67230557Sjimharris		desired_size += strlen(pwd->pw_shell) + 1;
68230557Sjimharris
69230557Sjimharris	if ((*buffer_size < desired_size) || (buffer == NULL)) {
70230557Sjimharris		*buffer_size = desired_size;
71230557Sjimharris		TRACE_OUT(passwd_marshal_func);
72230557Sjimharris		return (NS_RETURN);
73230557Sjimharris	}
74230557Sjimharris
75230557Sjimharris	memcpy(&new_pwd, pwd, sizeof(struct passwd));
76230557Sjimharris	memset(buffer, 0, desired_size);
77230557Sjimharris
78230557Sjimharris	*buffer_size = desired_size;
79230557Sjimharris	p = buffer + sizeof(struct passwd) + sizeof(char *);
80230557Sjimharris	memcpy(buffer + sizeof(struct passwd), &p, sizeof(char *));
81230557Sjimharris
82230557Sjimharris	if (new_pwd.pw_name != NULL) {
83230557Sjimharris		size = strlen(new_pwd.pw_name);
84230557Sjimharris		memcpy(p, new_pwd.pw_name, size);
85230557Sjimharris		new_pwd.pw_name = p;
86230557Sjimharris		p += size + 1;
87230557Sjimharris	}
88230557Sjimharris
89230557Sjimharris	if (new_pwd.pw_passwd != NULL) {
90230557Sjimharris		size = strlen(new_pwd.pw_passwd);
91230557Sjimharris		memcpy(p, new_pwd.pw_passwd, size);
92230557Sjimharris		new_pwd.pw_passwd = p;
93230557Sjimharris		p += size + 1;
94230557Sjimharris	}
95230557Sjimharris
96230557Sjimharris	if (new_pwd.pw_class != NULL) {
97230557Sjimharris		size = strlen(new_pwd.pw_class);
98230557Sjimharris		memcpy(p, new_pwd.pw_class, size);
99230557Sjimharris		new_pwd.pw_class = p;
100230557Sjimharris		p += size + 1;
101230557Sjimharris	}
102230557Sjimharris
103230557Sjimharris	if (new_pwd.pw_gecos != NULL) {
104230557Sjimharris		size = strlen(new_pwd.pw_gecos);
105230557Sjimharris		memcpy(p, new_pwd.pw_gecos, size);
106230557Sjimharris		new_pwd.pw_gecos = p;
107230557Sjimharris		p += size + 1;
108230557Sjimharris	}
109230557Sjimharris
110230557Sjimharris	if (new_pwd.pw_dir != NULL) {
111230557Sjimharris		size = strlen(new_pwd.pw_dir);
112230557Sjimharris		memcpy(p, new_pwd.pw_dir, size);
113230557Sjimharris		new_pwd.pw_dir = p;
114230557Sjimharris		p += size + 1;
115230557Sjimharris	}
116230557Sjimharris
117230557Sjimharris	if (new_pwd.pw_shell != NULL) {
118230557Sjimharris		size = strlen(new_pwd.pw_shell);
119230557Sjimharris		memcpy(p, new_pwd.pw_shell, size);
120230557Sjimharris		new_pwd.pw_shell = p;
121230557Sjimharris		p += size + 1;
122230557Sjimharris	}
123230557Sjimharris
124230557Sjimharris	memcpy(buffer, &new_pwd, sizeof(struct passwd));
125230557Sjimharris	TRACE_OUT(passwd_marshal_func);
126230557Sjimharris	return (NS_SUCCESS);
127230557Sjimharris}
128230557Sjimharris
129230557Sjimharrisstatic int
130230557Sjimharrispasswd_lookup_func(const char *key, size_t key_size, char **buffer,
131230557Sjimharris	size_t *buffer_size)
132230557Sjimharris{
133230557Sjimharris	enum nss_lookup_type lookup_type;
134230557Sjimharris	char	*login;
135230557Sjimharris	size_t	size;
136230557Sjimharris	uid_t	uid;
137230557Sjimharris
138230557Sjimharris	struct passwd *result;
139230557Sjimharris
140230557Sjimharris	TRACE_IN(passwd_lookup_func);
141230557Sjimharris	assert(buffer != NULL);
142230557Sjimharris	assert(buffer_size != NULL);
143230557Sjimharris
144230557Sjimharris	if (key_size < sizeof(enum nss_lookup_type)) {
145230557Sjimharris		TRACE_OUT(passwd_lookup_func);
146230557Sjimharris		return (NS_UNAVAIL);
147230557Sjimharris	}
148230557Sjimharris	memcpy(&lookup_type, key, sizeof(enum nss_lookup_type));
149230557Sjimharris
150230557Sjimharris	switch (lookup_type) {
151230557Sjimharris	case nss_lt_name:
152230557Sjimharris		size = key_size - sizeof(enum nss_lookup_type)	+ 1;
153230557Sjimharris		login = (char *)calloc(1, size);
154230557Sjimharris		assert(login != NULL);
155230557Sjimharris		memcpy(login, key + sizeof(enum nss_lookup_type), size - 1);
156230557Sjimharris		break;
157230557Sjimharris	case nss_lt_id:
158230557Sjimharris		if (key_size < sizeof(enum nss_lookup_type) +
159230557Sjimharris			sizeof(uid_t)) {
160230557Sjimharris			TRACE_OUT(passwd_lookup_func);
161230557Sjimharris			return (NS_UNAVAIL);
162230557Sjimharris		}
163230557Sjimharris
164230557Sjimharris		memcpy(&uid, key + sizeof(enum nss_lookup_type), sizeof(uid_t));
165230557Sjimharris		break;
166230557Sjimharris	default:
167230557Sjimharris		TRACE_OUT(passwd_lookup_func);
168230557Sjimharris		return (NS_UNAVAIL);
169230557Sjimharris	}
170230557Sjimharris
171230557Sjimharris	switch (lookup_type) {
172230557Sjimharris	case nss_lt_name:
173230557Sjimharris		result = getpwnam(login);
174230557Sjimharris		free(login);
175230557Sjimharris		break;
176230557Sjimharris	case nss_lt_id:
177230557Sjimharris		result = getpwuid(uid);
178230557Sjimharris		break;
179230557Sjimharris	default:
180230557Sjimharris		/* SHOULD NOT BE REACHED */
181230557Sjimharris		break;
182230557Sjimharris	}
183230557Sjimharris
184230557Sjimharris	if (result != NULL) {
185230557Sjimharris		passwd_marshal_func(result, NULL, buffer_size);
186230557Sjimharris		*buffer = (char *)malloc(*buffer_size);
187230557Sjimharris		assert(*buffer != NULL);
188230557Sjimharris		passwd_marshal_func(result, *buffer, buffer_size);
189230557Sjimharris	}
190230557Sjimharris
191230557Sjimharris	TRACE_OUT(passwd_lookup_func);
192230557Sjimharris	return (result == NULL ? NS_NOTFOUND : NS_SUCCESS);
193230557Sjimharris}
194230557Sjimharris
195230557Sjimharrisstatic void *
196230557Sjimharrispasswd_mp_init_func(void)
197230557Sjimharris{
198230557Sjimharris	TRACE_IN(passwd_mp_init_func);
199230557Sjimharris	setpwent();
200230557Sjimharris	TRACE_OUT(passwd_mp_init_func);
201230557Sjimharris
202230557Sjimharris	return (NULL);
203230557Sjimharris}
204230557Sjimharris
205230557Sjimharrisstatic int
206230557Sjimharrispasswd_mp_lookup_func(char **buffer, size_t *buffer_size, void *mdata)
207230557Sjimharris{
208230557Sjimharris	struct passwd	*result;
209230557Sjimharris
210230557Sjimharris	TRACE_IN(passwd_mp_lookup_func);
211230557Sjimharris	result = getpwent();
212230557Sjimharris	if (result != NULL) {
213230557Sjimharris		passwd_marshal_func(result, NULL, buffer_size);
214230557Sjimharris		*buffer = (char *)malloc(*buffer_size);
215230557Sjimharris		assert(*buffer != NULL);
216230557Sjimharris		passwd_marshal_func(result, *buffer, buffer_size);
217230557Sjimharris	}
218230557Sjimharris
219230557Sjimharris	TRACE_OUT(passwd_mp_lookup_func);
220230557Sjimharris	return (result == NULL ? NS_NOTFOUND : NS_SUCCESS);
221230557Sjimharris}
222230557Sjimharris
223230557Sjimharrisstatic void
224230557Sjimharrispasswd_mp_destroy_func(void *mdata)
225230557Sjimharris{
226230557Sjimharris	TRACE_IN(passwd_mp_destroy_func);
227230557Sjimharris	TRACE_OUT(passwd_mp_destroy_func);
228230557Sjimharris}
229230557Sjimharris
230230557Sjimharrisstruct agent *
231230557Sjimharrisinit_passwd_agent(void)
232230557Sjimharris{
233230557Sjimharris	struct common_agent	*retval;
234230557Sjimharris
235230557Sjimharris	TRACE_IN(init_passwd_agent);
236230557Sjimharris	retval = (struct common_agent *)calloc(1, sizeof(struct common_agent));
237230557Sjimharris	assert(retval != NULL);
238230557Sjimharris
239230557Sjimharris	retval->parent.name = strdup("passwd");
240230557Sjimharris	assert(retval->parent.name != NULL);
241230557Sjimharris
242230557Sjimharris	retval->parent.type = COMMON_AGENT;
243230557Sjimharris	retval->lookup_func = passwd_lookup_func;
244230557Sjimharris
245230557Sjimharris	TRACE_OUT(init_passwd_agent);
246230557Sjimharris	return ((struct agent *)retval);
247230557Sjimharris}
248230557Sjimharris
249230557Sjimharrisstruct agent *
250230557Sjimharrisinit_passwd_mp_agent(void)
251230557Sjimharris{
252230557Sjimharris	struct multipart_agent	*retval;
253230557Sjimharris
254230557Sjimharris	TRACE_IN(init_passwd_mp_agent);
255230557Sjimharris	retval = (struct multipart_agent *)calloc(1,
256230557Sjimharris		sizeof(struct multipart_agent));
257230557Sjimharris	assert(retval != NULL);
258230557Sjimharris
259230557Sjimharris	retval->parent.name = strdup("passwd");
260230557Sjimharris	retval->parent.type = MULTIPART_AGENT;
261230557Sjimharris	retval->mp_init_func = passwd_mp_init_func;
262230557Sjimharris	retval->mp_lookup_func = passwd_mp_lookup_func;
263230557Sjimharris	retval->mp_destroy_func = passwd_mp_destroy_func;
264230557Sjimharris	assert(retval->parent.name != NULL);
265230557Sjimharris
266230557Sjimharris	TRACE_OUT(init_passwd_mp_agent);
267230557Sjimharris	return ((struct agent *)retval);
268230557Sjimharris}
269230557Sjimharris