~ubuntu-branches/ubuntu/maverick/samba/maverick-proposed

« back to all changes in this revision

Viewing changes to source/nsswitch/winbindd_acct.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2004-10-15 12:31:58 UTC
  • Revision ID: james.westby@ubuntu.com-20041015123158-aokykzdqkdgy6dfx
Tags: upstream-3.0.7
ImportĀ upstreamĀ versionĀ 3.0.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
   Unix SMB/CIFS implementation.
 
3
 
 
4
   Winbind account management functions
 
5
 
 
6
   Copyright (C) by Gerald (Jerry) Carter       2003
 
7
   
 
8
   This program is free software; you can redistribute it and/or modify
 
9
   it under the terms of the GNU General Public License as published by
 
10
   the Free Software Foundation; either version 2 of the License, or
 
11
   (at your option) any later version.
 
12
   
 
13
   This program is distributed in the hope that it will be useful,
 
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
   GNU General Public License for more details.
 
17
   
 
18
   You should have received a copy of the GNU General Public License
 
19
   along with this program; if not, write to the Free Software
 
20
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
21
*/
 
22
 
 
23
#include "includes.h"
 
24
#include "winbindd.h"
 
25
 
 
26
#undef DBGC_CLASS
 
27
#define DBGC_CLASS DBGC_WINBIND
 
28
 
 
29
#define WBKEY_PASSWD    "WBA_PASSWD"
 
30
#define WBKEY_GROUP     "WBA_GROUP"
 
31
 
 
32
#define NUM_PW_FIELDS   7
 
33
#define NUM_GRP_FIELDS  4
 
34
 
 
35
/* Globals */
 
36
 
 
37
static TDB_CONTEXT *account_tdb;
 
38
 
 
39
extern userdom_struct current_user_info;
 
40
 
 
41
struct _check_primary_grp {
 
42
        gid_t   gid;
 
43
        BOOL    found;
 
44
};
 
45
 
 
46
/**********************************************************************
 
47
**********************************************************************/
 
48
 
 
49
static void free_winbindd_gr( WINBINDD_GR *grp )
 
50
{
 
51
        int i;
 
52
 
 
53
        if ( !grp )
 
54
                return;
 
55
                
 
56
        for ( i=0; i<grp->num_gr_mem; i++ )
 
57
                SAFE_FREE( grp->gr_mem[i] );
 
58
 
 
59
        SAFE_FREE( grp->gr_mem );
 
60
        
 
61
        return;
 
62
}
 
63
 
 
64
/*****************************************************************************
 
65
 Initialise auto-account database. 
 
66
*****************************************************************************/
 
67
 
 
68
static BOOL winbindd_accountdb_init(void)
 
69
{
 
70
        /* see if we've already opened the tdb */
 
71
        
 
72
        if ( account_tdb )
 
73
                return True;
 
74
 
 
75
        /* winbindd_idmap.tdb should always be opened by the idmap_init()
 
76
           code first */
 
77
 
 
78
        if ( !(account_tdb = idmap_tdb_handle()) ) {
 
79
                DEBUG(0, ("winbindd_accountdb_init: Unable to retreive handle for database\n"));
 
80
                return False;
 
81
        }
 
82
        
 
83
        /* yeah! */
 
84
        
 
85
        return True;   
 
86
}
 
87
 
 
88
/**********************************************************************
 
89
 Convert a string in /etc/passwd format to a struct passwd* entry
 
90
**********************************************************************/
 
91
 
 
92
static WINBINDD_PW* string2passwd( char *string )
 
93
{
 
94
        static WINBINDD_PW pw;
 
95
        char *p, *str;
 
96
        char *fields[NUM_PW_FIELDS];
 
97
        int i;
 
98
        
 
99
        if ( !string )
 
100
                return NULL;
 
101
        
 
102
        ZERO_STRUCTP( &pw );
 
103
        
 
104
        DEBUG(10,("string2passwd: converting \"%s\"\n", string));
 
105
        
 
106
        ZERO_STRUCT( fields );
 
107
        
 
108
        for ( i=0, str=string; i<NUM_PW_FIELDS-1; i++ ) {
 
109
                if ( !(p = strchr( str, ':' )) ) {
 
110
                        DEBUG(0,("string2passwd: parsing failure\n"));
 
111
                        return NULL;
 
112
                }
 
113
                *p = '\0';
 
114
                if ( str )
 
115
                        fields[i] = str;
 
116
                str = p + 1;
 
117
        }
 
118
        if ( str ) 
 
119
                fields[i] = str;
 
120
        
 
121
        /* copy fields */
 
122
        
 
123
        fstrcpy( pw.pw_name,   fields[0] );
 
124
        fstrcpy( pw.pw_passwd, fields[1] );
 
125
        pw.pw_uid = atoi(      fields[2] );
 
126
        pw.pw_gid = atoi(      fields[3] );
 
127
        fstrcpy( pw.pw_gecos,  fields[4] );
 
128
        fstrcpy( pw.pw_dir,    fields[5] );
 
129
        fstrcpy( pw.pw_shell,  fields[6] );
 
130
        
 
131
        
 
132
        /* last minute sanity checks */
 
133
        
 
134
        if ( pw.pw_uid==0 || pw.pw_gid==0 ) {
 
135
                DEBUG(0,("string2passwd: Failure! uid==%lu, gid==%lu\n",
 
136
                        (unsigned long)pw.pw_uid, (unsigned long)pw.pw_gid));
 
137
                return NULL;
 
138
        }
 
139
        
 
140
        DEBUG(10,("string2passwd: Success\n"));
 
141
 
 
142
        return &pw;
 
143
}
 
144
 
 
145
/**********************************************************************
 
146
 Convert a struct passwd* to a string formatted for /etc/passwd
 
147
**********************************************************************/
 
148
 
 
149
static char* passwd2string( const WINBINDD_PW *pw )
 
