1158115Sume/*-
2158115Sume * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
3158115Sume * All rights reserved.
4158115Sume *
5158115Sume * Redistribution and use in source and binary forms, with or without
6158115Sume * modification, are permitted provided that the following conditions
7158115Sume * are met:
8158115Sume * 1. Redistributions of source code must retain the above copyright
9158115Sume *    notice, this list of conditions and the following disclaimer.
10158115Sume * 2. Redistributions in binary form must reproduce the above copyright
11158115Sume *    notice, this list of conditions and the following disclaimer in the
12158115Sume *    documentation and/or other materials provided with the distribution.
13158115Sume *
14158115Sume * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15158115Sume * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16158115Sume * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17158115Sume * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18158115Sume * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19158115Sume * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20158115Sume * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21158115Sume * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22158115Sume * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23158115Sume * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24158115Sume * SUCH DAMAGE.
25158115Sume *
26158115Sume */
27158115Sume
28158115Sume#include <sys/cdefs.h>
29158115Sume__FBSDID("$FreeBSD$");
30158115Sume
31158115Sume#include <sys/param.h>
32194093Sdes
33158115Sume#include <assert.h>
34194093Sdes#include <grp.h>
35158115Sume#include <nsswitch.h>
36194093Sdes#include <stdlib.h>
37158115Sume#include <string.h>
38194093Sdes
39158115Sume#include "../debug.h"
40194094Sdes#include "group.h"
41158115Sume
42158115Sumestatic int group_marshal_func(struct group *, char *, size_t *);
43158115Sumestatic int group_lookup_func(const char *, size_t, char **, size_t *);
44194087Sdesstatic void *group_mp_init_func(void);
45158115Sumestatic int group_mp_lookup_func(char **, size_t *, void *);
46158115Sumestatic void group_mp_destroy_func(void *);
47158115Sume
48158115Sumestatic int
49158115Sumegroup_marshal_func(struct group *grp, char *buffer, size_t *buffer_size)
50158115Sume{
51158115Sume	struct group new_grp;
52158115Sume	size_t desired_size, size, mem_size;
53158115Sume	char *p, **mem;
54158115Sume
55158115Sume	TRACE_IN(group_marshal_func);
56158115Sume	desired_size = ALIGNBYTES + sizeof(struct group) + sizeof(char *);
57158115Sume
58158115Sume	if (grp->gr_name != NULL)
59158115Sume		desired_size += strlen(grp->gr_name) + 1;
60158115Sume	if (grp->gr_passwd != NULL)
61158115Sume		desired_size += strlen(grp->gr_passwd) + 1;
62158115Sume
63158115Sume	if (grp->gr_mem != NULL) {
64158115Sume		mem_size = 0;
65158115Sume		for (mem = grp->gr_mem; *mem; ++mem) {
66158115Sume			desired_size += strlen(*mem) + 1;
67158115Sume			++mem_size;
68158115Sume		}
69158115Sume
70158115Sume		desired_size += ALIGNBYTES + (mem_size + 1) * sizeof(char *);
71158115Sume	}
72158115Sume
73158115Sume	if ((desired_size > *buffer_size) || (buffer == NULL)) {
74158115Sume		*buffer_size = desired_size;
75158115Sume		TRACE_OUT(group_marshal_func);
76158115Sume		return (NS_RETURN);
77158115Sume	}
78158115Sume
79158115Sume	memcpy(&new_grp, grp, sizeof(struct group));
80158115Sume	memset(buffer, 0, desired_size);
81158115Sume
82158115Sume	*buffer_size = desired_size;
83158115Sume	p = buffer + sizeof(struct group) + sizeof(char *);
84158115Sume	memcpy(buffer + sizeof(struct group), &p, sizeof(char *));
85158115Sume	p = (char *)ALIGN(p);
86158115Sume
87158115Sume	if (new_grp.gr_name != NULL) {
88158115Sume		size = strlen(new_grp.gr_name);
89158115Sume		memcpy(p, new_grp.gr_name, size);
90158115Sume		new_grp.gr_name = p;
91158115Sume		p += size + 1;
92158115Sume	}
93158115Sume
94158115Sume	if (new_grp.gr_passwd != NULL) {
95158115Sume		size = strlen(new_grp.gr_passwd);
96158115Sume		memcpy(p, new_grp.gr_passwd, size);
97158115Sume		new_grp.gr_passwd = p;
98158115Sume		p += size + 1;
99158115Sume	}
100158115Sume
101158115Sume	if (new_grp.gr_mem != NULL) {
102158115Sume		p = (char *)ALIGN(p);
103158115Sume		memcpy(p, new_grp.gr_mem, sizeof(char *) * mem_size);
104158115Sume		new_grp.gr_mem = (char **)p;
105158115Sume		p += sizeof(char *) * (mem_size + 1);
106158115Sume
107158115Sume		for (mem = new_grp.gr_mem; *mem; ++mem) {
108158115Sume			size = strlen(*mem);
109158115Sume			memcpy(p, *mem, size);
110158115Sume			*mem = p;
111158115Sume			p += size + 1;
112158115Sume		}
113158115Sume	}
114158115Sume
115158115Sume	memcpy(buffer, &new_grp, sizeof(struct group));
116158115Sume	TRACE_OUT(group_marshal_func);
117158115Sume	return (NS_SUCCESS);
118158115Sume}
119158115Sume
120158115Sumestatic int
121158115Sumegroup_lookup_func(const char *key, size_t key_size, char **buffer,
122158115Sume	size_t *buffer_size)
123158115Sume{
124158115Sume	enum nss_lookup_type lookup_type;
125158115Sume	char	*name;
126158115Sume	size_t	size;
127158115Sume	gid_t	gid;
128158115Sume
129158115Sume	struct group *result;
130158115Sume
131158115Sume	TRACE_IN(group_lookup_func);
132158115Sume	assert(buffer != NULL);
133158115Sume	assert(buffer_size != NULL);
134158115Sume
135158115Sume	if (key_size < sizeof(enum nss_lookup_type)) {
136158115Sume		TRACE_OUT(group_lookup_func);
137158115Sume		return (NS_UNAVAIL);
138158115Sume	}
139158115Sume	memcpy(&lookup_type, key, sizeof(enum nss_lookup_type));
140158115Sume
141158115Sume	switch (lookup_type) {
142158115Sume	case nss_lt_name:
143158115Sume		size = key_size - sizeof(enum nss_lookup_type)	+ 1;
144194104Sdes		name = calloc(1, size);
145158115Sume		assert(name != NULL);
146158115Sume		memcpy(name, key + sizeof(enum nss_lookup_type), size - 1);
147158115Sume		break;
148158115Sume	case nss_lt_id:
149158115Sume		if (key_size < sizeof(enum nss_lookup_type) +
150158115Sume			sizeof(gid_t)) {
151158115Sume			TRACE_OUT(passwd_lookup_func);
152158115Sume			return (NS_UNAVAIL);
153158115Sume		}
154158115Sume
155158115Sume		memcpy(&gid, key + sizeof(enum nss_lookup_type), sizeof(gid_t));
156158115Sume		break;
157158115Sume	default:
158158115Sume		TRACE_OUT(group_lookup_func);
159158115Sume		return (NS_UNAVAIL);
160158115Sume	}
161158115Sume
162158115Sume	switch (lookup_type) {
163158115Sume	case nss_lt_name:
164158115Sume		TRACE_STR(name);
165158115Sume		result = getgrnam(name);
166158115Sume		free(name);
167158115Sume		break;
168158115Sume	case nss_lt_id:
169158115Sume		result = getgrgid(gid);
170158115Sume		break;
171158115Sume	default:
172158115Sume		/* SHOULD NOT BE REACHED */
173158115Sume		break;
174158115Sume	}
175158115Sume
176158115Sume	if (result != NULL) {
177158115Sume		group_marshal_func(result, NULL, buffer_size);
178194104Sdes		*buffer = malloc(*buffer_size);
179158115Sume		assert(*buffer != NULL);
180158115Sume		group_marshal_func(result, *buffer, buffer_size);
181158115Sume	}
182158115Sume
183158115Sume	TRACE_OUT(group_lookup_func);
184158115Sume	return (result == NULL ? NS_NOTFOUND : NS_SUCCESS);
185158115Sume}
186158115Sume
187158115Sumestatic void *
188194087Sdesgroup_mp_init_func(void)
189158115Sume{
190158115Sume	TRACE_IN(group_mp_init_func);
191158115Sume	setgrent();
192158115Sume	TRACE_OUT(group_mp_init_func);
193158115Sume
194158115Sume	return (NULL);
195158115Sume}
196158115Sume
197158115Sumestatic int
198158115Sumegroup_mp_lookup_func(char **buffer, size_t *buffer_size, void *mdata)
199158115Sume{
200158115Sume	struct group *result;
201158115Sume
202158115Sume	TRACE_IN(group_mp_lookup_func);
203158115Sume	result = getgrent();
204158115Sume	if (result != NULL) {
205158115Sume		group_marshal_func(result, NULL, buffer_size);
206194104Sdes		*buffer = malloc(*buffer_size);
207158115Sume		assert(*buffer != NULL);
208158115Sume		group_marshal_func(result, *buffer, buffer_size);
209158115Sume	}
210158115Sume
211158115Sume	TRACE_OUT(group_mp_lookup_func);
212158115Sume	return (result == NULL ? NS_NOTFOUND : NS_SUCCESS);
213158115Sume}
214158115Sume
215158115Sumestatic void
216158115Sumegroup_mp_destroy_func(void *mdata)
217158115Sume{
218158115Sume	TRACE_IN(group_mp_destroy_func);
219158115Sume	TRACE_OUT(group_mp_destroy_func);
220158115Sume}
221158115Sume
222158115Sumestruct agent *
223194087Sdesinit_group_agent(void)
224158115Sume{
225158115Sume	struct common_agent	*retval;
226158115Sume
227158115Sume	TRACE_IN(init_group_agent);
228194104Sdes	retval = calloc(1, sizeof(*retval));
229158115Sume	assert(retval != NULL);
230158115Sume
231158115Sume	retval->parent.name = strdup("group");
232158115Sume	assert(retval->parent.name != NULL);
233158115Sume
234158115Sume	retval->parent.type = COMMON_AGENT;
235158115Sume	retval->lookup_func = group_lookup_func;
236158115Sume
237158115Sume	TRACE_OUT(init_group_agent);
238158115Sume	return ((struct agent *)retval);
239158115Sume}
240158115Sume
241158115Sumestruct agent *
242194087Sdesinit_group_mp_agent(void)
243158115Sume{
244158115Sume	struct multipart_agent	*retval;
245158115Sume
246158115Sume	TRACE_IN(init_group_mp_agent);
247194104Sdes	retval = calloc(1,
248194104Sdes		sizeof(*retval));
249158115Sume	assert(retval != NULL);
250158115Sume
251158115Sume	retval->parent.name = strdup("group");
252158115Sume	retval->parent.type = MULTIPART_AGENT;
253158115Sume	retval->mp_init_func = group_mp_init_func;
254158115Sume	retval->mp_lookup_func = group_mp_lookup_func;
255158115Sume	retval->mp_destroy_func = group_mp_destroy_func;
256158115Sume	assert(retval->parent.name != NULL);
257158115Sume
258158115Sume	TRACE_OUT(init_group_mp_agent);
259158115Sume	return ((struct agent *)retval);
260158115Sume}
261