r22787: More from Karolin: Make map_unix_group() static to net_sam.c, add "net
[metze/samba/wip.git] / source3 / groupdb / mapping.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Jean François Micouleau      1998-2001.
6  *  Copyright (C) Volker Lendecke              2006.
7  *  Copyright (C) Gerald Carter                2006.
8  *  
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *  
14  *  This program 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
17  *  GNU General Public License for more details.
18  *  
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24 #include "includes.h"
25 #include "groupdb/mapping.h"
26
27 /****************************************************************************
28 initialise first time the mapping list
29 ****************************************************************************/
30 NTSTATUS add_initial_entry(gid_t gid, const char *sid, enum lsa_SidType sid_name_use, const char *nt_name, const char *comment)
31 {
32         GROUP_MAP map;
33
34         if(!init_group_mapping()) {
35                 DEBUG(0,("failed to initialize group mapping\n"));
36                 return NT_STATUS_UNSUCCESSFUL;
37         }
38         
39         map.gid=gid;
40         if (!string_to_sid(&map.sid, sid)) {
41                 DEBUG(0, ("string_to_sid failed: %s", sid));
42                 return NT_STATUS_UNSUCCESSFUL;
43         }
44         
45         map.sid_name_use=sid_name_use;
46         fstrcpy(map.nt_name, nt_name);
47         fstrcpy(map.comment, comment);
48
49         return pdb_add_group_mapping_entry(&map);
50 }
51
52 static NTSTATUS alias_memberships(const DOM_SID *members, size_t num_members,
53                                   DOM_SID **sids, size_t *num)
54 {
55         size_t i;
56
57         *num = 0;
58         *sids = NULL;
59
60         for (i=0; i<num_members; i++) {
61                 NTSTATUS status = one_alias_membership(&members[i], sids, num);
62                 if (!NT_STATUS_IS_OK(status))
63                         return status;
64         }
65         return NT_STATUS_OK;
66 }
67
68 struct aliasmem_closure {
69         const DOM_SID *alias;
70         DOM_SID **sids;
71         size_t *num;
72 };
73
74
75
76 /*
77  *
78  * High level functions
79  * better to use them than the lower ones.
80  *
81  * we are checking if the group is in the mapping file
82  * and if the group is an existing unix group
83  *
84  */
85
86 /* get a domain group from it's SID */
87
88 BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map)
89 {
90         struct group *grp;
91         BOOL ret;
92         
93         if(!init_group_mapping()) {
94                 DEBUG(0,("failed to initialize group mapping\n"));
95                 return(False);
96         }
97
98         DEBUG(10, ("get_domain_group_from_sid\n"));
99
100         /* if the group is NOT in the database, it CAN NOT be a domain group */
101         
102         become_root();
103         ret = pdb_getgrsid(map, sid);
104         unbecome_root();
105         
106         /* special case check for rid 513 */
107         
108         if ( !ret ) {
109                 uint32 rid;
110                 
111                 sid_peek_rid( &sid, &rid );
112                 
113                 if ( rid == DOMAIN_GROUP_RID_USERS ) {
114                         fstrcpy( map->nt_name, "None" );
115                         fstrcpy( map->comment, "Ordinary Users" );
116                         sid_copy( &map->sid, &sid );
117                         map->sid_name_use = SID_NAME_DOM_GRP;
118                         
119                         return True;
120                 }
121                 
122                 return False;
123         }
124
125         DEBUG(10, ("get_domain_group_from_sid: SID found in the TDB\n"));
126
127         /* if it's not a domain group, continue */
128         if (map->sid_name_use!=SID_NAME_DOM_GRP) {
129                 return False;
130         }
131
132         DEBUG(10, ("get_domain_group_from_sid: SID is a domain group\n"));
133         
134         if (map->gid==-1) {
135                 return False;
136         }
137
138         DEBUG(10, ("get_domain_group_from_sid: SID is mapped to gid:%lu\n",(unsigned long)map->gid));
139         
140         grp = getgrgid(map->gid);
141         if ( !grp ) {
142                 DEBUG(10, ("get_domain_group_from_sid: gid DOESN'T exist in UNIX security\n"));
143                 return False;
144         }
145
146         DEBUG(10, ("get_domain_group_from_sid: gid exists in UNIX security\n"));
147
148         return True;
149 }
150
151 /****************************************************************************
152  Create a UNIX group on demand.
153 ****************************************************************************/
154
155 int smb_create_group(const char *unix_group, gid_t *new_gid)
156 {
157         pstring add_script;
158         int     ret = -1;
159         int     fd = 0;
160         
161         *new_gid = 0;
162
163         /* defer to scripts */
164         
165         if ( *lp_addgroup_script() ) {
166                 pstrcpy(add_script, lp_addgroup_script());
167                 pstring_sub(add_script, "%g", unix_group);
168                 ret = smbrun(add_script, &fd);
169                 DEBUG(ret ? 0 : 3,("smb_create_group: Running the command `%s' gave %d\n",add_script,ret));
170                 if (ret == 0) {
171                         smb_nscd_flush_group_cache();
172                 }
173                 if (ret != 0)
174                         return ret;
175
176                 if (fd != 0) {
177                         fstring output;
178
179                         *new_gid = 0;
180                         if (read(fd, output, sizeof(output)) > 0) {
181                                 *new_gid = (gid_t)strtoul(output, NULL, 10);
182                         }
183                         
184                         close(fd);
185                 }
186
187         }
188
189         if (*new_gid == 0) {
190                 struct group *grp = getgrnam(unix_group);
191
192                 if (grp != NULL)
193                         *new_gid = grp->gr_gid;
194         }
195                         
196         return ret;     
197 }
198
199 /****************************************************************************
200  Delete a UNIX group on demand.
201 ****************************************************************************/
202
203 int smb_delete_group(const char *unix_group)
204 {
205         pstring del_script;
206         int ret;
207
208         /* defer to scripts */
209         
210         if ( *lp_delgroup_script() ) {
211                 pstrcpy(del_script, lp_delgroup_script());
212                 pstring_sub(del_script, "%g", unix_group);
213                 ret = smbrun(del_script,NULL);
214                 DEBUG(ret ? 0 : 3,("smb_delete_group: Running the command `%s' gave %d\n",del_script,ret));
215                 if (ret == 0) {
216                         smb_nscd_flush_group_cache();
217                 }
218                 return ret;
219         }
220                 
221         return -1;
222 }
223
224 /****************************************************************************
225  Set a user's primary UNIX group.
226 ****************************************************************************/
227 int smb_set_primary_group(const char *unix_group, const char* unix_user)
228 {
229         pstring add_script;
230         int ret;
231
232         /* defer to scripts */
233         
234         if ( *lp_setprimarygroup_script() ) {
235                 pstrcpy(add_script, lp_setprimarygroup_script());
236                 all_string_sub(add_script, "%g", unix_group, sizeof(add_script));
237                 all_string_sub(add_script, "%u", unix_user, sizeof(add_script));
238                 ret = smbrun(add_script,NULL);
239                 flush_pwnam_cache();
240                 DEBUG(ret ? 0 : 3,("smb_set_primary_group: "
241                          "Running the command `%s' gave %d\n",add_script,ret));
242                 if (ret == 0) {
243                         smb_nscd_flush_group_cache();
244                 }
245                 return ret;
246         }
247
248         return -1;
249 }
250
251 /****************************************************************************
252  Add a user to a UNIX group.
253 ****************************************************************************/
254
255 int smb_add_user_group(const char *unix_group, const char *unix_user)
256 {
257         pstring add_script;
258         int ret;
259
260         /* defer to scripts */
261         
262         if ( *lp_addusertogroup_script() ) {
263                 pstrcpy(add_script, lp_addusertogroup_script());
264                 pstring_sub(add_script, "%g", unix_group);
265                 pstring_sub(add_script, "%u", unix_user);
266                 ret = smbrun(add_script,NULL);
267                 DEBUG(ret ? 0 : 3,("smb_add_user_group: Running the command `%s' gave %d\n",add_script,ret));
268                 if (ret == 0) {
269                         smb_nscd_flush_group_cache();
270                 }
271                 return ret;
272         }
273         
274         return -1;
275 }
276
277 /****************************************************************************
278  Delete a user from a UNIX group
279 ****************************************************************************/
280
281 int smb_delete_user_group(const char *unix_group, const char *unix_user)
282 {
283         pstring del_script;
284         int ret;
285
286         /* defer to scripts */
287         
288         if ( *lp_deluserfromgroup_script() ) {
289                 pstrcpy(del_script, lp_deluserfromgroup_script());
290                 pstring_sub(del_script, "%g", unix_group);
291                 pstring_sub(del_script, "%u", unix_user);
292                 ret = smbrun(del_script,NULL);
293                 DEBUG(ret ? 0 : 3,("smb_delete_user_group: Running the command `%s' gave %d\n",del_script,ret));
294                 if (ret == 0) {
295                         smb_nscd_flush_group_cache();
296                 }
297                 return ret;
298         }
299         
300         return -1;
301 }
302
303
304 NTSTATUS pdb_default_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
305                                  DOM_SID sid)
306 {
307         return get_group_map_from_sid(sid, map) ?
308                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
309 }
310
311 NTSTATUS pdb_default_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
312                                  gid_t gid)
313 {
314         return get_group_map_from_gid(gid, map) ?
315                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
316 }
317
318 NTSTATUS pdb_default_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
319                                  const char *name)
320 {
321         return get_group_map_from_ntname(name, map) ?
322                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
323 }
324
325 NTSTATUS pdb_default_add_group_mapping_entry(struct pdb_methods *methods,
326                                                 GROUP_MAP *map)
327 {
328         return add_mapping_entry(map, TDB_INSERT) ?
329                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
330 }
331
332 NTSTATUS pdb_default_update_group_mapping_entry(struct pdb_methods *methods,
333                                                    GROUP_MAP *map)
334 {
335         return add_mapping_entry(map, TDB_REPLACE) ?
336                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
337 }
338
339 NTSTATUS pdb_default_delete_group_mapping_entry(struct pdb_methods *methods,
340                                                    DOM_SID sid)
341 {
342         return group_map_remove(&sid) ?
343                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
344 }
345
346 NTSTATUS pdb_default_enum_group_mapping(struct pdb_methods *methods,
347                                            const DOM_SID *sid, enum lsa_SidType sid_name_use,
348                                            GROUP_MAP **pp_rmap, size_t *p_num_entries,
349                                            BOOL unix_only)
350 {
351         return enum_group_mapping(sid, sid_name_use, pp_rmap, p_num_entries, unix_only) ?
352                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
353 }
354
355 NTSTATUS pdb_default_create_alias(struct pdb_methods *methods,
356                                   const char *name, uint32 *rid)
357 {
358         DOM_SID sid;
359         enum lsa_SidType type;
360         uint32 new_rid;
361         gid_t gid;
362         BOOL exists;
363         GROUP_MAP map;
364         TALLOC_CTX *mem_ctx;
365         NTSTATUS status;
366
367         DEBUG(10, ("Trying to create alias %s\n", name));
368
369         mem_ctx = talloc_new(NULL);
370         if (mem_ctx == NULL) {
371                 return NT_STATUS_NO_MEMORY;
372         }
373
374         exists = lookup_name(mem_ctx, name, LOOKUP_NAME_ISOLATED,
375                              NULL, NULL, &sid, &type);
376         TALLOC_FREE(mem_ctx);
377
378         if (exists) {
379                 return NT_STATUS_ALIAS_EXISTS;
380         }
381
382         if (!winbind_allocate_gid(&gid)) {
383                 DEBUG(3, ("Could not get a gid out of winbind\n"));
384                 return NT_STATUS_ACCESS_DENIED;
385         }
386
387         if (!pdb_new_rid(&new_rid)) {
388                 DEBUG(0, ("Could not allocate a RID -- wasted a gid :-(\n"));
389                 return NT_STATUS_ACCESS_DENIED;
390         }
391
392         DEBUG(10, ("Creating alias %s with gid %d and rid %d\n",
393                    name, gid, new_rid));
394
395         sid_copy(&sid, get_global_sam_sid());
396         sid_append_rid(&sid, new_rid);
397
398         map.gid = gid;
399         sid_copy(&map.sid, &sid);
400         map.sid_name_use = SID_NAME_ALIAS;
401         fstrcpy(map.nt_name, name);
402         fstrcpy(map.comment, "");
403
404         status = pdb_add_group_mapping_entry(&map);
405
406         if (!NT_STATUS_IS_OK(status)) {
407                 DEBUG(0, ("Could not add group mapping entry for alias %s "
408                           "(%s)\n", name, nt_errstr(status)));
409                 return status;
410         }
411
412         *rid = new_rid;
413
414         return NT_STATUS_OK;
415 }
416
417 NTSTATUS pdb_default_delete_alias(struct pdb_methods *methods,
418                                   const DOM_SID *sid)
419 {
420         return pdb_delete_group_mapping_entry(*sid);
421 }
422
423 NTSTATUS pdb_default_get_aliasinfo(struct pdb_methods *methods,
424                                    const DOM_SID *sid,
425                                    struct acct_info *info)
426 {
427         GROUP_MAP map;
428
429         if (!pdb_getgrsid(&map, *sid))
430                 return NT_STATUS_NO_SUCH_ALIAS;
431
432         if ((map.sid_name_use != SID_NAME_ALIAS) &&
433             (map.sid_name_use != SID_NAME_WKN_GRP)) {
434                 DEBUG(2, ("%s is a %s, expected an alias\n",
435                           sid_string_static(sid),
436                           sid_type_lookup(map.sid_name_use)));
437                 return NT_STATUS_NO_SUCH_ALIAS;
438         }
439
440         fstrcpy(info->acct_name, map.nt_name);
441         fstrcpy(info->acct_desc, map.comment);
442         sid_peek_rid(&map.sid, &info->rid);
443         return NT_STATUS_OK;
444 }
445
446 NTSTATUS pdb_default_set_aliasinfo(struct pdb_methods *methods,
447                                    const DOM_SID *sid,
448                                    struct acct_info *info)
449 {
450         GROUP_MAP map;
451
452         if (!pdb_getgrsid(&map, *sid))
453                 return NT_STATUS_NO_SUCH_ALIAS;
454
455         fstrcpy(map.nt_name, info->acct_name);
456         fstrcpy(map.comment, info->acct_desc);
457
458         return pdb_update_group_mapping_entry(&map);
459 }
460
461 NTSTATUS pdb_default_add_aliasmem(struct pdb_methods *methods,
462                                   const DOM_SID *alias, const DOM_SID *member)
463 {
464         return add_aliasmem(alias, member);
465 }
466
467 NTSTATUS pdb_default_del_aliasmem(struct pdb_methods *methods,
468                                   const DOM_SID *alias, const DOM_SID *member)
469 {
470         return del_aliasmem(alias, member);
471 }
472
473 NTSTATUS pdb_default_enum_aliasmem(struct pdb_methods *methods,
474                                    const DOM_SID *alias, DOM_SID **pp_members,
475                                    size_t *p_num_members)
476 {
477         return enum_aliasmem(alias, pp_members, p_num_members);
478 }
479
480 NTSTATUS pdb_default_alias_memberships(struct pdb_methods *methods,
481                                        TALLOC_CTX *mem_ctx,
482                                        const DOM_SID *domain_sid,
483                                        const DOM_SID *members,
484                                        size_t num_members,
485                                        uint32 **pp_alias_rids,
486                                        size_t *p_num_alias_rids)
487 {
488         DOM_SID *alias_sids;
489         size_t i, num_alias_sids;
490         NTSTATUS result;
491
492         alias_sids = NULL;
493         num_alias_sids = 0;
494
495         result = alias_memberships(members, num_members,
496                                    &alias_sids, &num_alias_sids);
497
498         if (!NT_STATUS_IS_OK(result))
499                 return result;
500
501         *p_num_alias_rids = 0;
502
503         if (num_alias_sids == 0) {
504                 TALLOC_FREE(alias_sids);
505                 return NT_STATUS_OK;
506         }
507
508         *pp_alias_rids = TALLOC_ARRAY(mem_ctx, uint32, num_alias_sids);
509         if (*pp_alias_rids == NULL)
510                 return NT_STATUS_NO_MEMORY;
511
512         for (i=0; i<num_alias_sids; i++) {
513                 if (!sid_peek_check_rid(domain_sid, &alias_sids[i],
514                                         &(*pp_alias_rids)[*p_num_alias_rids]))
515                         continue;
516                 *p_num_alias_rids += 1;
517         }
518
519         TALLOC_FREE(alias_sids);
520
521         return NT_STATUS_OK;
522 }
523
524 /**********************************************************************
525  no ops for passdb backends that don't implement group mapping
526  *********************************************************************/
527
528 NTSTATUS pdb_nop_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
529                                  DOM_SID sid)
530 {
531         return NT_STATUS_UNSUCCESSFUL;
532 }
533
534 NTSTATUS pdb_nop_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
535                                  gid_t gid)
536 {
537         return NT_STATUS_UNSUCCESSFUL;
538 }
539
540 NTSTATUS pdb_nop_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
541                                  const char *name)
542 {
543         return NT_STATUS_UNSUCCESSFUL;
544 }
545
546 NTSTATUS pdb_nop_add_group_mapping_entry(struct pdb_methods *methods,
547                                                 GROUP_MAP *map)
548 {
549         return NT_STATUS_UNSUCCESSFUL;
550 }
551
552 NTSTATUS pdb_nop_update_group_mapping_entry(struct pdb_methods *methods,
553                                                    GROUP_MAP *map)
554 {
555         return NT_STATUS_UNSUCCESSFUL;
556 }
557
558 NTSTATUS pdb_nop_delete_group_mapping_entry(struct pdb_methods *methods,
559                                                    DOM_SID sid)
560 {
561         return NT_STATUS_UNSUCCESSFUL;
562 }
563
564 NTSTATUS pdb_nop_enum_group_mapping(struct pdb_methods *methods,
565                                            enum lsa_SidType sid_name_use,
566                                            GROUP_MAP **rmap, size_t *num_entries,
567                                            BOOL unix_only)
568 {
569         return NT_STATUS_UNSUCCESSFUL;
570 }
571
572 /****************************************************************************
573  These need to be redirected through pdb_interface.c
574 ****************************************************************************/
575 BOOL pdb_get_dom_grp_info(const DOM_SID *sid, struct acct_info *info)
576 {
577         GROUP_MAP map;
578         BOOL res;
579
580         become_root();
581         res = get_domain_group_from_sid(*sid, &map);
582         unbecome_root();
583
584         if (!res)
585                 return False;
586
587         fstrcpy(info->acct_name, map.nt_name);
588         fstrcpy(info->acct_desc, map.comment);
589         sid_peek_rid(sid, &info->rid);
590         return True;
591 }
592
593 BOOL pdb_set_dom_grp_info(const DOM_SID *sid, const struct acct_info *info)
594 {
595         GROUP_MAP map;
596
597         if (!get_domain_group_from_sid(*sid, &map))
598                 return False;
599
600         fstrcpy(map.nt_name, info->acct_name);
601         fstrcpy(map.comment, info->acct_desc);
602
603         return NT_STATUS_IS_OK(pdb_update_group_mapping_entry(&map));
604 }
605
606 /********************************************************************
607  Really just intended to be called by smbd
608 ********************************************************************/
609
610 NTSTATUS pdb_create_builtin_alias(uint32 rid)
611 {
612         DOM_SID sid;
613         enum lsa_SidType type;
614         gid_t gid;
615         GROUP_MAP map;
616         TALLOC_CTX *mem_ctx;
617         NTSTATUS status;
618         const char *name = NULL;
619         fstring groupname;
620
621         DEBUG(10, ("Trying to create builtin alias %d\n", rid));
622         
623         if ( !sid_compose( &sid, &global_sid_Builtin, rid ) ) {
624                 return NT_STATUS_NO_SUCH_ALIAS;
625         }
626         
627         if ( (mem_ctx = talloc_new(NULL)) == NULL ) {
628                 return NT_STATUS_NO_MEMORY;
629         }
630         
631         if ( !lookup_sid(mem_ctx, &sid, NULL, &name, &type) ) {
632                 TALLOC_FREE( mem_ctx );
633                 return NT_STATUS_NO_SUCH_ALIAS;
634         }
635         
636         /* validate RID so copy the name and move on */
637                 
638         fstrcpy( groupname, name );
639         TALLOC_FREE( mem_ctx );
640
641         if (!winbind_allocate_gid(&gid)) {
642                 DEBUG(3, ("pdb_create_builtin_alias: Could not get a gid out of winbind\n"));
643                 return NT_STATUS_ACCESS_DENIED;
644         }
645
646         DEBUG(10,("Creating alias %s with gid %d\n", name, gid));
647
648         map.gid = gid;
649         sid_copy(&map.sid, &sid);
650         map.sid_name_use = SID_NAME_ALIAS;
651         fstrcpy(map.nt_name, name);
652         fstrcpy(map.comment, "");
653
654         status = pdb_add_group_mapping_entry(&map);
655
656         if (!NT_STATUS_IS_OK(status)) {
657                 DEBUG(0, ("pdb_create_builtin_alias: Could not add group mapping entry for alias %d "
658                           "(%s)\n", rid, nt_errstr(status)));
659         }
660
661         return status;
662 }
663
664