150
{
 
151
        static pstring string;
 
152
        int ret;
 
153
        
 
154
        if ( !pw || !pw->pw_name )
 
155
                return NULL;
 
156
        
 
157
        DEBUG(10,("passwd2string: converting passwd struct for %s\n", 
 
158
                pw->pw_name));
 
159
 
 
160
        ret = pstr_sprintf( string, "%s:%s:%lu:%lu:%s:%s:%s",
 
161
                pw->pw_name, 
 
162
                pw->pw_passwd ? pw->pw_passwd : "x",
 
163
                (unsigned long)pw->pw_uid,
 
164
                (unsigned long)pw->pw_gid,
 
165
                pw->pw_gecos,
 
166
                pw->pw_dir,
 
167
                pw->pw_shell );
 
168
                
 
169
        if ( ret < 0 ) {
 
170
                DEBUG(0,("passwd2string: pstr_sprintf() failed!\n"));
 
171
                return NULL;
 
172
        }
 
173
                
 
174
        return string;  
 
175
}
 
176
 
 
177
/**********************************************************************
 
178
 Convert a string in /etc/group format to a struct group* entry
 
179
**********************************************************************/
 
180
 
 
181
static WINBINDD_GR* string2group( char *string )
 
182
{
 
183
        static WINBINDD_GR grp;
 
184
        char *p, *str;
 
185
        char *fields[NUM_GRP_FIELDS];
 
186
        int i;
 
187
        char **gr_members = NULL;
 
188
        int num_gr_members = 0;
 
189
        
 
190
        if ( !string )
 
191
                return NULL;
 
192
                
 
193
        ZERO_STRUCTP( &grp );
 
194
        
 
195
        DEBUG(10,("string2group: converting \"%s\"\n", string));
 
196
        
 
197
        ZERO_STRUCT( fields );
 
198
        
 
199
        for ( i=0, str=string; i<NUM_GRP_FIELDS-1; i++ ) {
 
200
                if ( !(p = strchr( str, ':' )) ) {
 
201
                        DEBUG(0,("string2group: parsing failure\n"));
 
202
                        return NULL;
 
203
                }
 
204
                *p = '\0';
 
205
                if ( str )
 
206
                        fields[i] = str;
 
207
                str = p + 1;
 
208
        }
 
209
        
 
210
        /* group members */
 
211
        
 
212
        if ( *str ) {
 
213
                /* we already know we have a non-empty string */
 
214
 
 
215
                num_gr_members = count_chars(str, ',') + 1;
 
216
                
 
217
                /* if there was at least one comma, then there 
 
218
                   are n+1 members */
 
219
                if ( num_gr_members ) {
 
220
                        fstring buffer;
 
221
                        
 
222
                        gr_members = (char**)smb_xmalloc(sizeof(char*)*(num_gr_members+1));
 
223
                        
 
224
                        i = 0;
 
225
                        while ( next_token(&str, buffer, ",", sizeof(buffer)) && i<num_gr_members ) {
 
226
                                gr_members[i++] = smb_xstrdup(buffer);
 
227
                        }
 
228
 
 
229
                        gr_members[i]   = NULL;
 
230
                }
 
231
        }
 
232
 
 
233
        
 
234
        /* copy fields */
 
235
        
 
236
        fstrcpy( grp.gr_name,   fields[0] );
 
237
        fstrcpy( grp.gr_passwd, fields[1] );
 
238
        grp.gr_gid = atoi(      fields[2] );
 
239
        
 
240
        grp.num_gr_mem = num_gr_members;
 
241
        grp.gr_mem     = gr_members;
 
242
        
 
243
        /* last minute sanity checks */
 
244
        
 
245
        if ( grp.gr_gid == 0 ) {
 
246
                DEBUG(0,("string2group: Failure! gid==%lu\n", (unsigned long)grp.gr_gid));
 
247
                SAFE_FREE( gr_members );
 
248
                return NULL;
 
249
        }
 
250
        
 
251
        DEBUG(10,("string2group: Success\n"));
 
252
 
 
253
        return &grp;
 
254
}
 
255
 
 
256
/**********************************************************************
 
257
 Convert a struct group* to a string formatted for /etc/group
 
258
**********************************************************************/
 
259
 
 
260
static char* group2string( const WINBINDD_GR *grp )
 
261
{
 
262
        static pstring string;
 
263
        int ret;
 
264
        char *member, *gr_mem_str;
 
265
        int num_members;
 
266
        int i, size;
 
267
        
 
268
        if ( !grp || !grp->gr_name )
 
269
                return NULL;
 
270
        
 
271
        DEBUG(10,("group2string: converting passwd struct for %s\n", 
 
272
                grp->gr_name));
 
273
        
 
274
        if ( grp->num_gr_mem ) {
 
275
                int idx = 0;
 
276
 
 
277
                member = grp->gr_mem[0];
 
278
                size = 0;
 
279
                num_members = 0;
 
280
 
 
281
                while ( member ) {
 
282
                        size += strlen(member) + 1;
 
283
                        num_members++;
 
284
                        member = grp->gr_mem[num_members];
 
285
                }
 
286
                
 
287
                gr_mem_str = smb_xmalloc(size);
 
288
        
 
289
                for ( i=0; i<num_members; i++ ) {
 
290
                        snprintf( &gr_mem_str[idx], size-idx, "%s,", grp->gr_mem[i] );
 
291
                        idx += strlen(grp->gr_mem[i]) + 1;
 
292
                }
 
293
                /* add trailing NULL (also removes trailing ',' */
 
294
                gr_mem_str[size-1] = '\0';
 
295
        }
 
296
        else {
 
297
                /* no members */
 
298
                gr_mem_str = smb_xmalloc(sizeof(fstring));
 
299
                fstrcpy( gr_mem_str, "" );
 
300
        }
 
301
 
 
302
        ret = pstr_sprintf( string, "%s:%s:%lu:%s",
 
303
                grp->gr_name, 
 
304
                grp->gr_passwd ? grp->gr_passwd : "*",
 
305
                (unsigned long)grp->gr_gid,
 
306
                gr_mem_str );
 
307
                
 
308
        SAFE_FREE( gr_mem_str );
 
309
                
 
310
        if ( ret < 0 ) {
 
311
                DEBUG(0,("group2string: pstr_sprintf() failed!\n"));
 
312
                return NULL;
 
313
        }
 
314
                
 
315
        return string;  
 
316
}
 
317
 
 
318
/**********************************************************************
 
319
**********************************************************************/
 
