StrCaseCmp tests: Add some tests in Katakana. Convert strings to
[ira/wip.git] / source3 / nsswitch / winbind_nss_aix.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    AIX loadable authentication mmodule, providing identification 
5    routines against Samba winbind/Windows NT Domain
6
7    Copyright (C) Tim Potter 2003
8    Copyright (C) Steve Roylance 2003
9    
10    This library is free software; you can redistribute it and/or
11    modify it under the terms of the GNU Library General Public
12    License as published by the Free Software Foundation; either
13    version 2 of the License, or (at your option) any later version.
14    
15    This library is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    Library General Public License for more details.
19    
20    You should have received a copy of the GNU Library General Public
21    License along with this library; if not, write to the
22    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23    Boston, MA  02111-1307, USA.   
24 */
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <usersec.h>
29 #include <errno.h>
30
31 #include "winbind_client.h"
32
33 #define MAX_GETPWENT_USERS 250
34 #define MAX_GETGRENT_USERS 250
35 /* #define WB_AIX_DEBUG */
36
37 static struct passwd *fill_pwent(struct winbindd_pw *pw)
38 {
39         struct passwd *result;
40
41         if (!(result = malloc(sizeof(struct passwd))))
42                 goto out;
43                 
44         ZERO_STRUCTP(result);
45
46         /* User name */
47
48         if ((result->pw_name = malloc(strlen(pw->pw_name) + 1)) == NULL)
49                 goto out;
50         
51         strcpy(result->pw_name, pw->pw_name);
52
53         /* Password */
54
55         if ((result->pw_passwd = malloc(strlen(pw->pw_passwd) + 1)) == NULL)
56                 goto out;
57         
58         strcpy(result->pw_passwd, pw->pw_passwd);
59         
60         /* [ug]id */
61
62         result->pw_uid = pw->pw_uid;
63         result->pw_gid = pw->pw_gid;
64
65         /* GECOS */
66
67         if ((result->pw_gecos = malloc(strlen(pw->pw_gecos) + 1)) == NULL)
68                 goto out;
69
70         strcpy(result->pw_gecos, pw->pw_gecos);
71         
72         /* Home directory */
73         
74         if ((result->pw_dir = malloc(strlen(pw->pw_dir) + 1)) == NULL)
75                 goto out;
76
77         strcpy(result->pw_dir, pw->pw_dir);
78
79         /* Logon shell */
80         
81         if ((result->pw_shell = malloc(strlen(pw->pw_shell) + 1)) == NULL)
82                 goto out;
83         
84         strcpy(result->pw_shell, pw->pw_shell);
85 #ifdef WB_AIX_DEBUG
86         printf("wb_aix - returning filled pwent %s, %d\n", result->pw_name, result->pw_uid);
87 #endif
88         return result;
89         
90         /* A memory allocation failed, undo succesfull allocations and
91            return NULL */
92
93 out:
94         SAFE_FREE(result->pw_dir);
95         SAFE_FREE(result->pw_gecos);
96         SAFE_FREE(result->pw_passwd);
97         SAFE_FREE(result->pw_name);
98         SAFE_FREE(result);      
99
100         return NULL;
101 }
102
103 static BOOL next_token(char **ptr,char *buff,char *sep, size_t bufsize)
104 {
105         char *s;
106         BOOL quoted;
107         size_t len=1;
108
109         if (!ptr) return(False);
110
111         s = *ptr;
112
113         /* default to simple separators */
114         if (!sep) sep = " \t\n\r";
115
116         /* find the first non sep char */
117         while (*s && strchr(sep,*s)) s++;
118         
119         /* nothing left? */
120         if (! *s) return(False);
121         
122         /* copy over the token */
123         for (quoted = False; len < bufsize && *s && (quoted || !strchr(sep,*s)); s++) {
124                 if (*s == '\"') {
125                         quoted = !quoted;
126                 } else {
127                         len++;
128                         *buff++ = *s;
129                 }
130         }
131         
132         *ptr = (*s) ? s+1 : s;  
133         *buff = 0;
134         
135         return(True);
136 }
137
138 static struct group *fill_grent(struct winbindd_gr *gr, char *gr_mem)
139 {
140         fstring name;
141         int i;
142         char *tst;
143         struct group *result;
144         
145         if (!(result = malloc(sizeof(struct group))))
146                 goto out;
147
148         ZERO_STRUCTP(result);
149
150         /* Group name */
151
152         if ((result->gr_name = malloc(strlen(gr->gr_name) + 1)) == NULL)
153                 goto out;
154
155         strcpy(result->gr_name, gr->gr_name);
156
157         /* Password */
158
159         if ((result->gr_passwd = malloc(strlen(gr->gr_passwd) + 1)) == NULL)
160                 goto out;
161
162         strcpy(result->gr_passwd, gr->gr_passwd);
163
164         /* gid */
165
166         result->gr_gid = gr->gr_gid;
167
168         /* Group membership */
169
170         if ((gr->num_gr_mem < 0) || !gr_mem) {
171                 gr->num_gr_mem = 0;
172         }
173         
174         if (gr->num_gr_mem == 0) {
175
176                 /* Group is empty */
177                 
178                 *(result->gr_mem) = NULL;
179                 return result;
180         }
181         
182         if ((tst = malloc(((gr->num_gr_mem + 1) * sizeof(char *)))) == NULL)
183                 goto out;
184                 
185         result->gr_mem = (char **)tst;
186
187         /* Start looking at extra data */
188
189         i = 0;
190
191         while(next_token((char **)&gr_mem, name, ",", sizeof(fstring))) {
192         
193                 /* Allocate space for member */
194         
195                 if (((result->gr_mem)[i] = 
196                      malloc(strlen(name) + 1)) == NULL) {
197                         for ( i -= 1; i >= 0; i--)
198                                 SAFE_FREE((result->gr_mem)[i]);
199                         goto out;
200
201                 }        
202         
203                 strcpy((result->gr_mem)[i], name);
204                 i++;
205         }
206
207         /* Terminate list */
208
209         (result->gr_mem)[i] = NULL;
210
211 #ifdef WB_AIX_DEBUG
212         printf("wb_aix - returning filled grent %s, %d\n", result->gr_name, result->gr_gid);
213 #endif
214         return result;
215         
216         /* A memory allocation failed, undo succesfull allocations and
217            return NULL */
218
219 out:
220         SAFE_FREE(tst);
221         SAFE_FREE(result->gr_passwd);
222         SAFE_FREE(result->gr_name);
223         SAFE_FREE(result);
224
225         return NULL;
226 }
227
228
229
230 static struct group *
231 wb_aix_getgrgid (gid_t gid)
232 {
233 /* take a group id and return a filled struct group */
234         
235         struct winbindd_response response;
236         struct winbindd_request request;
237
238         ZERO_STRUCT(response);
239         ZERO_STRUCT(request);
240 #ifdef WB_AIX_DEBUG
241         printf("wb_aix - getgrid for %d\n", gid);
242 #endif
243         
244         request.data.gid = gid;
245
246         if (winbindd_request(WINBINDD_GETGRGID, &request, &response)
247                         == NSS_STATUS_SUCCESS) {
248 #ifdef WB_AIX_DEBUG
249                 printf("wb_aix - returned from winbind_request\n");
250 #endif
251                 return fill_grent(&response.data.gr, response.extra_data);
252         }
253         
254         return NULL;
255 }
256
257 static struct group *
258 wb_aix_getgrnam (const char *name)
259 {
260 /* take a group name and return a filled struct group */
261
262         struct winbindd_response response;
263         struct winbindd_request request;
264         
265         ZERO_STRUCT(response);
266         ZERO_STRUCT(request);
267
268 #ifdef WB_AIX_DEBUG
269         printf("wb_aix - getgrnam for %s\n", name);
270 #endif
271
272         strncpy(request.data.groupname, name, 
273                 sizeof(request.data.groupname));
274         request.data.groupname
275                 [sizeof(request.data.groupname) - 1] = '\0';
276
277
278         if (winbindd_request(WINBINDD_GETGRNAM, &request, &response)
279                         == NSS_STATUS_SUCCESS) {
280 #ifdef WB_AIX_DEBUG
281                 printf("wb_aix - returned from winbind_request\n");
282 #endif
283                 return fill_grent(&response.data.gr, response.extra_data);
284         }       
285         return NULL;    
286 }
287
288 static char *
289 wb_aix_getgrset (const char *user)
290 {
291 /*      take a username and return a string containing a comma-separated list of 
292         group id numbers to which the user belongs */
293         
294         struct winbindd_response response;
295         struct winbindd_request request;
296         
297         char *tmpbuf, *result;
298         int i, idx = 0;
299
300 #ifdef WB_AIX_DEBUG
301         printf("wb_aix - getgrset for %s\n", user);
302 #endif
303         strncpy(request.data.username, user, 
304                 sizeof(request.data.username) - 1);
305         request.data.username
306                 [sizeof(request.data.username) - 1] = '\0';
307
308         
309         if (winbindd_request(WINBINDD_GETGROUPS, &request, &response)
310                         == NSS_STATUS_SUCCESS) {
311                 int num_gids = response.data.num_entries;
312                 gid_t *gid_list = (gid_t *)response.extra_data;
313 #ifdef WB_AIX_DEBUG
314                 printf("wb_aix - returned from winbind_request\n");
315 #endif
316                 
317                 /* allocate a space large enough to contruct the string */
318                 if (!(tmpbuf = malloc(num_gids*12))) {
319                         return NULL;
320                 }
321                 idx += sprintf(tmpbuf, "%d", gid_list[0]);
322                 for (i = 1; i < num_gids; i++) {
323                         tmpbuf[idx++] = ',';
324                         idx += sprintf(tmpbuf+idx, "%d", gid_list[i]);  
325                 }
326                 tmpbuf[idx] = '\0';
327                 if (!(result = malloc(idx+1))) {
328                         /*      allocate a string the right size to return, but
329                                 if that fails may as well return our working buffer
330                                 because it contains the same thing */
331                         return tmpbuf;
332                 }
333                 strcpy(result, tmpbuf);
334                 SAFE_FREE(tmpbuf);
335                 return result;
336         }
337         return NULL;
338 }
339
340 static struct passwd *
341 wb_aix_getpwuid (uid_t uid)
342 {
343 /* take a uid and return a filled struct passwd */
344         
345         struct winbindd_response response;
346         struct winbindd_request request;
347         
348         ZERO_STRUCT(response);
349         ZERO_STRUCT(request);
350
351 #ifdef WB_AIX_DEBUG
352         printf("wb_aix - getpwid for %d\n", uid);
353 #endif
354                 
355         request.data.uid = uid;
356                 
357         if (winbindd_request(WINBINDD_GETPWUID, &request, &response)
358                         == NSS_STATUS_SUCCESS) {
359 #ifdef WB_AIX_DEBUG
360                 printf("wb_aix - returned from winbind_request\n");
361 #endif
362                 return fill_pwent(&response.data.pw);
363         }
364         return NULL;    
365 }
366
367 static struct passwd *
368 wb_aix_getpwnam (const char *name)
369 {
370 /* take a username and return a filled struct passwd */
371
372         struct winbindd_response response;
373         struct winbindd_request request;
374         
375         ZERO_STRUCT(response);
376         ZERO_STRUCT(request);
377 #ifdef WB_AIX_DEBUG
378         printf("wb_aix - getpwnam for %s\n", name);
379 #endif
380         strncpy(request.data.username, name, 
381                 sizeof(request.data.username) - 1);
382         request.data.username
383                 [sizeof(request.data.username) - 1] = '\0';
384
385
386         if (winbindd_request(WINBINDD_GETPWNAM, &request, &response)
387                         == NSS_STATUS_SUCCESS) {
388 #ifdef WB_AIX_DEBUG
389                 printf("wb_aix - returned from winbind_request\n");
390 #endif          
391         return fill_pwent(&response.data.pw);
392         }
393         return NULL;
394 }
395
396 int
397 wb_aix_init (struct secmethod_table *methods)
398 {
399         memset(methods, 0, sizeof(*methods));
400
401         /* identification methods, this is the minimum requried for a
402         working module */
403     
404         methods->method_getgrgid = wb_aix_getgrgid;
405         methods->method_getgrnam = wb_aix_getgrnam;
406         methods->method_getgrset = wb_aix_getgrset;
407         methods->method_getpwnam = wb_aix_getpwnam;
408         methods->method_getpwuid = wb_aix_getpwuid;
409
410         return AUTH_SUCCESS;
411 }