1 /*-
2 * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28 #include <sys/types.h>
29
30 #include <assert.h>
31 #include <nsswitch.h>
32 #include <pwd.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #include "../debug.h"
37 #include "passwd.h"
38
39 static int passwd_marshal_func(struct passwd *, char *, size_t *);
40 static int passwd_lookup_func(const char *, size_t, char **, size_t *);
41 static void *passwd_mp_init_func(void);
42 static int passwd_mp_lookup_func(char **, size_t *, void *);
43 static void passwd_mp_destroy_func(void *mdata);
44
45 static int
passwd_marshal_func(struct passwd * pwd,char * buffer,size_t * buffer_size)46 passwd_marshal_func(struct passwd *pwd, char *buffer, size_t *buffer_size)
47 {
48 char *p;
49 struct passwd new_pwd;
50 size_t desired_size, size;
51
52 TRACE_IN(passwd_marshal_func);
53 desired_size = sizeof(struct passwd) + sizeof(char *) +
54 strlen(pwd->pw_name) + 1;
55 if (pwd->pw_passwd != NULL)
56 desired_size += strlen(pwd->pw_passwd) + 1;
57 if (pwd->pw_class != NULL)
58 desired_size += strlen(pwd->pw_class) + 1;
59 if (pwd->pw_gecos != NULL)
60 desired_size += strlen(pwd->pw_gecos) + 1;
61 if (pwd->pw_dir != NULL)
62 desired_size += strlen(pwd->pw_dir) + 1;
63 if (pwd->pw_shell != NULL)
64 desired_size += strlen(pwd->pw_shell) + 1;
65
66 if ((*buffer_size < desired_size) || (buffer == NULL)) {
67 *buffer_size = desired_size;
68 TRACE_OUT(passwd_marshal_func);
69 return (NS_RETURN);
70 }
71
72 memcpy(&new_pwd, pwd, sizeof(struct passwd));
73 memset(buffer, 0, desired_size);
74
75 *buffer_size = desired_size;
76 p = buffer + sizeof(struct passwd) + sizeof(char *);
77 memcpy(buffer + sizeof(struct passwd), &p, sizeof(char *));
78
79 if (new_pwd.pw_name != NULL) {
80 size = strlen(new_pwd.pw_name);
81 memcpy(p, new_pwd.pw_name, size);
82 new_pwd.pw_name = p;
83 p += size + 1;
84 }
85
86 if (new_pwd.pw_passwd != NULL) {
87 size = strlen(new_pwd.pw_passwd);
88 memcpy(p, new_pwd.pw_passwd, size);
89 new_pwd.pw_passwd = p;
90 p += size + 1;
91 }
92
93 if (new_pwd.pw_class != NULL) {
94 size = strlen(new_pwd.pw_class);
95 memcpy(p, new_pwd.pw_class, size);
96 new_pwd.pw_class = p;
97 p += size + 1;
98 }
99
100 if (new_pwd.pw_gecos != NULL) {
101 size = strlen(new_pwd.pw_gecos);
102 memcpy(p, new_pwd.pw_gecos, size);
103 new_pwd.pw_gecos = p;
104 p += size + 1;
105 }
106
107 if (new_pwd.pw_dir != NULL) {
108 size = strlen(new_pwd.pw_dir);
109 memcpy(p, new_pwd.pw_dir, size);
110 new_pwd.pw_dir = p;
111 p += size + 1;
112 }
113
114 if (new_pwd.pw_shell != NULL) {
115 size = strlen(new_pwd.pw_shell);
116 memcpy(p, new_pwd.pw_shell, size);
117 new_pwd.pw_shell = p;
118 p += size + 1;
119 }
120
121 memcpy(buffer, &new_pwd, sizeof(struct passwd));
122 TRACE_OUT(passwd_marshal_func);
123 return (NS_SUCCESS);
124 }
125
126 static int
passwd_lookup_func(const char * key,size_t key_size,char ** buffer,size_t * buffer_size)127 passwd_lookup_func(const char *key, size_t key_size, char **buffer,
128 size_t *buffer_size)
129 {
130 enum nss_lookup_type lookup_type;
131 char *login;
132 size_t size;
133 uid_t uid;
134
135 struct passwd *result;
136
137 TRACE_IN(passwd_lookup_func);
138 assert(buffer != NULL);
139 assert(buffer_size != NULL);
140
141 if (key_size < sizeof(enum nss_lookup_type)) {
142 TRACE_OUT(passwd_lookup_func);
143 return (NS_UNAVAIL);
144 }
145 memcpy(&lookup_type, key, sizeof(enum nss_lookup_type));
146
147 switch (lookup_type) {
148 case nss_lt_name:
149 size = key_size - sizeof(enum nss_lookup_type) + 1;
150 login = calloc(1, size);
151 assert(login != NULL);
152 memcpy(login, key + sizeof(enum nss_lookup_type), size - 1);
153 break;
154 case nss_lt_id:
155 if (key_size < sizeof(enum nss_lookup_type) +
156 sizeof(uid_t)) {
157 TRACE_OUT(passwd_lookup_func);
158 return (NS_UNAVAIL);
159 }
160
161 memcpy(&uid, key + sizeof(enum nss_lookup_type), sizeof(uid_t));
162 break;
163 default:
164 TRACE_OUT(passwd_lookup_func);
165 return (NS_UNAVAIL);
166 }
167
168 switch (lookup_type) {
169 case nss_lt_name:
170 result = getpwnam(login);
171 free(login);
172 break;
173 case nss_lt_id:
174 result = getpwuid(uid);
175 break;
176 default:
177 /* SHOULD NOT BE REACHED */
178 break;
179 }
180
181 if (result != NULL) {
182 passwd_marshal_func(result, NULL, buffer_size);
183 *buffer = malloc(*buffer_size);
184 assert(*buffer != NULL);
185 passwd_marshal_func(result, *buffer, buffer_size);
186 }
187
188 TRACE_OUT(passwd_lookup_func);
189 return (result == NULL ? NS_NOTFOUND : NS_SUCCESS);
190 }
191
192 static void *
passwd_mp_init_func(void)193 passwd_mp_init_func(void)
194 {
195 TRACE_IN(passwd_mp_init_func);
196 setpwent();
197 TRACE_OUT(passwd_mp_init_func);
198
199 return (NULL);
200 }
201
202 static int
passwd_mp_lookup_func(char ** buffer,size_t * buffer_size,void * mdata)203 passwd_mp_lookup_func(char **buffer, size_t *buffer_size, void *mdata)
204 {
205 struct passwd *result;
206
207 TRACE_IN(passwd_mp_lookup_func);
208 result = getpwent();
209 if (result != NULL) {
210 passwd_marshal_func(result, NULL, buffer_size);
211 *buffer = malloc(*buffer_size);
212 assert(*buffer != NULL);
213 passwd_marshal_func(result, *buffer, buffer_size);
214 }
215
216 TRACE_OUT(passwd_mp_lookup_func);
217 return (result == NULL ? NS_NOTFOUND : NS_SUCCESS);
218 }
219
220 static void
passwd_mp_destroy_func(void * mdata)221 passwd_mp_destroy_func(void *mdata)
222 {
223 TRACE_IN(passwd_mp_destroy_func);
224 TRACE_OUT(passwd_mp_destroy_func);
225 }
226
227 struct agent *
init_passwd_agent(void)228 init_passwd_agent(void)
229 {
230 struct common_agent *retval;
231
232 TRACE_IN(init_passwd_agent);
233 retval = calloc(1, sizeof(*retval));
234 assert(retval != NULL);
235
236 retval->parent.name = strdup("passwd");
237 assert(retval->parent.name != NULL);
238
239 retval->parent.type = COMMON_AGENT;
240 retval->lookup_func = passwd_lookup_func;
241
242 TRACE_OUT(init_passwd_agent);
243 return ((struct agent *)retval);
244 }
245
246 struct agent *
init_passwd_mp_agent(void)247 init_passwd_mp_agent(void)
248 {
249 struct multipart_agent *retval;
250
251 TRACE_IN(init_passwd_mp_agent);
252 retval = calloc(1,
253 sizeof(*retval));
254 assert(retval != NULL);
255
256 retval->parent.name = strdup("passwd");
257 retval->parent.type = MULTIPART_AGENT;
258 retval->mp_init_func = passwd_mp_init_func;
259 retval->mp_lookup_func = passwd_mp_lookup_func;
260 retval->mp_destroy_func = passwd_mp_destroy_func;
261 assert(retval->parent.name != NULL);
262
263 TRACE_OUT(init_passwd_mp_agent);
264 return ((struct agent *)retval);
265 }
266