320
 
 
321
static char* acct_userkey_byname( const char *name )
 
322
{
 
323
        static fstring key;
 
324
        
 
325
        fstr_sprintf( key, "%s/NAME/%s", WBKEY_PASSWD, name );
 
326
        
 
327
        return key;             
 
328
}
 
329
 
 
330
/**********************************************************************
 
331
**********************************************************************/
 
332
 
 
333
static char* acct_userkey_byuid( uid_t uid )
 
334
{
 
335
        static fstring key;
 
336
        
 
337
        fstr_sprintf( key, "%s/UID/%lu", WBKEY_PASSWD, (unsigned long)uid );
 
338
        
 
339
        return key;             
 
340
}
 
341
 
 
342
/**********************************************************************
 
343
**********************************************************************/
 
344
 
 
345
static char* acct_groupkey_byname( const char *name )
 
346
{
 
347
        static fstring key;
 
348
        
 
349
        fstr_sprintf( key, "%s/NAME/%s", WBKEY_GROUP, name );
 
350
        
 
351
        return key;             
 
352
}
 
353
 
 
354
/**********************************************************************
 
355
**********************************************************************/
 
356
 
 
357
static char* acct_groupkey_bygid( gid_t gid )
 
358
{
 
359
        static fstring key;
 
360
        
 
361
        fstr_sprintf( key, "%s/GID/%lu", WBKEY_GROUP, (unsigned long)gid );
 
362
        
 
363
        return key;             
 
364
}
 
365
 
 
366
/**********************************************************************
 
367
**********************************************************************/
 
368
 
 
369
WINBINDD_PW* wb_getpwnam( const char * name )
 
370
{
 
371
        char *keystr;
 
372
        TDB_DATA data;
 
373
        static WINBINDD_PW *pw;
 
374
        
 
375
        if ( !account_tdb && !winbindd_accountdb_init() ) {
 
376
                DEBUG(0,("wb_getpwnam: Failed to open winbindd account db\n"));
 
377
                return NULL;
 
378
        }
 
379
                
 
380
        
 
381
        keystr = acct_userkey_byname( name );
 
382
        
 
383
        data = tdb_fetch_bystring( account_tdb, keystr );
 
384
        
 
385
        pw = NULL;
 
386
        
 
387
        if ( data.dptr ) {
 
388
                pw = string2passwd( data.dptr );
 
389
                SAFE_FREE( data.dptr );
 
390
        }
 
391
                
 
392
        DEBUG(5,("wb_getpwnam: %s user (%s)\n", 
 
393
                (pw ? "Found" : "Did not find"), name ));
 
394
        
 
395
        return pw;
 
396
}
 
397
 
 
398
/**********************************************************************
 
399
**********************************************************************/
 
400
 
 
401
WINBINDD_PW* wb_getpwuid( const uid_t uid )
 
402
{
 
403
        char *keystr;
 
404
        TDB_DATA data;
 
405
        static WINBINDD_PW *pw;
 
406
        
 
407
        if ( !account_tdb && !winbindd_accountdb_init() ) {
 
408
                DEBUG(0,("wb_getpwuid: Failed to open winbindd account db\n"));
 
409
                return NULL;
 
410
        }
 
411
        
 
412
        data = tdb_fetch_bystring( account_tdb, acct_userkey_byuid(uid) );
 
413
        if ( !data.dptr ) {
 
414
                DEBUG(4,("wb_getpwuid: failed to locate uid == %lu\n", (unsigned long)uid));
 
415
                return NULL;
 
416
        }
 
417
        keystr = acct_userkey_byname( data.dptr );
 
418
 
 
419
        SAFE_FREE( data.dptr );
 
420
        
 
421
        data = tdb_fetch_bystring( account_tdb, keystr );
 
422
        
 
423
        pw = NULL;
 
424
        
 
425
        if ( data.dptr ) {
 
426
                pw = string2passwd( data.dptr );
 
427
                SAFE_FREE( data.dptr );
 
428
        }
 
429
 
 
430
        DEBUG(5,("wb_getpwuid: %s user (uid == %lu)\n", 
 
431
                (pw ? "Found" : "Did not find"), (unsigned long)uid ));
 
432
        
 
433
        return pw;
 
434
}
 
435
 
 
436
/**********************************************************************
 
437
**********************************************************************/
 
438
 
 
439
static BOOL wb_storepwnam( const WINBINDD_PW *pw )
 
440
{
 
441
        char *namekey, *uidkey;
 
442
        TDB_DATA data;
 
443
        char *str;
 
444
        int ret = 0;
 
445
        fstring username;
 
446
 
 
447
        if ( !account_tdb && !winbindd_accountdb_init() ) {
 
448
                DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n"));
 
449
                return False;
 
450
        }
 
451
 
 
452
        namekey = acct_userkey_byname( pw->pw_name );
 
453
        
 
454
        /* lock the main entry first */
 
455
        
 
456
        if ( tdb_lock_bystring(account_tdb, namekey, 0) == -1 ) {
 
457
                DEBUG(0,("wb_storepwnam: Failed to lock %s\n", namekey));
 
458
                return False;
 
459
        }
 
460
        
 
461
        str = passwd2string( pw );
 
462
 
 
463
        data.dptr = str;
 
464
        data.dsize = strlen(str) + 1;   
 
465
 
 
466
        if ( (tdb_store_bystring(account_tdb, namekey, data, TDB_REPLACE)) == -1 ) {
 
467
                DEBUG(0,("wb_storepwnam: Failed to store \"%s\"\n", str));
 
468
                ret = -1;
 
469
                goto done;
 
470
        }
 
471
        
 
472
        /* store the uid index */
 
473
        
 
474
        uidkey = acct_userkey_byuid(pw->pw_uid);
 
475
        
 
476
        fstrcpy( username, pw->pw_name );
 
477
        data.dptr = username;
 
478
        data.dsize = strlen(username) + 1;
 
479
        
 
480
        if ( (tdb_store_bystring(account_tdb, uidkey, data, TDB_REPLACE)) == -1 ) {
 
481
                DEBUG(0,("wb_storepwnam: Failed to store uid key \"%s\"\n", str));
 
482
                tdb_delete_bystring(account_tdb, namekey);
 
483
                ret = -1;
 
484
                goto done;
 
485
        }               
 
486
        
 
487
        DEBUG(10,("wb_storepwnam: Success -> \"%s\"\n", str));
 
488
 
 
489
done:   
 
490
        tdb_unlock_bystring( account_tdb, namekey );
 
491
        
 
492
        return ( ret == 0 );
 
493
}
 
