]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - usr.sbin/nscd/agents/passwd.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / usr.sbin / nscd / agents / passwd.c
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/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 #include <sys/types.h>
32 #include <assert.h>
33 #include <nsswitch.h>
34 #include <pwd.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include "../debug.h"
38 #include "passwd.h"
39
40 static int passwd_marshal_func(struct passwd *, char *, size_t *);
41 static int passwd_lookup_func(const char *, size_t, char **, size_t *);
42 static void *passwd_mp_init_func();
43 static int passwd_mp_lookup_func(char **, size_t *, void *);
44 static void passwd_mp_destroy_func(void *mdata);
45
46 static int
47 passwd_marshal_func(struct passwd *pwd, char *buffer, size_t *buffer_size)
48 {
49         char            *p;
50         struct passwd   new_pwd;
51         size_t          desired_size, size;
52
53         TRACE_IN(passwd_marshal_func);
54         desired_size = sizeof(struct passwd) + sizeof(char *) +
55                 strlen(pwd->pw_name) + 1;
56         if (pwd->pw_passwd != NULL)
57                 desired_size += strlen(pwd->pw_passwd) + 1;
58         if (pwd->pw_class != NULL)
59                 desired_size += strlen(pwd->pw_class) + 1;
60         if (pwd->pw_gecos != NULL)
61                 desired_size += strlen(pwd->pw_gecos) + 1;
62         if (pwd->pw_dir != NULL)
63                 desired_size += strlen(pwd->pw_dir) + 1;
64         if (pwd->pw_shell != NULL)
65                 desired_size += strlen(pwd->pw_shell) + 1;
66
67         if ((*buffer_size < desired_size) || (buffer == NULL)) {
68                 *buffer_size = desired_size;
69                 TRACE_OUT(passwd_marshal_func);
70                 return (NS_RETURN);
71         }
72
73         memcpy(&new_pwd, pwd, sizeof(struct passwd));
74         memset(buffer, 0, desired_size);
75
76         *buffer_size = desired_size;
77         p = buffer + sizeof(struct passwd) + sizeof(char *);
78         memcpy(buffer + sizeof(struct passwd), &p, sizeof(char *));
79
80         if (new_pwd.pw_name != NULL) {
81                 size = strlen(new_pwd.pw_name);
82                 memcpy(p, new_pwd.pw_name, size);
83                 new_pwd.pw_name = p;
84                 p += size + 1;
85         }
86
87         if (new_pwd.pw_passwd != NULL) {
88                 size = strlen(new_pwd.pw_passwd);
89                 memcpy(p, new_pwd.pw_passwd, size);
90                 new_pwd.pw_passwd = p;
91                 p += size + 1;
92         }
93
94         if (new_pwd.pw_class != NULL) {
95                 size = strlen(new_pwd.pw_class);
96                 memcpy(p, new_pwd.pw_class, size);
97                 new_pwd.pw_class = p;
98                 p += size + 1;
99         }
100
101         if (new_pwd.pw_gecos != NULL) {
102                 size = strlen(new_pwd.pw_gecos);
103                 memcpy(p, new_pwd.pw_gecos, size);
104                 new_pwd.pw_gecos = p;
105                 p += size + 1;
106         }
107
108         if (new_pwd.pw_dir != NULL) {
109                 size = strlen(new_pwd.pw_dir);
110                 memcpy(p, new_pwd.pw_dir, size);
111                 new_pwd.pw_dir = p;
112                 p += size + 1;
113         }
114
115         if (new_pwd.pw_shell != NULL) {
116                 size = strlen(new_pwd.pw_shell);
117                 memcpy(p, new_pwd.pw_shell, size);
118                 new_pwd.pw_shell = p;
119                 p += size + 1;
120         }
121
122         memcpy(buffer, &new_pwd, sizeof(struct passwd));
123         TRACE_OUT(passwd_marshal_func);
124         return (NS_SUCCESS);
125 }
126
127 static int
128 passwd_lookup_func(const char *key, size_t key_size, char **buffer,
129         size_t *buffer_size)
130 {
131         enum nss_lookup_type lookup_type;
132         char    *login;
133         size_t  size;
134         uid_t   uid;
135
136         struct passwd *result;
137
138         TRACE_IN(passwd_lookup_func);
139         assert(buffer != NULL);
140         assert(buffer_size != NULL);
141
142         if (key_size < sizeof(enum nss_lookup_type)) {
143                 TRACE_OUT(passwd_lookup_func);
144                 return (NS_UNAVAIL);
145         }
146         memcpy(&lookup_type, key, sizeof(enum nss_lookup_type));
147
148         switch (lookup_type) {
149         case nss_lt_name:
150                 size = key_size - sizeof(enum nss_lookup_type)  + 1;
151                 login = (char *)calloc(1, size);
152                 assert(login != NULL);
153                 memcpy(login, key + sizeof(enum nss_lookup_type), size - 1);
154                 break;
155         case nss_lt_id:
156                 if (key_size < sizeof(enum nss_lookup_type) +
157                         sizeof(uid_t)) {
158                         TRACE_OUT(passwd_lookup_func);
159                         return (NS_UNAVAIL);
160                 }
161
162                 memcpy(&uid, key + sizeof(enum nss_lookup_type), sizeof(uid_t));
163                 break;
164         default:
165                 TRACE_OUT(passwd_lookup_func);
166                 return (NS_UNAVAIL);
167         }
168
169         switch (lookup_type) {
170         case nss_lt_name:
171                 result = getpwnam(login);
172                 free(login);
173                 break;
174         case nss_lt_id:
175                 result = getpwuid(uid);
176                 break;
177         default:
178                 /* SHOULD NOT BE REACHED */
179                 break;
180         }
181
182         if (result != NULL) {
183                 passwd_marshal_func(result, NULL, buffer_size);
184                 *buffer = (char *)malloc(*buffer_size);
185                 assert(*buffer != NULL);
186                 passwd_marshal_func(result, *buffer, buffer_size);
187         }
188
189         TRACE_OUT(passwd_lookup_func);
190         return (result == NULL ? NS_NOTFOUND : NS_SUCCESS);
191 }
192
193 static void *
194 passwd_mp_init_func()
195 {
196         TRACE_IN(passwd_mp_init_func);
197         setpwent();
198         TRACE_OUT(passwd_mp_init_func);
199
200         return (NULL);
201 }
202
203 static int
204 passwd_mp_lookup_func(char **buffer, size_t *buffer_size, void *mdata)
205 {
206         struct passwd   *result;
207
208         TRACE_IN(passwd_mp_lookup_func);
209         result = getpwent();
210         if (result != NULL) {
211                 passwd_marshal_func(result, NULL, buffer_size);
212                 *buffer = (char *)malloc(*buffer_size);
213                 assert(*buffer != NULL);
214                 passwd_marshal_func(result, *buffer, buffer_size);
215         }
216
217         TRACE_OUT(passwd_mp_lookup_func);
218         return (result == NULL ? NS_NOTFOUND : NS_SUCCESS);
219 }
220
221 static void
222 passwd_mp_destroy_func(void *mdata)
223 {
224         TRACE_IN(passwd_mp_destroy_func);
225         TRACE_OUT(passwd_mp_destroy_func);
226 }
227
228 struct agent *
229 init_passwd_agent()
230 {
231         struct common_agent     *retval;
232
233         TRACE_IN(init_passwd_agent);
234         retval = (struct common_agent *)calloc(1, sizeof(struct common_agent));
235         assert(retval != NULL);
236
237         retval->parent.name = strdup("passwd");
238         assert(retval->parent.name != NULL);
239
240         retval->parent.type = COMMON_AGENT;
241         retval->lookup_func = passwd_lookup_func;
242
243         TRACE_OUT(init_passwd_agent);
244         return ((struct agent *)retval);
245 }
246
247 struct agent *
248 init_passwd_mp_agent()
249 {
250         struct multipart_agent  *retval;
251
252         TRACE_IN(init_passwd_mp_agent);
253         retval = (struct multipart_agent *)calloc(1,
254                 sizeof(struct multipart_agent));
255         assert(retval != NULL);
256
257         retval->parent.name = strdup("passwd");
258         retval->parent.type = MULTIPART_AGENT;
259         retval->mp_init_func = passwd_mp_init_func;
260         retval->mp_lookup_func = passwd_mp_lookup_func;
261         retval->mp_destroy_func = passwd_mp_destroy_func;
262         assert(retval->parent.name != NULL);
263
264         TRACE_OUT(init_passwd_mp_agent);
265         return ((struct agent *)retval);
266 }