fix sid_to_[uid|gid] (spotted by Volker).
[kai/samba-autobuild/.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         /* see if the caller wants a new RID returned */
319         
320         if ( rid ) 
321                 request.flags = WBFLAG_ALLOCATE_RID;
322
323         fstrcpy( request.data.acct_mgt.username, name );
324         fstrcpy( request.data.acct_mgt.groupname, "" );
325         
326         ZERO_STRUCT(response);
327         
328         result = winbindd_request( WINBINDD_CREATE_USER, &request, &response);
329         
330         if ( rid )
331                 *rid = response.data.rid;
332         
333         return result == NSS_STATUS_SUCCESS;
334 }
335
336 /**********************************************************************
337  Ask winbindd to create a local group
338 **********************************************************************/
339
340 BOOL winbind_create_group( const char *name, uint32 *rid )
341 {
342         struct winbindd_request request;
343         struct winbindd_response response;
344         NSS_STATUS result;
345         
346         if ( !lp_winbind_enable_local_accounts() )
347                 return False;
348                 
349         if ( !name )
350                 return False;
351                 
352         DEBUG(10,("winbind_create_group: %s\n", name));
353
354         /* see if the caller wants a new RID returned */
355         
356         if ( rid ) 
357                 request.flags = WBFLAG_ALLOCATE_RID;
358                 
359         fstrcpy( request.data.acct_mgt.groupname, name );
360         
361         ZERO_STRUCT(response);
362         
363         result = winbindd_request( WINBINDD_CREATE_GROUP, &request, &response);
364         
365         if ( rid )
366                 *rid = response.data.rid;
367         
368         return result == NSS_STATUS_SUCCESS;
369 }
370
371 /**********************************************************************
372  Ask winbindd to add a user to a local group
373 **********************************************************************/
374
375 BOOL winbind_add_user_to_group( const char *user, const char *group )
376 {
377         struct winbindd_request request;
378         struct winbindd_response response;
379         NSS_STATUS result;
380         
381         if ( !lp_winbind_enable_local_accounts() )
382                 return False;
383                 
384         if ( !user || !group )
385                 return False;
386                 
387         DEBUG(10,("winbind_add_user_to_group: user(%s), group(%s) \n", 
388                 user, group));
389                 
390         fstrcpy( request.data.acct_mgt.username, user );
391         fstrcpy( request.data.acct_mgt.groupname, group );
392         
393         ZERO_STRUCT(response);
394         
395         result = winbindd_request( WINBINDD_ADD_USER_TO_GROUP, &request, &response);
396         
397         return result == NSS_STATUS_SUCCESS;
398 }
399
400 /**********************************************************************
401  Ask winbindd to remove a user to a local group
402 **********************************************************************/
403
404 BOOL winbind_remove_user_from_group( const char *user, const char *group )
405 {
406         struct winbindd_request request;
407         struct winbindd_response response;
408         NSS_STATUS result;
409         
410         if ( !lp_winbind_enable_local_accounts() )
411                 return False;
412                 
413         if ( !user || !group )
414                 return False;
415                 
416         DEBUG(10,("winbind_remove_user_from_group: user(%s), group(%s) \n", 
417                 user, group));
418                 
419         fstrcpy( request.data.acct_mgt.username, user );
420         fstrcpy( request.data.acct_mgt.groupname, group );
421         
422         ZERO_STRUCT(response);
423         
424         result = winbindd_request( WINBINDD_REMOVE_USER_FROM_GROUP, &request, &response);
425         
426         return result == NSS_STATUS_SUCCESS;
427 }
428
429 /**********************************************************************
430  Ask winbindd to set the primary group for a user local user
431 **********************************************************************/
432
433 BOOL winbind_set_user_primary_group( const char *user, const char *group )
434 {
435         struct winbindd_request request;
436         struct winbindd_response response;
437         NSS_STATUS result;
438         
439         if ( !lp_winbind_enable_local_accounts() )
440                 return False;
441                 
442         if ( !user || !group )
443                 return False;
444                 
445         DEBUG(10,("winbind_set_user_primary_group: user(%s), group(%s) \n", 
446                 user, group));
447
448         fstrcpy( request.data.acct_mgt.username, user );
449         fstrcpy( request.data.acct_mgt.groupname, group );
450         
451         ZERO_STRUCT(response);
452         
453         result = winbindd_request( WINBINDD_SET_USER_PRIMARY_GROUP, &request, &response);
454         
455         return result == NSS_STATUS_SUCCESS;
456 }
457
458
459 /**********************************************************************
460  Ask winbindd to remove a user from its lists of accounts
461 **********************************************************************/
462
463 BOOL winbind_delete_user( const char *user )
464 {
465         struct winbindd_request request;
466         struct winbindd_response response;
467         NSS_STATUS result;
468         
469         if ( !lp_winbind_enable_local_accounts() )
470                 return False;
471                 
472         if ( !user )
473                 return False;
474                 
475         DEBUG(10,("winbind_delete_user: user (%s)\n", user));
476
477         fstrcpy( request.data.acct_mgt.username, user );
478         
479         ZERO_STRUCT(response);
480         
481         result = winbindd_request( WINBINDD_DELETE_USER, &request, &response);
482         
483         return result == NSS_STATUS_SUCCESS;
484 }
485
486 /**********************************************************************
487  Ask winbindd to remove a group from its lists of accounts
488 **********************************************************************/
489
490 BOOL winbind_delete_group( const char *group )
491 {
492         struct winbindd_request request;
493         struct winbindd_response response;
494         NSS_STATUS result;
495         
496         if ( !lp_winbind_enable_local_accounts() )
497                 return False;
498                 
499         if ( !group )
500                 return False;
501                 
502         DEBUG(10,("winbind_delete_group: group (%s)\n", group));
503
504         fstrcpy( request.data.acct_mgt.groupname, group );
505         
506         ZERO_STRUCT(response);
507         
508         result = winbindd_request( WINBINDD_DELETE_GROUP, &request, &response);
509         
510         return result == NSS_STATUS_SUCCESS;
511 }
512
513 /***********************************************************************/
514 #if 0   /* not needed currently since winbindd_acct was added -- jerry */
515
516 /* Call winbindd to convert SID to uid. Do not allocate */
517
518 BOOL winbind_sid_to_uid_query(uid_t *puid, const DOM_SID *sid)
519 {
520         struct winbindd_request request;
521         struct winbindd_response response;
522         int result;
523         fstring sid_str;
524
525         if (!puid)
526                 return False;
527
528         /* Initialise request */
529
530         ZERO_STRUCT(request);
531         ZERO_STRUCT(response);
532
533         sid_to_string(sid_str, sid);
534         fstrcpy(request.data.sid, sid_str);
535
536         request.flags = WBFLAG_QUERY_ONLY;
537         
538         /* Make request */
539
540         result = winbindd_request(WINBINDD_SID_TO_UID, &request, &response);
541
542         /* Copy out result */
543
544         if (result == NSS_STATUS_SUCCESS) {
545                 *puid = response.data.uid;
546         }
547
548         return (result == NSS_STATUS_SUCCESS);
549 }
550
551 /* Call winbindd to convert SID to gid.  Do not allocate */
552
553 BOOL winbind_sid_to_gid_query(gid_t *pgid, const DOM_SID *sid)
554 {
555         struct winbindd_request request;
556         struct winbindd_response response;
557         int result;
558         fstring sid_str;
559
560         if (!pgid)
561                 return False;
562
563         /* Initialise request */
564
565         ZERO_STRUCT(request);
566         ZERO_STRUCT(response);
567
568         sid_to_string(sid_str, sid);
569         fstrcpy(request.data.sid, sid_str);
570         
571         request.flags = WBFLAG_QUERY_ONLY;
572
573         /* Make request */
574
575         result = winbindd_request(WINBINDD_SID_TO_GID, &request, &response);
576
577         /* Copy out result */
578
579         if (result == NSS_STATUS_SUCCESS) {
580                 *pgid = response.data.gid;
581         }
582
583         return (result == NSS_STATUS_SUCCESS);
584 }
585
586 #endif  /* JERRY */
587
588 /***********************************************************************/
589