494
 
 
495
/**********************************************************************
 
496
**********************************************************************/
 
497
 
 
498
WINBINDD_GR* wb_getgrnam( const char * name )
 
499
{
 
500
        char *keystr;
 
501
        TDB_DATA data;
 
502
        static WINBINDD_GR *grp;
 
503
        
 
504
        if ( !account_tdb && !winbindd_accountdb_init() ) {
 
505
                DEBUG(0,("wb_getgrnam: Failed to open winbindd account db\n"));
 
506
                return NULL;
 
507
        }
 
508
                
 
509
        
 
510
        keystr = acct_groupkey_byname( name );
 
511
        
 
512
        data = tdb_fetch_bystring( account_tdb, keystr );
 
513
        
 
514
        grp = NULL;
 
515
        
 
516
        if ( data.dptr ) {
 
517
                grp = string2group( data.dptr );
 
518
                SAFE_FREE( data.dptr );
 
519
        }
 
520
                
 
521
        DEBUG(5,("wb_getgrnam: %s group (%s)\n", 
 
522
                (grp ? "Found" : "Did not find"), name ));
 
523
        
 
524
        return grp;
 
525
}
 
526
 
 
527
/**********************************************************************
 
528
**********************************************************************/
 
529
 
 
530
WINBINDD_GR* wb_getgrgid( gid_t gid )
 
531
{
 
532
        char *keystr;
 
533
        TDB_DATA data;
 
534
        static WINBINDD_GR *grp;
 
535
        
 
536
        if ( !account_tdb && !winbindd_accountdb_init() ) {
 
537
                DEBUG(0,("wb_getgrgid: Failed to open winbindd account db\n"));
 
538
                return NULL;
 
539
        }
 
540
        
 
541
        data = tdb_fetch_bystring( account_tdb, acct_groupkey_bygid(gid) );
 
542
        if ( !data.dptr ) {
 
543
                DEBUG(4,("wb_getgrgid: failed to locate gid == %lu\n", 
 
544
                         (unsigned long)gid));
 
545
                return NULL;
 
546
        }
 
547
        keystr = acct_groupkey_byname( data.dptr );
 
548
 
 
549
        SAFE_FREE( data.dptr );
 
550
        
 
551
        data = tdb_fetch_bystring( account_tdb, keystr );
 
552
        
 
553
        grp = NULL;
 
554
        
 
555
        if ( data.dptr ) {
 
556
                grp = string2group( data.dptr );
 
557
                SAFE_FREE( data.dptr );
 
558
        }
 
559
 
 
560
        DEBUG(5,("wb_getgrgid: %s group (gid == %lu)\n", 
 
561
                (grp ? "Found" : "Did not find"), (unsigned long)gid ));
 
562
        
 
563
        return grp;
 
564
}
 
565
 
 
566
/**********************************************************************
 
567
**********************************************************************/
 
568
 
 
569
static BOOL wb_storegrnam( const WINBINDD_GR *grp )
 
570
{
 
571
        char *namekey, *gidkey;
 
572
        TDB_DATA data;
 
573
        char *str;
 
574
        int ret = 0;
 
575
        fstring groupname;
 
576
 
 
577
        if ( !account_tdb && !winbindd_accountdb_init() ) {
 
578
                DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n"));
 
579
                return False;
 
580
        }
 
581
 
 
582
        namekey = acct_groupkey_byname( grp->gr_name );
 
583
        
 
584
        /* lock the main entry first */
 
585
        
 
586
        if ( tdb_lock_bystring(account_tdb, namekey, 0) == -1 ) {
 
587
                DEBUG(0,("wb_storegrnam: Failed to lock %s\n", namekey));
 
588
                return False;
 
589
        }
 
590
        
 
591
        str = group2string( grp );
 
592
 
 
593
        data.dptr = str;
 
594
        data.dsize = strlen(str) + 1;   
 
595
 
 
596
        if ( (tdb_store_bystring(account_tdb, namekey, data, TDB_REPLACE)) == -1 ) {
 
597
                DEBUG(0,("wb_storegrnam: Failed to store \"%s\"\n", str));
 
598
                ret = -1;
 
599
                goto done;
 
600
        }
 
601
        
 
602
        /* store the gid index */
 
603
        
 
604
        gidkey = acct_groupkey_bygid(grp->gr_gid);
 
605
        
 
606
        fstrcpy( groupname, grp->gr_name );
 
607
        data.dptr = groupname;
 
608
        data.dsize = strlen(groupname) + 1;
 
609
        
 
610
        if ( (tdb_store_bystring(account_tdb, gidkey, data, TDB_REPLACE)) == -1 ) {
 
611
                DEBUG(0,("wb_storegrnam: Failed to store gid key \"%s\"\n", str));
 
612
                tdb_delete_bystring(account_tdb, namekey);
 
613
                ret = -1;
 
614
                goto done;
 
615
        }
 
616
        
 
617
        DEBUG(10,("wb_storegrnam: Success -> \"%s\"\n", str));
 
618
 
 
619
done:   
 
620
        tdb_unlock_bystring( account_tdb, namekey );
 
621
        
 
622
        return ( ret == 0 );
 
623
}
 
624
 
 
625
/**********************************************************************
 
626
**********************************************************************/
 
627
 
 
628
static BOOL wb_addgrpmember( WINBINDD_GR *grp, const char *user )
 
