fixes for 'net rpc vampire'. I can now take a blank Samba host
[samba.git] / source3 / nsswitch / wb_client.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    winbind client code
5
6    Copyright (C) Tim Potter 2000
7    Copyright (C) Andrew Tridgell 2000
8    
9    This library is free software; you can redistribute it and/or
10    modify it under the terms of the GNU Library General Public
11    License as published by the Free Software Foundation; either
12    version 2 of the License, or (at your option) any later version.
13    
14    This library is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17    Library General Public License for more details.
18    
19    You should have received a copy of the GNU Library General Public
20    License along with this library; if not, write to the
21    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22    Boston, MA  02111-1307, USA.   
23 */
24
25 #include "includes.h"
26 #include "nsswitch/winbind_nss.h"
27
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_WINBIND
30
31 extern DOM_SID global_sid_NULL;                         /* NULL sid */
32
33 NSS_STATUS winbindd_request(int req_type,
34                                  struct winbindd_request *request,
35                                  struct winbindd_response *response);
36
37 /* Call winbindd to convert a name to a sid */
38
39 BOOL winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid, 
40                          enum SID_NAME_USE *name_type)
41 {
42         struct winbindd_request request;
43         struct winbindd_response response;
44         NSS_STATUS result;
45         
46         if (!sid || !name_type)
47                 return False;
48
49         /* Send off request */
50
51         ZERO_STRUCT(request);
52         ZERO_STRUCT(response);
53
54         fstrcpy(request.data.name.dom_name, dom_name);
55         fstrcpy(request.data.name.name, name);
56
57         if ((result = winbindd_request(WINBINDD_LOOKUPNAME, &request, 
58                                        &response)) == NSS_STATUS_SUCCESS) {
59                 if (!string_to_sid(sid, response.data.sid.sid))
60                         return False;
61                 *name_type = (enum SID_NAME_USE)response.data.sid.type;
62         }
63
64         return result == NSS_STATUS_SUCCESS;
65 }
66
67 /* Call winbindd to convert sid to name */
68
69 BOOL winbind_lookup_sid(const DOM_SID *sid, 
70                         fstring dom_name, fstring name, 
71                         enum SID_NAME_USE *name_type)
72 {
73         struct winbindd_request request;
74         struct winbindd_response response;
75         NSS_STATUS result;
76         fstring sid_str;
77         
78         /* Initialise request */
79
80         ZERO_STRUCT(request);
81         ZERO_STRUCT(response);
82
83         sid_to_string(sid_str, sid);
84         fstrcpy(request.data.sid, sid_str);
85         
86         /* Make request */
87
88         result = winbindd_request(WINBINDD_LOOKUPSID, &request, &response);
89
90         /* Copy out result */
91
92         if (result == NSS_STATUS_SUCCESS) {
93                 fstrcpy(dom_name, response.data.name.dom_name);
94                 fstrcpy(name, response.data.name.name);
95                 *name_type = (enum SID_NAME_USE)response.data.name.type;
96
97                 DEBUG(10, ("winbind_lookup_sid: SUCCESS: SID %s -> %s %s\n", 
98                            sid_str, dom_name, name));
99         }
100
101         return (result == NSS_STATUS_SUCCESS);
102 }
103
104 /* Call winbindd to convert SID to uid */
105
106 BOOL winbind_sid_to_uid(uid_t *puid, const DOM_SID *sid)
107 {
108         struct winbindd_request request;
109         struct winbindd_response response;
110         int result;
111         fstring sid_str;
112
113         if (!puid)
114                 return False;
115
116         /* Initialise request */
117
118         ZERO_STRUCT(request);
119         ZERO_STRUCT(response);
120
121         sid_to_string(sid_str, sid);
122         fstrcpy(request.data.sid, sid_str);
123         
124         /* Make request */
125
126         result = winbindd_request(WINBINDD_SID_TO_UID, &request, &response);
127
128         /* Copy out result */
129
130         if (result == NSS_STATUS_SUCCESS) {
131                 *puid = response.data.uid;
132         }
133
134         return (result == NSS_STATUS_SUCCESS);
135 }
136
137 /* Call winbindd to convert uid to sid */
138
139 BOOL winbind_uid_to_sid(DOM_SID *sid, uid_t uid)
140 {
141         struct winbindd_request request;
142         struct winbindd_response response;
143         int result;
144
145         if (!sid)
146                 return False;
147
148         /* Initialise request */
149
150         ZERO_STRUCT(request);
151         ZERO_STRUCT(response);
152
153         request.data.uid = uid;
154
155         /* Make request */
156
157         result = winbindd_request(WINBINDD_UID_TO_SID, &request, &response);
158
159         /* Copy out result */
160
161         if (result == NSS_STATUS_SUCCESS) {
162                 if (!string_to_sid(sid, response.data.sid.sid))
163                         return False;
164         } else {
165                 sid_copy(sid, &global_sid_NULL);
166         }
167
168         return (result == NSS_STATUS_SUCCESS);
169 }
170
171 /* Call winbindd to convert SID to gid */
172
173 BOOL winbind_sid_to_gid(gid_t *pgid, const DOM_SID *sid)
174 {
175         struct winbindd_request request;
176         struct winbindd_response response;
177         int result;
178         fstring sid_str;
179
180         if (!pgid)
181                 return False;
182
183         /* Initialise request */
184
185         ZERO_STRUCT(request);
186         ZERO_STRUCT(response);
187
188         sid_to_string(sid_str, sid);
189         fstrcpy(request.data.sid, sid_str);
190         
191         /* Make request */
192
193         result = winbindd_request(WINBINDD_SID_TO_GID, &request, &response);
194
195         /* Copy out result */
196
197         if (result == NSS_STATUS_SUCCESS) {
198                 *pgid = response.data.gid;
199         }
200
201         return (result == NSS_STATUS_SUCCESS);
202 }
203
204 /* Call winbindd to convert gid to sid */
205
206 BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
207 {
208         struct winbindd_request request;
209         struct winbindd_response response;
210         int result;
211
212         if (!sid)
213                 return False;
214
215         /* Initialise request */
216
217         ZERO_STRUCT(request);
218         ZERO_STRUCT(response);
219
220         request.data.gid = gid;
221
222         /* Make request */
223
224         result = winbindd_request(WINBINDD_GID_TO_SID, &request, &response);
225
226         /* Copy out result */
227
228         if (result == NSS_STATUS_SUCCESS) {
229                 if (!string_to_sid(sid, response.data.sid.sid))
230                         return False;
231         } else {
232                 sid_copy(sid, &global_sid_NULL);
233         }
234
235         return (result == NSS_STATUS_SUCCESS);
236 }
237
238 /* Fetch the list of groups a user is a member of from winbindd.  This is
239    used by winbind_getgroups. */
240
241 static int wb_getgroups(const char *user, gid_t **groups)
242 {
243         struct winbindd_request request;
244         struct winbindd_response response;
245         int result;
246
247         /* Call winbindd */
248
249         fstrcpy(request.data.username, user);
250
251         ZERO_STRUCT(response);
252
253         result = winbindd_request(WINBINDD_GETGROUPS, &request, &response);
254
255         if (result == NSS_STATUS_SUCCESS) {
256                 
257                 /* Return group list.  Don't forget to free the group list
258                    when finished. */
259
260                 *groups = (gid_t *)response.extra_data;
261                 return response.data.num_entries;
262         }
263
264         return -1;
265 }
266
267 /* Return a list of groups the user is a member of.  This function is
268    useful for large systems where inverting the group database would be too
269    time consuming.  If size is zero, list is not modified and the total
270    number of groups for the user is returned. */
271
272 int winbind_getgroups(const char *user, gid_t **list)
273 {
274         /*
275          * Don't do the lookup if the name has no separator _and_ we are not in
276          * 'winbind use default domain' mode.
277          */
278
279         if (!(strchr(user, *lp_winbind_separator()) || lp_winbind_use_default_domain()))
280                 return -1;
281
282         /* Fetch list of groups */
283
284         return wb_getgroups(user, list);
285 }
286
287 /**********************************************************************
288  simple wrapper function to see if winbindd is alive
289 **********************************************************************/
290
291 BOOL winbind_ping( void )
292 {
293         NSS_STATUS result;
294
295         result = winbindd_request(WINBINDD_PING, NULL, NULL);
296
297         return result == NSS_STATUS_SUCCESS;
298 }
299
300 /**********************************************************************
301  Ask winbindd to create a local user
302 **********************************************************************/
303
304 BOOL winbind_create_user( const char *name, uint32 *rid )
305 {
306         struct winbindd_request request;
307         struct winbindd_response response;
308         NSS_STATUS result;
309         
310         if ( !lp_winbind_enable_local_accounts() )
311                 return False;
312         
313         if ( !name )
314                 return False;
315                 
316         DEBUG(10,("winbind_create_user: %s\n", name));
317         
318         ZERO_STRUCT(request);
319         ZERO_STRUCT(response);
320         
321         /* see if the caller wants a new RID returned */
322         
323         if ( rid ) 
324                 request.flags = WBFLAG_ALLOCATE_RID;
325
326         fstrcpy( request.data.acct_mgt.username, name );
327         fstrcpy( request.data.acct_mgt.groupname, "" );
328         
329         result = winbindd_request( WINBINDD_CREATE_USER, &request, &response);
330         
331         if ( rid )
332                 *rid = response.data.rid;
333         
334         return result == NSS_STATUS_SUCCESS;
335 }
336
337 /**********************************************************************
338  Ask winbindd to create a local group
339 **********************************************************************/
340
341 BOOL winbind_create_group( const char *name, uint32 *rid )
342 {
343         struct winbindd_request request;
344         struct winbindd_response response;
345         NSS_STATUS result;
346         
347         if ( !lp_winbind_enable_local_accounts() )
348                 return False;
349                 
350         if ( !name )
351                 return False;
352                 
353         DEBUG(10,("winbind_create_group: %s\n", name));
354
355         ZERO_STRUCT(request);
356         ZERO_STRUCT(response);
357         
358         /* see if the caller wants a new RID returned */
359         
360         if ( rid ) 
361                 request.flags = WBFLAG_ALLOCATE_RID;
362                 
363         fstrcpy( request.data.acct_mgt.groupname, name );
364         
365         
366         result = winbindd_request( WINBINDD_CREATE_GROUP, &request, &response);
367         
368         if ( rid )
369                 *rid = response.data.rid;
370         
371         return result == NSS_STATUS_SUCCESS;
372 }
373
374 /**********************************************************************
375  Ask winbindd to add a user to a local group
376 **********************************************************************/
377
378 BOOL winbind_add_user_to_group( const char *user, const char *group )
379 {
380         struct winbindd_request request;
381         struct winbindd_response response;
382         NSS_STATUS result;
383         
384         if ( !lp_winbind_enable_local_accounts() )
385                 return False;
386                 
387         if ( !user || !group )
388                 return False;
389                 
390         ZERO_STRUCT(request);
391         ZERO_STRUCT(response);
392         
393         DEBUG(10,("winbind_add_user_to_group: user(%s), group(%s) \n", 
394                 user, group));
395                 
396         fstrcpy( request.data.acct_mgt.username, user );
397         fstrcpy( request.data.acct_mgt.groupname, group );
398         
399         result = winbindd_request( WINBINDD_ADD_USER_TO_GROUP, &request, &response);
400         
401         return result == NSS_STATUS_SUCCESS;
402 }
403
404 /**********************************************************************
405  Ask winbindd to remove a user to a local group
406 **********************************************************************/
407
408 BOOL winbind_remove_user_from_group( const char *user, const char *group )
409 {
410         struct winbindd_request request;
411         struct winbindd_response response;
412         NSS_STATUS result;
413         
414         if ( !lp_winbind_enable_local_accounts() )
415                 return False;
416                 
417         if ( !user || !group )
418                 return False;
419                 
420         ZERO_STRUCT(request);
421         ZERO_STRUCT(response);
422         
423         DEBUG(10,("winbind_remove_user_from_group: user(%s), group(%s) \n", 
424                 user, group));
425                 
426         ZERO_STRUCT(response);
427         
428         result = winbindd_request( WINBINDD_REMOVE_USER_FROM_GROUP, &request, &response);
429         
430         return result == NSS_STATUS_SUCCESS;
431 }
432
433 /**********************************************************************
434  Ask winbindd to set the primary group for a user local user
435 **********************************************************************/
436
437 BOOL winbind_set_user_primary_group( const char *user, const char *group )
438 {
439         struct winbindd_request request;
440         struct winbindd_response response;
441         NSS_STATUS result;
442         
443         if ( !lp_winbind_enable_local_accounts() )
444                 return False;
445                 
446         if ( !user || !group )
447                 return False;
448                 
449         ZERO_STRUCT(request);
450         ZERO_STRUCT(response);
451         
452         DEBUG(10,("winbind_set_user_primary_group: user(%s), group(%s) \n", 
453                 user, group));
454
455         fstrcpy( request.data.acct_mgt.username, user );
456         fstrcpy( request.data.acct_mgt.groupname, group );
457         
458         result = winbindd_request( WINBINDD_SET_USER_PRIMARY_GROUP, &request, &response);
459         
460         return result == NSS_STATUS_SUCCESS;
461 }
462
463
464 /**********************************************************************
465  Ask winbindd to remove a user from its lists of accounts
466 **********************************************************************/
467
468 BOOL winbind_delete_user( const char *user )
469 {
470         struct winbindd_request request;
471         struct winbindd_response response;
472         NSS_STATUS result;
473         
474         if ( !lp_winbind_enable_local_accounts() )
475                 return False;
476                 
477         if ( !user )
478                 return False;
479                 
480         ZERO_STRUCT(request);
481         ZERO_STRUCT(response);
482         
483         DEBUG(10,("winbind_delete_user: user (%s)\n", user));
484
485         fstrcpy( request.data.acct_mgt.username, user );
486         
487         result = winbindd_request( WINBINDD_DELETE_USER, &request, &response);
488         
489         return result == NSS_STATUS_SUCCESS;
490 }
491
492 /**********************************************************************
493  Ask winbindd to remove a group from its lists of accounts
494 **********************************************************************/
495
496 BOOL winbind_delete_group( const char *group )
497 {
498         struct winbindd_request request;
499         struct winbindd_response response;
500         NSS_STATUS result;
501         
502         if ( !lp_winbind_enable_local_accounts() )
503                 return False;
504                 
505         if ( !group )
506                 return False;
507                 
508         ZERO_STRUCT(request);
509         ZERO_STRUCT(response);
510         
511         DEBUG(10,("winbind_delete_group: group (%s)\n", group));
512
513         fstrcpy( request.data.acct_mgt.groupname, group );
514         
515         result = winbindd_request( WINBINDD_DELETE_GROUP, &request, &response);
516         
517         return result == NSS_STATUS_SUCCESS;
518 }
519
520 /***********************************************************************/
521 #if 0   /* not needed currently since winbindd_acct was added -- jerry */
522
523 /* Call winbindd to convert SID to uid. Do not allocate */
524
525 BOOL winbind_sid_to_uid_query(uid_t *puid, const DOM_SID *sid)
526 {
527         struct winbindd_request request;
528         struct winbindd_response response;
529         int result;
530         fstring sid_str;
531
532         if (!puid)
533                 return False;
534
535         /* Initialise request */
536
537         ZERO_STRUCT(request);
538         ZERO_STRUCT(response);
539
540         sid_to_string(sid_str, sid);
541         fstrcpy(request.data.sid, sid_str);
542
543         request.flags = WBFLAG_QUERY_ONLY;
544         
545         /* Make request */
546
547         result = winbindd_request(WINBINDD_SID_TO_UID, &request, &response);
548
549         /* Copy out result */
550
551         if (result == NSS_STATUS_SUCCESS) {
552                 *puid = response.data.uid;
553         }
554
555         return (result == NSS_STATUS_SUCCESS);
556 }
557
558 /* Call winbindd to convert SID to gid.  Do not allocate */
559
560 BOOL winbind_sid_to_gid_query(gid_t *pgid, const DOM_SID *sid)
561 {
562         struct winbindd_request request;
563         struct winbindd_response response;
564         int result;
565         fstring sid_str;
566
567         if (!pgid)
568                 return False;
569
570         /* Initialise request */
571
572         ZERO_STRUCT(request);
573         ZERO_STRUCT(response);
574
575         sid_to_string(sid_str, sid);
576         fstrcpy(request.data.sid, sid_str);
577         
578         request.flags = WBFLAG_QUERY_ONLY;
579
580         /* Make request */
581
582         result = winbindd_request(WINBINDD_SID_TO_GID, &request, &response);
583
584         /* Copy out result */
585
586         if (result == NSS_STATUS_SUCCESS) {
587                 *pgid = response.data.gid;
588         }
589
590         return (result == NSS_STATUS_SUCCESS);
591 }
592
593 #endif  /* JERRY */
594
595 /***********************************************************************/
596