first pass at updating head branch to be to be the same as the SAMBA_2_0 branch
[nivanova/samba-autobuild/.git] / source3 / rpc_server / srv_lookup.c
1
2 /* 
3  *  Unix SMB/Netbios implementation.
4  *  Version 1.9.
5  *  RPC Pipe client / server routines
6  *  Copyright (C) Andrew Tridgell              1992-1998
7  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
8  *  Copyright (C) Paul Ashton                  1997-1998.
9  *  
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *  
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *  
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25 /*
26  *
27  *
28
29  this module provides nt user / nt rid lookup functions.
30  users, local groups, domain groups.
31
32  no unix / samba functions should be called in this module:
33  it should purely provide a gateway to the password database API,
34  the local group database API or the domain group database API,
35  but first checking built-in rids.
36
37  did i say rids?  oops, what about "S-1-1" the "Everyone" group
38  and other such well-known sids...
39
40  speed is not of the essence: no particular optimisation is in place.
41
42  *
43  *
44  */
45
46 #include "includes.h"
47 #include "nterr.h"
48
49 extern int DEBUGLEVEL;
50
51 extern fstring global_sam_name;
52 extern DOM_SID global_sam_sid;
53 extern DOM_SID global_sid_S_1_5_20;
54
55 /*
56  * A list of the rids of well known BUILTIN and Domain users
57  * and groups.
58  */
59
60 rid_name builtin_alias_rids[] =
61 {  
62     { BUILTIN_ALIAS_RID_ADMINS       , "Administrators" },
63     { BUILTIN_ALIAS_RID_USERS        , "Users" },
64     { BUILTIN_ALIAS_RID_GUESTS       , "Guests" },
65     { BUILTIN_ALIAS_RID_POWER_USERS  , "Power Users" },
66    
67     { BUILTIN_ALIAS_RID_ACCOUNT_OPS  , "Account Operators" },
68     { BUILTIN_ALIAS_RID_SYSTEM_OPS   , "System Operators" },
69     { BUILTIN_ALIAS_RID_PRINT_OPS    , "Print Operators" },
70     { BUILTIN_ALIAS_RID_BACKUP_OPS   , "Backup Operators" },
71     { BUILTIN_ALIAS_RID_REPLICATOR   , "Replicator" },
72     { 0                             , NULL }
73 };
74
75 /* array lookup of well-known Domain RID users. */
76 rid_name domain_user_rids[] =
77 {  
78     { DOMAIN_USER_RID_ADMIN         , "Administrator" },
79     { DOMAIN_USER_RID_GUEST         , "Guest" },
80     { 0                             , NULL }
81 };
82
83 /* array lookup of well-known Domain RID groups. */
84 rid_name domain_group_rids[] =
85 {  
86     { DOMAIN_GROUP_RID_ADMINS       , "Domain Admins" },
87     { DOMAIN_GROUP_RID_USERS        , "Domain Users" },
88     { DOMAIN_GROUP_RID_GUESTS       , "Domain Guests" },
89     { 0                             , NULL }
90 };
91
92
93 int make_dom_gids(DOMAIN_GRP *mem, int num_members, DOM_GID **ppgids)
94 {
95         int count;
96         int i;
97         DOM_GID *gids = NULL;
98
99         *ppgids = NULL;
100
101         DEBUG(4,("make_dom_gids: %d\n", num_members));
102
103         if (mem == NULL || num_members == 0)
104         {
105                 return 0;
106         }
107
108         for (i = 0, count = 0; i < num_members && count < LSA_MAX_GROUPS; i++) 
109         {
110                 uint32 status;
111
112                 uint32 rid;
113                 uint8  type;
114
115                 uint8  attr  = mem[count].attr;
116                 char   *name = mem[count].name;
117
118                 become_root(True);
119                 status = lookup_grp_rid(name, &rid, &type);
120                 unbecome_root(True);
121
122                 if (status == 0x0)
123                 {
124                         gids = (DOM_GID *)Realloc( gids, sizeof(DOM_GID) * (count+1) );
125
126                         if (gids == NULL)
127                         {
128                                 DEBUG(0,("make_dom_gids: Realloc fail !\n"));
129                                 return 0;
130                         }
131
132                         gids[count].g_rid = rid;
133                         gids[count].attr  = attr;
134
135                         DEBUG(5,("group name: %s rid: %d attr: %d\n",
136                                   name, rid, attr));
137                         count++;
138                 }
139                 else
140                 {
141                         DEBUG(1,("make_dom_gids: unknown group name %s\n", name));
142                 }
143         }
144
145         *ppgids = gids;
146         return count;
147 }
148
149 /*******************************************************************
150  gets a domain user's groups
151  ********************************************************************/
152 int get_domain_user_groups(DOMAIN_GRP_MEMBER **grp_members, uint32 group_rid)
153 {
154         DOMAIN_GRP *grp;
155         int num_mem;
156
157         if (grp_members == NULL) return 0;
158
159         grp = getgrouprid(group_rid, grp_members, &num_mem);
160
161         if (grp == NULL)
162         {
163                 return 0;
164         }
165
166         return num_mem;
167 }
168
169
170 /*******************************************************************
171  lookup_builtin_names
172  ********************************************************************/
173 uint32 lookup_builtin_names(uint32 rid, char *name, uint8 *type)
174 {
175         uint32 status = 0xC0000000 | NT_STATUS_NONE_MAPPED;
176
177         status = (status != 0x0) ? lookup_wk_user_name (rid, name, type) : status;
178         status = (status != 0x0) ? lookup_wk_group_name(rid, name, type) : status;
179         status = (status != 0x0) ? lookup_wk_alias_name(rid, name, type) : status;
180
181         return status;
182 }
183
184
185 /*******************************************************************
186  lookup_added_name - names that have been added to the SAM database by admins.
187  ********************************************************************/
188 uint32 lookup_added_name(uint32 rid, char *name, uint8 *type)
189 {
190         uint32 status = 0xC0000000 | NT_STATUS_NONE_MAPPED;
191
192         status = (status != 0x0) ? lookup_user_name (rid, name, type) : status;
193         status = (status != 0x0) ? lookup_group_name(rid, name, type) : status;
194         status = (status != 0x0) ? lookup_alias_name(rid, name, type) : status;
195
196         return status;
197 }
198
199
200 /*******************************************************************
201  lookup_name
202  ********************************************************************/
203 uint32 lookup_name(uint32 rid, char *name, uint8 *type)
204 {
205         uint32 status = 0xC0000000 | NT_STATUS_NONE_MAPPED;
206
207         status = (status != 0x0) ? lookup_builtin_names(rid, name, type) : status;
208         status = (status != 0x0) ? lookup_added_name   (rid, name, type) : status;
209
210         return status;
211 }
212
213
214 /*******************************************************************
215  lookup_wk_group_name
216  ********************************************************************/
217 uint32 lookup_wk_group_name(uint32 rid, char *group_name, uint8 *type)
218 {
219         int i = 0; 
220         (*type) = SID_NAME_WKN_GRP;
221
222         DEBUG(5,("lookup_wk_group_name: rid: %d", rid));
223
224         while (domain_group_rids[i].rid != rid && domain_group_rids[i].rid != 0)
225         {
226                 i++;
227         }
228
229         if (domain_group_rids[i].rid != 0)
230         {
231                 fstrcpy(group_name, domain_group_rids[i].name);
232                 DEBUG(5,(" = %s\n", group_name));
233                 return 0x0;
234         }
235
236         DEBUG(5,(" none mapped\n"));
237         return 0xC0000000 | NT_STATUS_NONE_MAPPED;
238 }
239
240 /*******************************************************************
241  lookup_group_name
242  ********************************************************************/
243 uint32 lookup_group_name(uint32 rid, char *group_name, uint8 *type)
244 {
245         uint32 status = 0xC0000000 | NT_STATUS_NONE_MAPPED;
246         DOM_SID sid;
247
248         DEBUG(5,("lookup_group_name: rid: 0x%x", rid));
249
250         sid_copy      (&sid, &global_sam_sid);
251         sid_append_rid(&sid, rid);
252
253         (*type) = SID_NAME_DOM_GRP;
254
255         if (map_group_sid_to_name(&sid, group_name, NULL))
256         {
257                 status = 0x0;
258         }
259
260         if (status == 0x0)
261         {
262                 DEBUG(5,(" = %s\n", group_name));
263         }
264         else
265         {
266                 DEBUG(5,(" none mapped\n"));
267         }
268
269         return status;
270 }
271
272 /*******************************************************************
273  lookup_wk_alias_name
274  ********************************************************************/
275 uint32 lookup_wk_alias_name(uint32 rid, char *alias_name, uint8 *type)
276 {
277         int i = 0; 
278         (*type) = SID_NAME_ALIAS;
279
280         DEBUG(5,("lookup_wk_alias_name: rid: %d", rid));
281
282         while (builtin_alias_rids[i].rid != rid && builtin_alias_rids[i].rid != 0)
283         {
284                 i++;
285         }
286
287         if (builtin_alias_rids[i].rid != 0)
288         {
289                 fstrcpy(alias_name, builtin_alias_rids[i].name);
290                 DEBUG(5,(" = %s\n", alias_name));
291                 return 0x0;
292         }
293
294         DEBUG(5,(" none mapped\n"));
295         return 0xC0000000 | NT_STATUS_NONE_MAPPED;
296 }
297
298 /*******************************************************************
299  lookup_alias_name
300  ********************************************************************/
301 uint32 lookup_alias_name(uint32 rid, char *alias_name, uint8 *type)
302 {
303         (*type) = SID_NAME_ALIAS;
304
305         DEBUG(2,("lookup_alias_name: rid: %d\n", rid));
306         DEBUG(2,(" NOT IMPLEMENTED\n"));
307
308         return 0xC0000000 | NT_STATUS_NONE_MAPPED;
309 }
310
311 /*******************************************************************
312  lookup well-known user name
313  ********************************************************************/
314 uint32 lookup_wk_user_name(uint32 rid, char *user_name, uint8 *type)
315 {
316         int i = 0;
317         (*type) = SID_NAME_USER;
318
319         DEBUG(5,("lookup_wk_user_name: rid: %d", rid));
320
321         /* look up the well-known domain user rids first */
322         while (domain_user_rids[i].rid != rid && domain_user_rids[i].rid != 0)
323         {
324                 i++;
325         }
326
327         if (domain_user_rids[i].rid != 0)
328         {
329                 fstrcpy(user_name, domain_user_rids[i].name);
330                 DEBUG(5,(" = %s\n", user_name));
331                 return 0x0;
332         }
333
334         DEBUG(5,(" none mapped\n"));
335         return 0xC0000000 | NT_STATUS_NONE_MAPPED;
336 }
337
338 /*******************************************************************
339  lookup user name
340  ********************************************************************/
341 uint32 lookup_user_name(uint32 rid, char *user_name, uint8 *type)
342 {
343         struct sam_disp_info *disp_info;
344         (*type) = SID_NAME_USER;
345
346         DEBUG(5,("lookup_user_name: rid: %d", rid));
347
348         /* find the user account */
349         become_root(True);
350         disp_info = getsamdisprid(rid);
351         unbecome_root(True);
352
353         if (disp_info != NULL)
354         {
355                 fstrcpy(user_name, disp_info->smb_name);
356                 DEBUG(5,(" = %s\n", user_name));
357                 return 0x0;
358         }
359
360         DEBUG(5,(" none mapped\n"));
361         return 0xC0000000 | NT_STATUS_NONE_MAPPED;
362 }
363
364 /*******************************************************************
365  lookup_group_rid
366  ********************************************************************/
367 uint32 lookup_group_rid(char *group_name, uint32 *rid, uint8 *type)
368 {
369         DOM_SID sid;
370
371         (*rid) = 0;
372         (*type) = SID_NAME_DOM_GRP;
373
374         DEBUG(5,("lookup_group_rid: name: %s", group_name));
375
376         if (map_group_name_to_sid(group_name, &sid) &&
377             sid_split_rid(&sid, rid) &&
378             sid_equal(&sid, &global_sam_sid))
379         {
380                 DEBUG(5,(" = 0x%x\n", (*rid)));
381                 return 0x0;
382         }
383
384         DEBUG(5,(" none mapped\n"));
385         return 0xC0000000 | NT_STATUS_NONE_MAPPED;
386 }
387
388 /*******************************************************************
389  lookup_wk_group_rid
390  ********************************************************************/
391 uint32 lookup_wk_group_rid(char *group_name, uint32 *rid, uint8 *type)
392 {
393         char *grp_name;
394         int i = -1; /* start do loop at -1 */
395         (*rid) = 0;
396         (*type) = SID_NAME_WKN_GRP;
397
398         do /* find, if it exists, a group rid for the group name */
399         {
400                 i++;
401                 (*rid) = domain_group_rids[i].rid;
402                 grp_name = domain_group_rids[i].name;
403
404         } while (grp_name != NULL && !strequal(grp_name, group_name));
405
406         return (grp_name != NULL) ? 0 : 0xC0000000 | NT_STATUS_NONE_MAPPED;
407 }
408
409 /*******************************************************************
410  lookup_alias_sid
411  ********************************************************************/
412 uint32 lookup_alias_sid(char *alias_name, DOM_SID *sid, uint8 *type)
413 {
414         (*type) = SID_NAME_ALIAS;
415
416         DEBUG(5,("lookup_alias_rid: name: %s", alias_name));
417
418         if (map_alias_name_to_sid(alias_name, sid))
419         {
420                 fstring sid_str;
421                 sid_to_string(sid_str, sid);
422                 DEBUG(5,(" = %s\n", sid_str));
423                 return 0x0;
424         }
425
426         DEBUG(5,(" none mapped\n"));
427         return 0xC0000000 | NT_STATUS_NONE_MAPPED;
428 }
429
430 /*******************************************************************
431  lookup_alias_rid
432  ********************************************************************/
433 uint32 lookup_alias_rid(char *alias_name, uint32 *rid, uint8 *type)
434 {
435         DOM_SID sid;
436
437         (*rid) = 0;
438         (*type) = SID_NAME_ALIAS;
439
440         DEBUG(5,("lookup_alias_rid: name: %s", alias_name));
441
442         if (map_alias_name_to_sid(alias_name, &sid) &&
443             sid_split_rid(&sid, rid) &&
444             sid_equal(&sid, &global_sam_sid))
445         {
446                 DEBUG(5,(" = 0x%x\n", (*rid)));
447                 return 0x0;
448         }
449
450         DEBUG(5,(" none mapped\n"));
451         return 0xC0000000 | NT_STATUS_NONE_MAPPED;
452 }
453
454 /*******************************************************************
455  lookup_wk_alias_sid
456  ********************************************************************/
457 uint32 lookup_wk_alias_sid(char *alias_name, DOM_SID *sid, uint8 *type)
458 {
459         char *als_name;
460         int i = 0;
461         uint32 rid;
462         (*type) = SID_NAME_ALIAS;
463
464         do /* find, if it exists, a alias rid for the alias name*/
465         {
466                 rid      = builtin_alias_rids[i].rid;
467                 als_name = builtin_alias_rids[i].name;
468
469                 i++;
470
471                 if (strequal(als_name, alias_name))
472                 {
473                         sid_copy(sid, &global_sid_S_1_5_20);
474                         sid_append_rid(sid, rid);
475
476                         return 0x0;
477                 }
478                         
479         } while (als_name != NULL);
480
481         return 0xC0000000 | NT_STATUS_NONE_MAPPED;
482 }
483
484 /*******************************************************************
485  lookup_wk_alias_rid
486  ********************************************************************/
487 uint32 lookup_wk_alias_rid(char *alias_name, uint32 *rid, uint8 *type)
488 {
489         char *als_name;
490         int i = -1; /* start do loop at -1 */
491         (*rid) = 0;
492         (*type) = SID_NAME_ALIAS;
493
494         do /* find, if it exists, a alias rid for the alias name*/
495         {
496                 i++;
497                 (*rid) = builtin_alias_rids[i].rid;
498                 als_name = builtin_alias_rids[i].name;
499
500         } while (als_name != NULL && !strequal(als_name, alias_name));
501
502         return (als_name != NULL) ? 0 : 0xC0000000 | NT_STATUS_NONE_MAPPED;
503 }
504
505 /*******************************************************************
506  lookup_sid
507  ********************************************************************/
508 uint32 lookup_sid(char *name, DOM_SID *sid, uint8 *type)
509 {
510         uint32 status = 0xC0000000 | NT_STATUS_NONE_MAPPED;
511         fstring domain;
512         fstring user;
513         
514         split_domain_name(name, domain, user);
515
516         if (!strequal(domain, global_sam_name))
517         {
518                 DEBUG(0,("lookup_sid: remote domain %s not supported\n", domain));
519                 return status;
520         }
521
522         status = (status != 0x0) ? lookup_wk_alias_sid(user, sid, type) : status;
523         status = (status != 0x0) ? lookup_alias_sid   (user, sid, type) : status;
524 #if 0
525         status = (status != 0x0) ? lookup_domain_sid  (user, sid, type) : status;
526 #endif
527
528         return status;
529 }
530
531 /*******************************************************************
532  lookup_added_user_rid
533  ********************************************************************/
534 uint32 lookup_added_user_rids(char *user_name,
535                 uint32 *usr_rid, uint32 *grp_rid)
536 {
537         struct sam_passwd *sam_pass;
538         (*usr_rid) = 0;
539         (*grp_rid) = 0;
540
541         /* find the user account */
542         become_root(True);
543         sam_pass = getsam21pwnam(user_name);
544         unbecome_root(True);
545
546         if (sam_pass != NULL)
547         {
548                 (*usr_rid) = sam_pass->user_rid ;
549                 (*grp_rid) = sam_pass->group_rid;
550                 return 0x0;
551         }
552
553         return 0xC0000000 | NT_STATUS_NONE_MAPPED;
554 }
555
556 /*******************************************************************
557  lookup_added_user_rid
558  ********************************************************************/
559 uint32 lookup_added_user_rid(char *user_name, uint32 *rid, uint8 *type)
560 {
561         struct sam_passwd *sam_pass;
562         (*rid) = 0;
563         (*type) = SID_NAME_USER;
564
565         /* find the user account */
566         become_root(True);
567         sam_pass = getsam21pwnam(user_name);
568         unbecome_root(True);
569
570         if (sam_pass != NULL)
571         {
572                 (*rid) = sam_pass->user_rid;
573                 return 0x0;
574         }
575
576         return 0xC0000000 | NT_STATUS_NONE_MAPPED;
577 }
578
579 /*******************************************************************
580  lookup_wk_user_rid
581  ********************************************************************/
582 uint32 lookup_wk_user_rid(char *user_name, uint32 *rid, uint8 *type)
583 {
584         char *usr_name;
585         int i = -1; /* start do loop at -1 */
586         (*rid) = 0;
587         (*type) = SID_NAME_USER;
588
589         do /* find, if it exists, a alias rid for the alias name*/
590         {
591                 i++;
592                 (*rid) = domain_user_rids[i].rid;
593                 usr_name = domain_user_rids[i].name;
594
595         } while (usr_name != NULL && !strequal(usr_name, user_name));
596
597         return (usr_name != NULL) ? 0 : 0xC0000000 | NT_STATUS_NONE_MAPPED;
598 }
599
600 /*******************************************************************
601  lookup_added_grp_rid
602  ********************************************************************/
603 uint32 lookup_added_grp_rid(char *name, uint32 *rid, uint8 *type)
604 {
605         uint32 status = 0xC0000000 | NT_STATUS_NONE_MAPPED;
606
607         status = (status != 0x0) ? lookup_group_rid(name, rid, type) : status;
608         status = (status != 0x0) ? lookup_alias_rid(name, rid, type) : status;
609
610         return status;
611 }
612
613 /*******************************************************************
614  lookup_builtin_grp_rid
615  ********************************************************************/
616 uint32 lookup_builtin_grp_rid(char *name, uint32 *rid, uint8 *type)
617 {
618         uint32 status = 0xC0000000 | NT_STATUS_NONE_MAPPED;
619
620         status = (status != 0x0) ? lookup_wk_group_rid(name, rid, type) : status;
621         status = (status != 0x0) ? lookup_wk_alias_rid(name, rid, type) : status;
622
623         return status;
624 }
625
626 /*******************************************************************
627  lookup_grp_rid
628  ********************************************************************/
629 uint32 lookup_grp_rid(char *name, uint32 *rid, uint8 *type)
630 {
631         uint32 status = 0xC0000000 | NT_STATUS_NONE_MAPPED;
632
633         status = (status != 0x0) ? lookup_builtin_grp_rid(name, rid, type) : status;
634         status = (status != 0x0) ? lookup_added_grp_rid  (name, rid, type) : status;
635
636         return status;
637 }
638
639 /*******************************************************************
640  lookup_user_rid
641  ********************************************************************/
642 uint32 lookup_user_rid(char *name, uint32 *rid, uint8 *type)
643 {
644         uint32 status = 0xC0000000 | NT_STATUS_NONE_MAPPED;
645
646         status = (status != 0x0) ? lookup_wk_user_rid   (name, rid, type) : status;
647         status = (status != 0x0) ? lookup_added_user_rid(name, rid, type) : status;
648
649         return status;
650 }
651
652 /*******************************************************************
653  lookup_rid
654  ********************************************************************/
655 uint32 lookup_rid(char *name, uint32 *rid, uint8 *type)
656 {
657         uint32 status = 0xC0000000 | NT_STATUS_NONE_MAPPED;
658
659         status = (status != 0x0) ? lookup_user_rid(name, rid, type) : status;
660         status = (status != 0x0) ? lookup_grp_rid (name, rid, type) : status;
661
662         return status;
663 }
664
665 /*******************************************************************
666  lookup_user_rids
667  ********************************************************************/
668 uint32 lookup_user_rids(char *name, uint32 *usr_rid, uint32 *grp_rid)
669 {
670         uint32 status = 0xC0000000 | NT_STATUS_NONE_MAPPED;
671         uint8 type;
672
673         /*
674          * try an ordinary user lookup
675          */
676
677         status = lookup_added_user_rids(name, usr_rid, grp_rid);
678         if (status == 0)
679         {
680                 return status;
681         }
682
683         /*
684          * hm.  must be a well-known user, in a well-known group.
685          */
686
687         status = lookup_wk_user_rid(name, usr_rid, &type);
688         if (status != 0 || type != SID_NAME_USER)
689         {
690                 return status; /* ok, maybe not! */
691         }
692         if (type != SID_NAME_USER)
693         {
694                 return 0xC0000000 | NT_STATUS_NONE_MAPPED; /* users only... */
695         }
696
697         /*
698          * ok, got the user rid: now try the group rid
699          */
700
701         status = lookup_builtin_grp_rid(name, grp_rid, &type);
702         if (type == SID_NAME_DOM_GRP ||
703             type == SID_NAME_ALIAS ||
704             type == SID_NAME_WKN_GRP)
705         {
706                 status = 0xC0000000 | NT_STATUS_NONE_MAPPED;
707         }
708
709         return status;
710 }