629
{
 
630
        int i;
 
631
        char **members;
 
632
        
 
633
        if ( !grp || !user )
 
634
                return False;
 
635
        
 
636
        for ( i=0; i<grp->num_gr_mem; i++ ) {
 
637
                if ( StrCaseCmp( grp->gr_mem[i], user ) == 0 )
 
638
                        return True;
 
639
        }
 
640
        
 
641
        /* add one new slot and keep an extra for the terminating NULL */
 
642
        members = Realloc( grp->gr_mem, (grp->num_gr_mem+2)*sizeof(char*) );
 
643
        if ( !members )
 
644
                return False;
 
645
                
 
646
        grp->gr_mem = members;
 
647
        grp->gr_mem[grp->num_gr_mem++] = smb_xstrdup(user);
 
648
        grp->gr_mem[grp->num_gr_mem]   = NULL;
 
649
                
 
650
        return True;
 
651
}
 
652
 
 
653
/**********************************************************************
 
654
**********************************************************************/
 
655
 
 
656
static BOOL wb_delgrpmember( WINBINDD_GR *grp, const char *user )
 
657
{
 
658
        int i;
 
659
        BOOL found = False;
 
660
        
 
661
        if ( !grp || !user )
 
662
                return False;
 
663
        
 
664
        for ( i=0; i<grp->num_gr_mem; i++ ) {
 
665
                if ( StrCaseCmp( grp->gr_mem[i], user ) == 0 ) {
 
666
                        found = True;
 
667
                        break;
 
668
                }
 
669
        }
 
670
        
 
671
        if ( !found ) 
 
672
                return False;
 
673
 
 
674
        /* still some remaining members */
 
675
 
 
676
        if ( grp->num_gr_mem > 1 ) {
 
677
                SAFE_FREE(grp->gr_mem[i]);
 
678
                grp->num_gr_mem--;
 
679
                grp->gr_mem[i] = grp->gr_mem[grp->num_gr_mem];
 
680
                grp->gr_mem[grp->num_gr_mem] = NULL;
 
681
        }
 
682
        else {  /* last one */
 
683
                free_winbindd_gr( grp );
 
684
                grp->gr_mem = NULL;
 
685
                grp->num_gr_mem = 0;
 
686
        }
 
687
                                
 
688
        return True;
 
689
}
 
690
 
 
691
/**********************************************************************
 
692
**********************************************************************/
 
693
 
 
694
static int cleangroups_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, 
 
695
                       void *state)
 
696
{
 
697
        int len;
 
698
        fstring key;
 
699
        char *name = (char*)state;
 
700
        
 
701
        fstr_sprintf( key, "%s/NAME", WBKEY_GROUP );
 
702
        len = strlen(key);
 
703
        
 
704
        /* if this is a group entry then, check the members */
 
705
        
 
706
        if ( (strncmp(kbuf.dptr, key, len) == 0) && dbuf.dptr ) {
 
707
                WINBINDD_GR *grp;
 
708
                
 
709
                if ( !(grp = string2group( dbuf.dptr )) ) {
 
710
                        DEBUG(0,("cleangroups_traverse_fn: Failure to parse [%s]\n",
 
711
                                dbuf.dptr));
 
712
                        return 0;
 
713
                }
 
714
                
 
715
                /* just try to delete the user and rely on wb_delgrpmember()
 
716
                   to tell you whether or not the group changed.  This is more 
 
717
                   effecient than testing group membership first since the 
 
718
                   checks for deleting a user from a group is essentially the 
 
719
                   same as checking if he/she is a member */
 
720
                   
 
721
                if ( wb_delgrpmember( grp, name ) ) {
 
722
                        DEBUG(10,("cleanupgroups_traverse_fn: Removed user (%s) from group (%s)\n",
 
723
                                name, grp->gr_name));
 
724
                        wb_storegrnam( grp );
 
725
                }
 
726
                
 
727
                free_winbindd_gr( grp );
 
728
        }
 
729
 
 
730
        return 0;
 
731
}
 
732
 
 
733
/**********************************************************************
 
734
**********************************************************************/
 
735
 
 
736
static BOOL wb_delete_user( WINBINDD_PW *pw)
 
737
{
 
738
        char *namekey;
 
739
        char *uidkey;
 
740
        
 
741
        if ( !account_tdb && !winbindd_accountdb_init() ) {
 
742
                DEBUG(0,("wb_delete_user: Failed to open winbindd account db\n"));
 
743
                return False;
 
744
        }
 
745
 
 
746
        namekey = acct_userkey_byname( pw->pw_name );
 
747
        
 
748
        /* lock the main entry first */
 
749
        
 
750
        if ( tdb_lock_bystring(account_tdb, namekey, 0) == -1 ) {
 
751
                DEBUG(0,("wb_delete_user: Failed to lock %s\n", namekey));
 
752
                return False;
 
753
        }
 
754
        
 
755
        /* remove user from all groups */
 
756
        
 
757
        tdb_traverse(account_tdb, cleangroups_traverse_fn, (void *)pw->pw_name);
 
758
        
 
759
        /* remove the user */
 
760
        uidkey = acct_userkey_byuid( pw->pw_uid );
 
761
        
 
762
        tdb_delete_bystring( account_tdb, namekey );
 
763
        tdb_delete_bystring( account_tdb, uidkey );
 
764
        
 
765
        tdb_unlock_bystring( account_tdb, namekey );
 
766
        
 
767
        return True;
 
768
}
 
769
 
 
770
/**********************************************************************
 
771
**********************************************************************/
 
772
 
 
773
static int isprimarygroup_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, 
 
774
                                      TDB_DATA dbuf, void *params)
 
775
{
 
776
        int len;
 
777
        fstring key;
 
778
        struct _check_primary_grp *check = (struct _check_primary_grp*)params;
 
779
        
 
780
        fstr_sprintf( key, "%s/NAME", WBKEY_PASSWD );
 
781
        len = strlen(key);
 
782
        
 
783
        /* if this is a group entry then, check the members */
 
784
        
 
785
        if ( (strncmp(kbuf.dptr, key, len) == 0) && dbuf.dptr ) {
 
786
                WINBINDD_PW *pw;;
 
787
                
 
788
                if ( !(pw = string2passwd( dbuf.dptr )) ) {
 
789
                        DEBUG(0,("isprimarygroup_traverse_fn: Failure to parse [%s]\n",
 
790
                                dbuf.dptr));
 
791
                        return 0;
 
792
                }
 
793
                
 
794
                if ( check->gid == pw->pw_gid ) {
 
795
                        check->found = True;
 
796
                        return 1;
 
797
                }
 
798
        }
 
799
 
 
800
        return 0;
 
801
}
 
802
 
 
803
 
 
804
/**********************************************************************
 
805
**********************************************************************/
 
806
 
 
807
static BOOL wb_delete_group( WINBINDD_GR *grp )
 
808
{
 
809
        struct _check_primary_grp check;
 
810
        char *namekey;
 
811
        char *gidkey;
 
812
        
 
813
        if ( !account_tdb && !winbindd_accountdb_init() ) {
 
814
                DEBUG(0,("wb_delete_group: Failed to open winbindd account db\n"));
 
815
                return False;
 
816
        }
 
817
        
 
818
        /* lock the main entry first */
 
819
        
 
820
        namekey = acct_groupkey_byname( grp->gr_name ); 
 
821
        if ( tdb_lock_bystring(account_tdb, namekey, 0) == -1 ) {
 
822
                DEBUG(0,("wb_delete_group: Failed to lock %s\n", namekey));
 
823
                return False;
 
824
        }
 
825
        
 
826
        /* is this group the primary group for any user?  If 
 
827
           so deny delete */
 
828
           
 
829
        check.found = False;    
 
830
        tdb_traverse(account_tdb, isprimarygroup_traverse_fn, (void *)&check);
 
831
        
 
832
        if ( check.found ) {
 
833
                DEBUG(4,("wb_delete_group: Cannot delete group (%s) since it "
 
834
                        "is the primary group for some users\n", grp->gr_name));
 
835
                return False;
 
836
        }
 
837
        
 
838
        /* We're clear.  Delete the group */
 
839
        
 
840
        DEBUG(5,("wb_delete_group: Removing group (%s)\n", grp->gr_name));
 
841
        
 
842
        gidkey = acct_groupkey_bygid( grp->gr_gid );
 
843
        
 
844
        tdb_delete_bystring( account_tdb, namekey );
 
845
        tdb_delete_bystring( account_tdb, gidkey );
 
846
        
 
847
        tdb_unlock_bystring( account_tdb, namekey );
 
848
        
 
849
        return True;
 
850
}
 
851
 
 
852
/**********************************************************************
 
853
 Create a new "UNIX" user for the system given a username
 
854
**********************************************************************/
 
855
 
 
856
enum winbindd_result winbindd_create_user(struct winbindd_cli_state *state)
 
857
{
 
858
        char *user, *group;
 
859
        unid_t id;
 
860
        WINBINDD_PW pw, *pw_check;
 
861
        WINBINDD_GR *wb_grp;
 
862
        struct group *unix_grp;
 
863
        gid_t primary_gid;
 
864
        uint32 flags = state->request.flags;
 
865
        uint32 rid;
 
866
        
 
867
        if ( !state->privileged ) {
 
868
                DEBUG(2, ("winbindd_create_user: non-privileged access denied!\n"));
 
869
                return WINBINDD_ERROR;
 
870
        }
 
871
        
 
872
        /* Ensure null termination */
 
873
        state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';
 
874
        state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
 
875
        
 
876
        user  = state->request.data.acct_mgt.username;
 
877
        group = state->request.data.acct_mgt.groupname;
 
878
        
 
879
        DEBUG(3, ("[%5lu]: create_user: user=>(%s), group=>(%s)\n", 
 
880
                (unsigned long)state->pid, user, group));
 
881
 
 
882
        if ( (pw_check=wb_getpwnam(user)) != NULL ) {
 
883
                DEBUG(0,("winbindd_create_user: Refusing to create user that already exists (%s)\n", 
 
884
                        user));
 
885
                return WINBINDD_ERROR;
 
886
        }
 
887
 
 
888
                
 
889
        if ( !*group )
 
890
                group = lp_template_primary_group();
 
891
                
 
892
        /* validate the primary group
 
893
           1) lookup in local tdb first
 
894
           2) call getgrnam() as a last resort */
 
895
           
 
896
        if ( (wb_grp=wb_getgrnam(group)) != NULL ) {
 
897
                primary_gid = wb_grp->gr_gid;
 
898
                free_winbindd_gr( wb_grp );
 
899
        }
 
900
        else if ( (unix_grp=sys_getgrnam(group)) != NULL ) {
 
901
                primary_gid = unix_grp->gr_gid; 
 
902
        }
 
903
        else {
 
904
                DEBUG(2,("winbindd_create_user: Cannot validate gid for group (%s)\n", group));
 
905
                return WINBINDD_ERROR;
 
906
        }
 
907
 
 
908
        /* get a new uid */
 
909
        
 
910
        if ( !NT_STATUS_IS_OK(idmap_allocate_id( &id, ID_USERID)) ) {
 
911
                DEBUG(0,("winbindd_create_user: idmap_allocate_id() failed!\n"));
 
912
                return WINBINDD_ERROR;
 
913
        }
 
914
        
 
915
        /* The substitution of %U and %D in the 'template homedir' is done
 
916
           by lp_string() calling standard_sub_basic(). */
 
917
 
 
918
        fstrcpy( current_user_info.smb_name, user );
 
919
        sub_set_smb_name( user );
 
920
        fstrcpy( current_user_info.domain, get_global_sam_name() );
 
921
        
 
922
        /* fill in the passwd struct */
 
923
                
 
924
        fstrcpy( pw.pw_name,   user );
 
925
        fstrcpy( pw.pw_passwd, "x" );
 
926
        fstrcpy( pw.pw_gecos,  user);
 
927
        fstrcpy( pw.pw_dir,    lp_template_homedir() );
 
928
        fstrcpy( pw.pw_shell,  lp_template_shell() );
 
929
        
 
930
        pw.pw_uid = id.uid;
 
931
        pw.pw_gid = primary_gid;
 
932
        
 
933
        /* store the new entry */
 
934
        
 
935
        if ( !wb_storepwnam(&pw) )
 
936
                return WINBINDD_ERROR;
 
937
                
 
938
        /* do we need a new RID? */
 
939
        
 
940
        if ( flags & WBFLAG_ALLOCATE_RID ) {
 
941
                if ( !NT_STATUS_IS_OK(idmap_allocate_rid(&rid, USER_RID_TYPE)) ) {
 
942
                        DEBUG(0,("winbindd_create_user: RID allocation failure!  Cannot create user (%s)\n",
 
943
                                user));
 
944
                        wb_delete_user( &pw );
 
945
                        
 
946
                        return WINBINDD_ERROR;
 
947
                }
 
948
                
 
949
                state->response.data.rid = rid;
 
950
        }
 
951
 
 
952
        return WINBINDD_OK;
 
953
}
 
954
 
 
955
/**********************************************************************
 
956
 Create a new "UNIX" group for the system given a username
 
957
**********************************************************************/
 
958
 
 
959
enum winbindd_result winbindd_create_group(struct winbindd_cli_state *state)
 
960
{
 
961
        char *group;
 
962
        unid_t id;
 
963
        WINBINDD_GR grp, *grp_check;
 
964
        uint32 flags = state->request.flags;
 
965
        uint32 rid;
 
966
        
 
967
        if ( !state->privileged ) {
 
968
                DEBUG(2, ("winbindd_create_group: non-privileged access denied!\n"));
 
969
                return WINBINDD_ERROR;
 
970
        }
 
971
        
 
972
        /* Ensure null termination */
 
973
        state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';  
 
974
        group = state->request.data.acct_mgt.groupname;
 
975
        
 
976
        DEBUG(3, ("[%5lu]: create_group: (%s)\n", (unsigned long)state->pid, group));
 
977
        
 
978
        if ( (grp_check=wb_getgrnam(group)) != NULL ) {
 
979
                DEBUG(0,("winbindd_create_group: Refusing to create group that already exists (%s)\n", 
 
980
                        group));
 
981
                return WINBINDD_ERROR;
 
982
        }
 
983
        
 
984
        /* get a new gid */
 
985
        
 
986
        if ( !NT_STATUS_IS_OK(idmap_allocate_id( &id, ID_GROUPID)) ) {
 
987
                DEBUG(0,("winbindd_create_group: idmap_allocate_id() failed!\n"));
 
988
                return WINBINDD_ERROR;
 
989
        }
 
990
        
 
991
        /* fill in the group struct */
 
992
                
 
993
        fstrcpy( grp.gr_name,   group );
 
994
        fstrcpy( grp.gr_passwd, "*" );
 
995
        
 
996
        grp.gr_gid      = id.gid;
 
997
        grp.gr_mem      = NULL; /* start with no members */
 
998
        grp.num_gr_mem  = 0;
 
999
        
 
1000
        if ( !wb_storegrnam(&grp) )
 
1001
                return WINBINDD_ERROR;
 
1002
                
 
1003
        /* do we need a new RID? */
 
1004
        
 
1005
        if ( flags & WBFLAG_ALLOCATE_RID ) {
 
1006
                if ( !NT_STATUS_IS_OK(idmap_allocate_rid(&rid, GROUP_RID_TYPE)) ) {
 
1007
                        DEBUG(0,("winbindd_create_group: RID allocation failure!  Cannot create group (%s)\n",
 
1008
                                group));
 
1009
                        wb_delete_group( &grp );
 
1010
                        
 
1011
                        return WINBINDD_ERROR;
 
1012
                }
 
1013
                
 
1014
                state->response.data.rid = rid;
 
1015
        }
 
1016
 
 
1017
        return WINBINDD_OK;
 
1018
}
 
1019
 
 
1020
/**********************************************************************
 
1021
 Add a user to the membership for a group.
 
1022
**********************************************************************/
 
1023
 
 
1024
enum winbindd_result winbindd_add_user_to_group(struct winbindd_cli_state *state)
 
1025
{
 
1026
        WINBINDD_PW *pw;
 
1027
        WINBINDD_GR *grp;
 
1028
        char *user, *group;
 
1029
        BOOL ret;
 
1030
        
 
1031
        if ( !state->privileged ) {
 
1032
                DEBUG(2, ("winbindd_add_user_to_group: non-privileged access denied!\n"));
 
1033
                return WINBINDD_ERROR;
 
1034
        }
 
1035
        
 
1036
        /* Ensure null termination */
 
1037
        state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';  
 
1038
        state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';    
 
1039
        group = state->request.data.acct_mgt.groupname;
 
1040
        user = state->request.data.acct_mgt.username;
 
1041
        
 
1042
        DEBUG(3, ("[%5lu]:  add_user_to_group: add %s to %s\n", (unsigned long)state->pid, 
 
1043
                user, group));
 
1044
        
 
1045
        /* make sure it is a valid user */
 
1046
        
 
1047
        if ( !(pw = wb_getpwnam( user )) ) {
 
1048
                DEBUG(4,("winbindd_add_user_to_group: Cannot add a non-existent user\n"));
 
1049
                return WINBINDD_ERROR;
 
1050
        }
 
1051
        
 
1052
        /* make sure it is a valid group */
 
1053
        
 
1054
        if ( !(grp = wb_getgrnam( group )) ) {
 
1055
                DEBUG(4,("winbindd_add_user_to_group: Cannot add a user to a non-extistent group\n"));
 
1056
                return WINBINDD_ERROR;  
 
1057
        }
 
1058
        
 
1059
        if ( !wb_addgrpmember( grp, user ) )
 
1060
                return WINBINDD_ERROR;
 
1061
                
 
1062
        ret = wb_storegrnam(grp);
 
1063
        
 
1064
        free_winbindd_gr( grp );
 
1065
        
 
1066
        return ( ret ? WINBINDD_OK : WINBINDD_ERROR );
 
1067
}
 
1068
 
 
1069
/**********************************************************************
 
1070
 Remove a user from the membership of a group
 
1071
**********************************************************************/
 
1072
 
 
1073
enum winbindd_result winbindd_remove_user_from_group(struct winbindd_cli_state *state)
 
1074
{
 
1075
        WINBINDD_GR *grp;
 
1076
        char *user, *group;
 
1077
        BOOL ret;
 
1078
 
 
1079
        if ( !state->privileged ) {
 
1080
                DEBUG(2, ("winbindd_remove_user_from_group: non-privileged access denied!\n"));
 
1081
                return WINBINDD_ERROR;
 
1082
        }
 
1083
        
 
1084
        /* Ensure null termination */
 
1085
        state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';  
 
1086
        state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';    
 
1087
        group = state->request.data.acct_mgt.groupname;
 
1088
        user = state->request.data.acct_mgt.username;
 
1089
        
 
1090
        DEBUG(3, ("[%5lu]:  remove_user_from_group: delete %s from %s\n", (unsigned long)state->pid, 
 
1091
                user, group));
 
1092
        
 
1093
        /* don't worry about checking the username since we're removing it anyways */
 
1094
        
 
1095
        /* make sure it is a valid group */
 
1096
        
 
1097
        if ( !(grp = wb_getgrnam( group )) ) {
 
1098
                DEBUG(4,("winbindd_remove_user_from_group: Cannot remove a user from a non-extistent group\n"));
 
1099
                return WINBINDD_ERROR;  
 
1100
        }
 
1101
        
 
1102
        if ( !wb_delgrpmember( grp, user ) )
 
1103
                return WINBINDD_ERROR;
 
1104
                
 
1105
        ret = wb_storegrnam(grp);
 
1106
        
 
1107
        free_winbindd_gr( grp );
 
1108
        
 
1109
        return ( ret ? WINBINDD_OK : WINBINDD_ERROR );
 
1110
}
 
1111
 
 
1112
/**********************************************************************
 
1113
 Set the primary group membership of a user
 
1114
**********************************************************************/
 
1115
 
 
1116
enum winbindd_result winbindd_set_user_primary_group(struct winbindd_cli_state *state)
 
1117
{
 
1118
        WINBINDD_PW *pw;
 
1119
        WINBINDD_GR *grp;
 
1120
        char *user, *group;
 
1121
 
 
1122
        if ( !state->privileged ) {
 
1123
                DEBUG(2, ("winbindd_set_user_primary_group: non-privileged access denied!\n"));
 
1124
                return WINBINDD_ERROR;
 
1125
        }
 
1126
        
 
1127
        /* Ensure null termination */
 
1128
        state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';  
 
1129
        state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';    
 
1130
        group = state->request.data.acct_mgt.groupname;
 
1131
        user = state->request.data.acct_mgt.username;
 
1132
        
 
1133
        DEBUG(3, ("[%5lu]:  set_user_primary_group: group %s for user %s\n", 
 
1134
                  (unsigned long)state->pid, group, user));
 
1135
        
 
1136
        /* make sure it is a valid user */
 
1137
        
 
1138
        if ( !(pw = wb_getpwnam( user )) ) {
 
1139
                DEBUG(4,("winbindd_add_user_to_group: Cannot add a non-existent user\n"));
 
1140
                return WINBINDD_ERROR;
 
1141
        }
 
1142
        
 
1143
        /* make sure it is a valid group */
 
1144
        
 
1145
        if ( !(grp = wb_getgrnam( group )) ) {
 
1146
                DEBUG(4,("winbindd_add_user_to_group: Cannot add a user to a non-extistent group\n"));
 
1147
                return WINBINDD_ERROR;  
 
1148
        }
 
1149
        
 
1150
        pw->pw_gid = grp->gr_gid;
 
1151
 
 
1152
        free_winbindd_gr( grp );
 
1153
                
 
1154
        return ( wb_storepwnam(pw) ? WINBINDD_OK : WINBINDD_ERROR );
 
1155
}
 
1156
 
 
1157
/**********************************************************************
 
1158
 Delete a user from the winbindd account tdb.
 
1159
**********************************************************************/
 
1160
 
 
1161
enum winbindd_result winbindd_delete_user(struct winbindd_cli_state *state)
 
1162
{
 
1163
        WINBINDD_PW *pw;
 
1164
        char *user;
 
1165
 
 
1166
        if ( !state->privileged ) {
 
1167
                DEBUG(2, ("winbindd_delete_user: non-privileged access denied!\n"));
 
1168
                return WINBINDD_ERROR;
 
1169
        }
 
1170
        
 
1171
        /* Ensure null termination */
 
1172
        state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';    
 
1173
        user = state->request.data.acct_mgt.username;
 
1174
        
 
1175
        DEBUG(3, ("[%5lu]:  delete_user: %s\n", (unsigned long)state->pid, user));
 
1176
        
 
1177
        /* make sure it is a valid user */
 
1178
        
 
1179
        if ( !(pw = wb_getpwnam( user )) ) {
 
1180
                DEBUG(4,("winbindd_delete_user: Cannot delete a non-existent user\n"));
 
1181
                return WINBINDD_ERROR;
 
1182
        }
 
1183
        
 
1184
        return ( wb_delete_user(pw) ? WINBINDD_OK : WINBINDD_ERROR );
 
1185
}
 
1186
 
 
1187
/**********************************************************************
 
1188
 Delete a group from winbindd's account tdb. 
 
1189
**********************************************************************/
 
1190
 
 
1191
enum winbindd_result winbindd_delete_group(struct winbindd_cli_state *state)
 
1192
{
 
1193
        WINBINDD_GR *grp;
 
1194
        char *group;
 
1195
        BOOL ret;
 
1196
 
 
1197
        if ( !state->privileged ) {
 
1198
                DEBUG(2, ("winbindd_delete_group: non-privileged access denied!\n"));
 
1199
                return WINBINDD_ERROR;
 
1200
        }
 
1201
        
 
1202
        /* Ensure null termination */
 
1203
        state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';   
 
1204
        group = state->request.data.acct_mgt.groupname;
 
1205
        
 
1206
        DEBUG(3, ("[%5lu]:  delete_group: %s\n", (unsigned long)state->pid, group));
 
1207
        
 
1208
        /* make sure it is a valid group */
 
1209
        
 
1210
        if ( !(grp = wb_getgrnam( group )) ) {
 
1211
                DEBUG(4,("winbindd_delete_group: Cannot delete a non-existent group\n"));
 
1212
                return WINBINDD_ERROR;
 
1213
        }
 
1214
        
 
1215
        ret = wb_delete_group(grp);
 
1216
        
 
1217
        free_winbindd_gr( grp );
 
1218
        
 
1219
        return ( ret ? WINBINDD_OK : WINBINDD_ERROR );
 
1220
}
 
1221
 
 
1222
 
 
1223