Removed version number from file header.
[sharpe/samba-autobuild/.git] / source3 / rpc_server / srv_lsa_nt.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-1997,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
6  *  Copyright (C) Paul Ashton                       1997.
7  *  Copyright (C) Jeremy Allison                    2001.
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 /* This is the implementation of the lsa server code. */
25
26 #include "includes.h"
27
28 extern DOM_SID global_sam_sid;
29 extern fstring global_myworkgroup;
30 extern pstring global_myname;
31 extern PRIVS privs[];
32
33 struct lsa_info {
34     DOM_SID sid;
35     uint32 access;
36 };
37
38 struct generic_mapping lsa_generic_mapping = {
39         POLICY_READ,
40         POLICY_WRITE,
41         POLICY_EXECUTE,
42         POLICY_ALL_ACCESS
43 };
44
45 /*******************************************************************
46  Function to free the per handle data.
47  ********************************************************************/
48
49 static void free_lsa_info(void *ptr)
50 {
51         struct lsa_info *lsa = (struct lsa_info *)ptr;
52
53         SAFE_FREE(lsa);
54 }
55
56 /***************************************************************************
57 Init dom_query
58  ***************************************************************************/
59
60 static void init_dom_query(DOM_QUERY *d_q, char *dom_name, DOM_SID *dom_sid)
61 {
62         int domlen = (dom_name != NULL) ? strlen(dom_name) : 0;
63
64         /*
65          * I'm not sure why this really odd combination of length
66          * values works, but it does appear to. I need to look at
67          * this *much* more closely - but at the moment leave alone
68          * until it's understood. This allows a W2k client to join
69          * a domain with both odd and even length names... JRA.
70          */
71
72         d_q->uni_dom_str_len = domlen ? ((domlen + 1) * 2) : 0;
73         d_q->uni_dom_max_len = domlen * 2;
74         d_q->buffer_dom_name = domlen != 0 ? 1 : 0; /* domain buffer pointer */
75         d_q->buffer_dom_sid = dom_sid != NULL ? 1 : 0;  /* domain sid pointer */
76
77         /* this string is supposed to be character short */
78         init_unistr2(&d_q->uni_domain_name, dom_name, domlen);
79         d_q->uni_domain_name.uni_max_len++;
80
81         if (dom_sid != NULL)
82                 init_dom_sid2(&d_q->dom_sid, dom_sid);
83 }
84
85 /***************************************************************************
86  init_dom_ref - adds a domain if it's not already in, returns the index.
87 ***************************************************************************/
88
89 static int init_dom_ref(DOM_R_REF *ref, char *dom_name, DOM_SID *dom_sid)
90 {
91         int num = 0;
92         int len;
93
94         if (dom_name != NULL) {
95                 for (num = 0; num < ref->num_ref_doms_1; num++) {
96                         fstring domname;
97                         rpcstr_pull(domname, &ref->ref_dom[num].uni_dom_name, sizeof(domname), -1, 0);
98                         if (strequal(domname, dom_name))
99                                 return num;
100                 }
101         } else {
102                 num = ref->num_ref_doms_1;
103         }
104
105         if (num >= MAX_REF_DOMAINS) {
106                 /* index not found, already at maximum domain limit */
107                 return -1;
108         }
109
110         ref->num_ref_doms_1 = num+1;
111         ref->ptr_ref_dom  = 1;
112         ref->max_entries = MAX_REF_DOMAINS;
113         ref->num_ref_doms_2 = num+1;
114
115         len = (dom_name != NULL) ? strlen(dom_name) : 0;
116         if(dom_name != NULL && len == 0)
117                 len = 1;
118
119         init_uni_hdr(&ref->hdr_ref_dom[num].hdr_dom_name, len);
120         ref->hdr_ref_dom[num].ptr_dom_sid = dom_sid != NULL ? 1 : 0;
121
122         init_unistr2(&ref->ref_dom[num].uni_dom_name, dom_name, len);
123         init_dom_sid2(&ref->ref_dom[num].ref_dom, dom_sid );
124
125         return num;
126 }
127
128 /***************************************************************************
129  init_lsa_rid2s
130  ***************************************************************************/
131
132 static void init_lsa_rid2s(DOM_R_REF *ref, DOM_RID2 *rid2,
133                                 int num_entries, UNISTR2 *name,
134                                 uint32 *mapped_count, BOOL endian)
135 {
136         int i;
137         int total = 0;
138         *mapped_count = 0;
139
140         SMB_ASSERT(num_entries <= MAX_LOOKUP_SIDS);
141
142         become_root(); /* lookup_name can require root privs */
143
144         for (i = 0; i < num_entries; i++) {
145                 BOOL status = False;
146                 DOM_SID sid;
147                 uint32 rid = 0xffffffff;
148                 int dom_idx = -1;
149                 pstring full_name;
150                 fstring dom_name, user;
151                 enum SID_NAME_USE name_type = SID_NAME_UNKNOWN;
152
153                 /* Split name into domain and user component */
154
155                 unistr2_to_ascii(full_name, &name[i], sizeof(full_name));
156                 split_domain_name(full_name, dom_name, user);
157
158                 /* Lookup name */
159
160                 DEBUG(5, ("init_lsa_rid2s: looking up name %s\n", full_name));
161
162                 status = lookup_name(dom_name, user, &sid, &name_type);
163
164                 DEBUG(5, ("init_lsa_rid2s: %s\n", status ? "found" : 
165                           "not found"));
166
167                 if (status) {
168                         sid_split_rid(&sid, &rid);
169                         dom_idx = init_dom_ref(ref, dom_name, &sid);
170                         (*mapped_count)++;
171                 } else {
172                         dom_idx = -1;
173                         rid = 0xffffffff;
174                         name_type = SID_NAME_UNKNOWN;
175                 }
176
177                 init_dom_rid2(&rid2[total], rid, name_type, dom_idx);
178                 total++;
179         }
180
181         unbecome_root();
182 }
183
184 /***************************************************************************
185  init_reply_lookup_names
186  ***************************************************************************/
187
188 static void init_reply_lookup_names(LSA_R_LOOKUP_NAMES *r_l,
189                 DOM_R_REF *ref, uint32 num_entries,
190                 DOM_RID2 *rid2, uint32 mapped_count)
191 {
192         r_l->ptr_dom_ref  = 1;
193         r_l->dom_ref      = ref;
194
195         r_l->num_entries  = num_entries;
196         r_l->ptr_entries  = 1;
197         r_l->num_entries2 = num_entries;
198         r_l->dom_rid      = rid2;
199
200         r_l->mapped_count = mapped_count;
201
202         if (mapped_count == 0)
203                 r_l->status = NT_STATUS_NONE_MAPPED;
204         else
205                 r_l->status = NT_STATUS_OK;
206 }
207
208 /***************************************************************************
209  Init lsa_trans_names.
210  ***************************************************************************/
211
212 static void init_lsa_trans_names(TALLOC_CTX *ctx, DOM_R_REF *ref, LSA_TRANS_NAME_ENUM *trn,
213                                  int num_entries, DOM_SID2 *sid,
214                                  uint32 *mapped_count)
215 {
216         int i;
217         int total = 0;
218         *mapped_count = 0;
219
220         /* Allocate memory for list of names */
221
222         if (num_entries > 0) {
223                 if (!(trn->name = (LSA_TRANS_NAME *)talloc(ctx, sizeof(LSA_TRANS_NAME) *
224                                                           num_entries))) {
225                         DEBUG(0, ("init_lsa_trans_names(): out of memory\n"));
226                         return;
227                 }
228
229                 if (!(trn->uni_name = (UNISTR2 *)talloc(ctx, sizeof(UNISTR2) * 
230                                                         num_entries))) {
231                         DEBUG(0, ("init_lsa_trans_names(): out of memory\n"));
232                         return;
233                 }
234         }
235
236         for (i = 0; i < num_entries; i++) {
237                 BOOL status = False;
238                 DOM_SID find_sid = sid[i].sid;
239                 uint32 rid = 0xffffffff;
240                 int dom_idx = -1;
241                 fstring name, dom_name;
242                 enum SID_NAME_USE sid_name_use = (enum SID_NAME_USE)0;
243
244                 sid_to_string(name, &find_sid);
245                 DEBUG(5, ("init_lsa_trans_names: looking up sid %s\n", name));
246
247                 /* Lookup sid from winbindd */
248
249                 memset(dom_name, '\0', sizeof(dom_name));
250                 memset(name, '\0', sizeof(name));
251
252                 status = lookup_sid(&find_sid, dom_name, name, &sid_name_use);
253
254                 DEBUG(5, ("init_lsa_trans_names: %s\n", status ? "found" : 
255                           "not found"));
256
257                 if (!status) {
258                         sid_name_use = SID_NAME_UNKNOWN;
259                 }
260
261                 /* Store domain sid in ref array */
262
263                 if (find_sid.num_auths == 5) {
264                         sid_split_rid(&find_sid, &rid);
265                 }
266
267                 dom_idx = init_dom_ref(ref, dom_name, &find_sid);
268
269                 DEBUG(10,("init_lsa_trans_names: added user '%s\\%s' to "
270                           "referenced list.\n", dom_name, name ));
271
272                 (*mapped_count)++;
273
274                 init_lsa_trans_name(&trn->name[total], &trn->uni_name[total],
275                                         sid_name_use, name, dom_idx);
276                 total++;
277         }
278
279         trn->num_entries = total;
280         trn->ptr_trans_names = 1;
281         trn->num_entries2 = total;
282 }
283
284 /***************************************************************************
285  Init_reply_lookup_sids.
286  ***************************************************************************/
287
288 static void init_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l,
289                 DOM_R_REF *ref, LSA_TRANS_NAME_ENUM *names,
290                 uint32 mapped_count)
291 {
292         r_l->ptr_dom_ref  = 1;
293         r_l->dom_ref      = ref;
294         r_l->names        = names;
295         r_l->mapped_count = mapped_count;
296
297         if (mapped_count == 0)
298                 r_l->status = NT_STATUS_NONE_MAPPED;
299         else
300                 r_l->status = NT_STATUS_OK;
301 }
302
303 static NTSTATUS lsa_get_generic_sd(TALLOC_CTX *mem_ctx, SEC_DESC **sd, size_t *sd_size)
304 {
305         extern DOM_SID global_sid_World;
306         extern DOM_SID global_sid_Builtin;
307         DOM_SID local_adm_sid;
308         DOM_SID adm_sid;
309
310         SEC_ACE ace[3];
311         SEC_ACCESS mask;
312
313         SEC_ACL *psa = NULL;
314
315         init_sec_access(&mask, POLICY_EXECUTE);
316         init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
317
318         sid_copy(&adm_sid, &global_sam_sid);
319         sid_append_rid(&adm_sid, DOMAIN_GROUP_RID_ADMINS);
320         init_sec_access(&mask, POLICY_ALL_ACCESS);
321         init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
322
323         sid_copy(&local_adm_sid, &global_sid_Builtin);
324         sid_append_rid(&local_adm_sid, BUILTIN_ALIAS_RID_ADMINS);
325         init_sec_access(&mask, POLICY_ALL_ACCESS);
326         init_sec_ace(&ace[2], &local_adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
327
328         if((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, 3, ace)) == NULL)
329                 return NT_STATUS_NO_MEMORY;
330
331         if((*sd = make_sec_desc(mem_ctx, SEC_DESC_REVISION, &adm_sid, NULL, NULL, psa, sd_size)) == NULL)
332                 return NT_STATUS_NO_MEMORY;
333
334         return NT_STATUS_OK;
335 }
336
337 /***************************************************************************
338  _lsa_open_policy2.
339  ***************************************************************************/
340
341 NTSTATUS _lsa_open_policy2(pipes_struct *p, LSA_Q_OPEN_POL2 *q_u, LSA_R_OPEN_POL2 *r_u)
342 {
343         struct lsa_info *info;
344         SEC_DESC *psd = NULL;
345         size_t sd_size;
346         uint32 des_access=q_u->des_access;
347         uint32 acc_granted;
348         NTSTATUS status;
349
350
351         /* map the generic bits to the lsa policy ones */
352         se_map_generic(&des_access, &lsa_generic_mapping);
353
354         /* get the generic lsa policy SD until we store it */
355         lsa_get_generic_sd(p->mem_ctx, &psd, &sd_size);
356
357         if(!se_access_check(psd, p->pipe_user.nt_user_token, des_access, &acc_granted, &status))
358                 return status;
359
360         /* associate the domain SID with the (unique) handle. */
361         if ((info = (struct lsa_info *)malloc(sizeof(struct lsa_info))) == NULL)
362                 return NT_STATUS_NO_MEMORY;
363
364         ZERO_STRUCTP(info);
365         info->sid = global_sam_sid;
366         info->access = acc_granted;
367
368         /* set up the LSA QUERY INFO response */
369         if (!create_policy_hnd(p, &r_u->pol, free_lsa_info, (void *)info))
370                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
371
372         return NT_STATUS_OK;
373 }
374
375 /***************************************************************************
376  _lsa_open_policy
377  ***************************************************************************/
378
379 NTSTATUS _lsa_open_policy(pipes_struct *p, LSA_Q_OPEN_POL *q_u, LSA_R_OPEN_POL *r_u)
380 {
381         struct lsa_info *info;
382         SEC_DESC *psd = NULL;
383         size_t sd_size;
384         uint32 des_access=q_u->des_access;
385         uint32 acc_granted;
386         NTSTATUS status;
387
388
389         /* map the generic bits to the lsa policy ones */
390         se_map_generic(&des_access, &lsa_generic_mapping);
391
392         /* get the generic lsa policy SD until we store it */
393         lsa_get_generic_sd(p->mem_ctx, &psd, &sd_size);
394
395         if(!se_access_check(psd, p->pipe_user.nt_user_token, des_access, &acc_granted, &status))
396                 return status;
397
398         /* associate the domain SID with the (unique) handle. */
399         if ((info = (struct lsa_info *)malloc(sizeof(struct lsa_info))) == NULL)
400                 return NT_STATUS_NO_MEMORY;
401
402         ZERO_STRUCTP(info);
403         info->sid = global_sam_sid;
404         info->access = acc_granted;
405
406         /* set up the LSA QUERY INFO response */
407         if (!create_policy_hnd(p, &r_u->pol, free_lsa_info, (void *)info))
408                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
409
410         return NT_STATUS_OK;
411 }
412
413 /***************************************************************************
414  _lsa_enum_trust_dom - this needs fixing to do more than return NULL ! JRA.
415  ***************************************************************************/
416
417 NTSTATUS _lsa_enum_trust_dom(pipes_struct *p, LSA_Q_ENUM_TRUST_DOM *q_u, LSA_R_ENUM_TRUST_DOM *r_u)
418 {
419         struct lsa_info *info;
420         uint32 enum_context = 0;
421         char *dom_name = NULL;
422         DOM_SID *dom_sid = NULL;
423
424         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
425                 return NT_STATUS_INVALID_HANDLE;
426
427         /* check if the user have enough rights */
428         if (!(info->access & POLICY_VIEW_LOCAL_INFORMATION))
429                 return NT_STATUS_ACCESS_DENIED;
430
431         /* set up the LSA QUERY INFO response */
432         init_r_enum_trust_dom(p->mem_ctx, r_u, enum_context, dom_name, dom_sid,
433               dom_name != NULL ? NT_STATUS_OK : NT_STATUS_NO_MORE_ENTRIES);
434
435         return r_u->status;
436 }
437
438 /***************************************************************************
439  _lsa_query_info. See the POLICY_INFOMATION_CLASS docs at msdn.
440  ***************************************************************************/
441
442 NTSTATUS _lsa_query_info(pipes_struct *p, LSA_Q_QUERY_INFO *q_u, LSA_R_QUERY_INFO *r_u)
443 {
444         extern DOM_SID global_sid_nonexistent;
445         struct lsa_info *handle;
446         LSA_INFO_UNION *info = &r_u->dom;
447         DOM_SID domain_sid;
448         char *name = NULL;
449         DOM_SID *sid = NULL;
450
451         r_u->status = NT_STATUS_OK;
452
453         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
454                 return NT_STATUS_INVALID_HANDLE;
455
456         switch (q_u->info_class) {
457         case 0x02:
458                 {
459                 unsigned int i;
460                 /* check if the user have enough rights */
461                 if (!(handle->access & POLICY_VIEW_AUDIT_INFORMATION))
462                         return NT_STATUS_ACCESS_DENIED;
463
464                 /* fake info: We audit everything. ;) */
465                 info->id2.auditing_enabled = 1;
466                 info->id2.count1 = 7;
467                 info->id2.count2 = 7;
468                 if ((info->id2.auditsettings = (uint32 *)talloc(p->mem_ctx,7*sizeof(uint32))) == NULL)
469                         return NT_STATUS_NO_MEMORY;
470                 for (i = 0; i < 7; i++)
471                         info->id2.auditsettings[i] = 3;
472                 break;
473                 }
474         case 0x03:
475                 /* check if the user have enough rights */
476                 if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
477                         return NT_STATUS_ACCESS_DENIED;
478
479                 /* Request PolicyPrimaryDomainInformation. */
480                 switch (lp_server_role()) {
481                         case ROLE_DOMAIN_PDC:
482                         case ROLE_DOMAIN_BDC:
483                                 name = global_myworkgroup;
484                                 sid = &global_sam_sid;
485                                 break;
486                         case ROLE_DOMAIN_MEMBER:
487                                 name = global_myworkgroup;
488                                 /* We need to return the Domain SID here. */
489                                 if (secrets_fetch_domain_sid(global_myworkgroup,
490                                                              &domain_sid))
491                                         sid = &domain_sid;
492                                 else
493                                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
494                                 break;
495                         case ROLE_STANDALONE:
496                                 name = global_myworkgroup;
497                                 sid = &global_sid_nonexistent;
498                                 break;
499                         default:
500                                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
501                 }
502                 init_dom_query(&r_u->dom.id3, name, sid);
503                 break;
504         case 0x05:
505                 /* check if the user have enough rights */
506                 if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
507                         return NT_STATUS_ACCESS_DENIED;
508
509                 /* Request PolicyAccountDomainInformation. */
510                 switch (lp_server_role()) {
511                         case ROLE_DOMAIN_PDC:
512                         case ROLE_DOMAIN_BDC:
513                                 name = global_myworkgroup;
514                                 sid = &global_sam_sid;
515                                 break;
516                         case ROLE_DOMAIN_MEMBER:
517                                 name = global_myname;
518                                 sid = &global_sam_sid;
519                                 break;
520                         case ROLE_STANDALONE:
521                                 name = global_myname;
522                                 sid = &global_sam_sid;
523                                 break;
524                         default:
525                                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
526                 }
527                 init_dom_query(&r_u->dom.id5, name, sid);
528                 break;
529         case 0x06:
530                 /* check if the user have enough rights */
531                 if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
532                         return NT_STATUS_ACCESS_DENIED;
533
534                 switch (lp_server_role()) {
535                         case ROLE_DOMAIN_BDC:
536                                 /*
537                                  * only a BDC is a backup controller
538                                  * of the domain, it controls.
539                                  */
540                                 info->id6.server_role = 2;
541                                 break;
542                         default:
543                                 /*
544                                  * any other role is a primary
545                                  * of the domain, it controls.
546                                  */
547                                 info->id6.server_role = 3;
548                                 break; 
549                 }
550                 break;
551         default:
552                 DEBUG(0,("_lsa_query_info: unknown info level in Lsa Query: %d\n", q_u->info_class));
553                 r_u->status = NT_STATUS_INVALID_INFO_CLASS;
554                 break;
555         }
556
557         if (NT_STATUS_IS_OK(r_u->status)) {
558                 r_u->undoc_buffer = 0x22000000; /* bizarre */
559                 r_u->info_class = q_u->info_class;
560         }
561
562         return r_u->status;
563 }
564
565 /***************************************************************************
566  _lsa_lookup_sids
567  ***************************************************************************/
568
569 NTSTATUS _lsa_lookup_sids(pipes_struct *p, LSA_Q_LOOKUP_SIDS *q_u, LSA_R_LOOKUP_SIDS *r_u)
570 {
571         struct lsa_info *handle;
572         DOM_SID2 *sid = q_u->sids.sid;
573         int num_entries = q_u->sids.num_entries;
574         DOM_R_REF *ref = NULL;
575         LSA_TRANS_NAME_ENUM *names = NULL;
576         uint32 mapped_count = 0;
577
578         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
579                 return NT_STATUS_INVALID_HANDLE;
580
581         /* check if the user have enough rights */
582         if (!(handle->access & POLICY_LOOKUP_NAMES))
583                 return NT_STATUS_ACCESS_DENIED;
584
585         ref = (DOM_R_REF *)talloc_zero(p->mem_ctx, sizeof(DOM_R_REF));
586         names = (LSA_TRANS_NAME_ENUM *)talloc_zero(p->mem_ctx, sizeof(LSA_TRANS_NAME_ENUM));
587
588         if (!ref || !names)
589                 return NT_STATUS_NO_MEMORY;
590
591         /* set up the LSA Lookup SIDs response */
592         init_lsa_trans_names(p->mem_ctx, ref, names, num_entries, sid, &mapped_count);
593         init_reply_lookup_sids(r_u, ref, names, mapped_count);
594
595         return r_u->status;
596 }
597
598 /***************************************************************************
599 lsa_reply_lookup_names
600  ***************************************************************************/
601
602 NTSTATUS _lsa_lookup_names(pipes_struct *p,LSA_Q_LOOKUP_NAMES *q_u, LSA_R_LOOKUP_NAMES *r_u)
603 {
604         struct lsa_info *handle;
605         UNISTR2 *names = q_u->uni_name;
606         int num_entries = q_u->num_entries;
607         DOM_R_REF *ref;
608         DOM_RID2 *rids;
609         uint32 mapped_count = 0;
610
611         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
612                 return NT_STATUS_INVALID_HANDLE;
613
614         /* check if the user have enough rights */
615         if (!(handle->access & POLICY_LOOKUP_NAMES))
616                 return NT_STATUS_ACCESS_DENIED;
617
618         if (num_entries >  MAX_LOOKUP_SIDS) {
619                 num_entries = MAX_LOOKUP_SIDS;
620                 DEBUG(5,("_lsa_lookup_names: truncating name lookup list to %d\n", num_entries));
621         }
622                 
623         ref = (DOM_R_REF *)talloc_zero(p->mem_ctx, sizeof(DOM_R_REF));
624         rids = (DOM_RID2 *)talloc_zero(p->mem_ctx, sizeof(DOM_RID2)*num_entries);
625
626         if (!ref || !rids)
627                 return NT_STATUS_NO_MEMORY;
628
629         /* set up the LSA Lookup RIDs response */
630         init_lsa_rid2s(ref, rids, num_entries, names, &mapped_count, p->endian);
631         init_reply_lookup_names(r_u, ref, num_entries, rids, mapped_count);
632
633         return r_u->status;
634 }
635
636 /***************************************************************************
637  _lsa_close. Also weird - needs to check if lsa handle is correct. JRA.
638  ***************************************************************************/
639
640 NTSTATUS _lsa_close(pipes_struct *p, LSA_Q_CLOSE *q_u, LSA_R_CLOSE *r_u)
641 {
642         if (!find_policy_by_hnd(p, &q_u->pol, NULL))
643                 return NT_STATUS_INVALID_HANDLE;
644
645         close_policy_hnd(p, &q_u->pol);
646         return NT_STATUS_OK;
647 }
648
649 /***************************************************************************
650   "No more secrets Marty...." :-).
651  ***************************************************************************/
652
653 NTSTATUS _lsa_open_secret(pipes_struct *p, LSA_Q_OPEN_SECRET *q_u, LSA_R_OPEN_SECRET *r_u)
654 {
655         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
656 }
657
658 /***************************************************************************
659 _lsa_enum_privs.
660  ***************************************************************************/
661
662 NTSTATUS _lsa_enum_privs(pipes_struct *p, LSA_Q_ENUM_PRIVS *q_u, LSA_R_ENUM_PRIVS *r_u)
663 {
664         struct lsa_info *handle;
665         uint32 i;
666
667         uint32 enum_context=q_u->enum_context;
668         LSA_PRIV_ENTRY *entry;
669         LSA_PRIV_ENTRY *entries=NULL;
670
671         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
672                 return NT_STATUS_INVALID_HANDLE;
673
674         /* check if the user have enough rights */
675
676         /*
677          * I don't know if it's the right one. not documented.
678          */
679         if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
680                 return NT_STATUS_ACCESS_DENIED;
681
682         if (enum_context >= PRIV_ALL_INDEX)
683                 return NT_STATUS_NO_MORE_ENTRIES;
684
685         entries = (LSA_PRIV_ENTRY *)talloc_zero(p->mem_ctx, sizeof(LSA_PRIV_ENTRY) * (PRIV_ALL_INDEX));
686         if (entries==NULL)
687                 return NT_STATUS_NO_MEMORY;
688
689         entry = entries;
690         
691         DEBUG(10,("_lsa_enum_privs: enum_context:%d total entries:%d\n", enum_context, PRIV_ALL_INDEX));
692
693         for (i = 0; i < PRIV_ALL_INDEX; i++, entry++) {
694                 if( i<enum_context) {
695                         init_uni_hdr(&entry->hdr_name, 0);
696                         init_unistr2(&entry->name, NULL, 0 );
697                         entry->luid_low = 0;
698                         entry->luid_high = 0;
699                 } else {
700                         init_uni_hdr(&entry->hdr_name, strlen(privs[i+1].priv));
701                         init_unistr2(&entry->name, privs[i+1].priv, strlen(privs[i+1].priv) );
702                         entry->luid_low = privs[i+1].se_priv;
703                         entry->luid_high = 0;
704                 }
705         }
706
707         enum_context = PRIV_ALL_INDEX;
708         init_lsa_r_enum_privs(r_u, enum_context, PRIV_ALL_INDEX, entries);
709
710         return NT_STATUS_OK;
711 }
712
713 /***************************************************************************
714 _lsa_priv_get_dispname.
715  ***************************************************************************/
716
717 NTSTATUS _lsa_priv_get_dispname(pipes_struct *p, LSA_Q_PRIV_GET_DISPNAME *q_u, LSA_R_PRIV_GET_DISPNAME *r_u)
718 {
719         struct lsa_info *handle;
720         fstring name_asc;
721         int i=1;
722
723         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
724                 return NT_STATUS_INVALID_HANDLE;
725
726         /* check if the user have enough rights */
727
728         /*
729          * I don't know if it's the right one. not documented.
730          */
731         if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
732                 return NT_STATUS_ACCESS_DENIED;
733
734         unistr2_to_ascii(name_asc, &q_u->name, sizeof(name_asc));
735
736         DEBUG(10,("_lsa_priv_get_dispname: %s", name_asc));
737
738         while (privs[i].se_priv!=SE_PRIV_ALL && strcmp(name_asc, privs[i].priv))
739                 i++;
740         
741         if (privs[i].se_priv!=SE_PRIV_ALL) {
742                 DEBUG(10,(": %s\n", privs[i].description));
743                 init_uni_hdr(&r_u->hdr_desc, strlen(privs[i].description));
744                 init_unistr2(&r_u->desc, privs[i].description, strlen(privs[i].description) );
745
746                 r_u->ptr_info=0xdeadbeef;
747                 r_u->lang_id=q_u->lang_id;
748                 return NT_STATUS_OK;
749         } else {
750                 DEBUG(10,("_lsa_priv_get_dispname: doesn't exist\n"));
751                 r_u->ptr_info=0;
752                 return NT_STATUS_NO_SUCH_PRIVILEGE;
753         }
754 }
755
756 /***************************************************************************
757 _lsa_enum_accounts.
758  ***************************************************************************/
759
760 NTSTATUS _lsa_enum_accounts(pipes_struct *p, LSA_Q_ENUM_ACCOUNTS *q_u, LSA_R_ENUM_ACCOUNTS *r_u)
761 {
762         struct lsa_info *handle;
763         GROUP_MAP *map=NULL;
764         int num_entries=0;
765         LSA_SID_ENUM *sids=&r_u->sids;
766         int i=0,j=0;
767
768         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
769                 return NT_STATUS_INVALID_HANDLE;
770
771         /* check if the user have enough rights */
772
773         /*
774          * I don't know if it's the right one. not documented.
775          */
776         if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
777                 return NT_STATUS_ACCESS_DENIED;
778
779         /* get the list of mapped groups (domain, local, builtin) */
780         if(!enum_group_mapping(SID_NAME_UNKNOWN, &map, &num_entries, ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV))
781                 return NT_STATUS_OK;
782
783         if (q_u->enum_context >= num_entries)
784                 return NT_STATUS_NO_MORE_ENTRIES;
785
786         sids->ptr_sid = (uint32 *)talloc_zero(p->mem_ctx, (num_entries-q_u->enum_context)*sizeof(uint32));
787         sids->sid = (DOM_SID2 *)talloc_zero(p->mem_ctx, (num_entries-q_u->enum_context)*sizeof(DOM_SID2));
788
789         if (sids->ptr_sid==NULL || sids->sid==NULL) {
790                 SAFE_FREE(map);
791                 return NT_STATUS_NO_MEMORY;
792         }
793
794         for (i=q_u->enum_context, j=0; i<num_entries; i++) {
795                 init_dom_sid2( &(*sids).sid[j],  &map[i].sid);
796                 (*sids).ptr_sid[j]=1;
797                 j++;
798         }
799
800         SAFE_FREE(map);
801
802         init_lsa_r_enum_accounts(r_u, j);
803
804         return NT_STATUS_OK;
805 }
806
807
808 NTSTATUS _lsa_unk_get_connuser(pipes_struct *p, LSA_Q_UNK_GET_CONNUSER *q_u, LSA_R_UNK_GET_CONNUSER *r_u)
809 {
810         fstring username, domname;
811         int ulen, dlen;
812         user_struct *vuser = get_valid_user_struct(p->vuid);
813   
814         if (vuser == NULL)
815                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
816   
817         fstrcpy(username, vuser->user.smb_name);
818         fstrcpy(domname, vuser->user.domain);
819   
820         ulen = strlen(username) + 1;
821         dlen = strlen(domname) + 1;
822   
823         init_uni_hdr(&r_u->hdr_user_name, ulen);
824         r_u->ptr_user_name = 1;
825         init_unistr2(&r_u->uni2_user_name, username, ulen);
826
827         r_u->unk1 = 1;
828   
829         init_uni_hdr(&r_u->hdr_dom_name, dlen);
830         r_u->ptr_dom_name = 1;
831         init_unistr2(&r_u->uni2_dom_name, domname, dlen);
832
833         r_u->status = NT_STATUS_OK;
834   
835         return r_u->status;
836 }
837
838 /***************************************************************************
839  
840  ***************************************************************************/
841
842 NTSTATUS _lsa_open_account(pipes_struct *p, LSA_Q_OPENACCOUNT *q_u, LSA_R_OPENACCOUNT *r_u)
843 {
844         struct lsa_info *handle;
845         struct lsa_info *info;
846
847         r_u->status = NT_STATUS_OK;
848
849         /* find the connection policy handle. */
850         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
851                 return NT_STATUS_INVALID_HANDLE;
852
853         /* check if the user have enough rights */
854
855         /*
856          * I don't know if it's the right one. not documented.
857          * but guessed with rpcclient.
858          */
859         if (!(handle->access & POLICY_GET_PRIVATE_INFORMATION))
860                 return NT_STATUS_ACCESS_DENIED;
861
862         /* associate the user/group SID with the (unique) handle. */
863         if ((info = (struct lsa_info *)malloc(sizeof(struct lsa_info))) == NULL)
864                 return NT_STATUS_NO_MEMORY;
865
866         ZERO_STRUCTP(info);
867         info->sid = q_u->sid.sid;
868         info->access = q_u->access;
869
870         /* get a (unique) handle.  open a policy on it. */
871         if (!create_policy_hnd(p, &r_u->pol, free_lsa_info, (void *)info))
872                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
873
874         return r_u->status;
875 }
876
877 /***************************************************************************
878  For a given SID, enumerate all the privilege this account has.
879  ***************************************************************************/
880
881 NTSTATUS _lsa_enum_privsaccount(pipes_struct *p, LSA_Q_ENUMPRIVSACCOUNT *q_u, LSA_R_ENUMPRIVSACCOUNT *r_u)
882 {
883         struct lsa_info *info=NULL;
884         GROUP_MAP map;
885         int i=0;
886
887         LUID_ATTR *set=NULL;
888
889         r_u->status = NT_STATUS_OK;
890
891         /* find the connection policy handle. */
892         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
893                 return NT_STATUS_INVALID_HANDLE;
894
895         if (!get_group_map_from_sid(info->sid, &map, MAPPING_WITH_PRIV))
896                 return NT_STATUS_NO_SUCH_GROUP;
897
898         DEBUG(10,("_lsa_enum_privsaccount: %d privileges\n", map.priv_set.count));
899         if (map.priv_set.count!=0) {
900         
901                 set=(LUID_ATTR *)talloc(p->mem_ctx, map.priv_set.count*sizeof(LUID_ATTR));
902                 if (set == NULL) {
903                         free_privilege(&map.priv_set);  
904                         return NT_STATUS_NO_MEMORY;
905                 }
906
907                 for (i=0; i<map.priv_set.count; i++) {
908                         set[i].luid.low=map.priv_set.set[i].luid.low;
909                         set[i].luid.high=map.priv_set.set[i].luid.high;
910                         set[i].attr=map.priv_set.set[i].attr;
911                         DEBUG(10,("_lsa_enum_privsaccount: priv %d: %d:%d:%d\n", i, 
912                                    set[i].luid.high, set[i].luid.low, set[i].attr));
913                 }
914         }
915
916         init_lsa_r_enum_privsaccount(r_u, set, map.priv_set.count, 0);  
917         free_privilege(&map.priv_set);  
918
919         return r_u->status;
920 }
921
922 /***************************************************************************
923  
924  ***************************************************************************/
925
926 NTSTATUS _lsa_getsystemaccount(pipes_struct *p, LSA_Q_GETSYSTEMACCOUNT *q_u, LSA_R_GETSYSTEMACCOUNT *r_u)
927 {
928         struct lsa_info *info=NULL;
929         GROUP_MAP map;
930         r_u->status = NT_STATUS_OK;
931
932         /* find the connection policy handle. */
933         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
934                 return NT_STATUS_INVALID_HANDLE;
935
936         if (!get_group_map_from_sid(info->sid, &map, MAPPING_WITHOUT_PRIV))
937                 return NT_STATUS_NO_SUCH_GROUP;
938
939         /*
940           0x01 -> Log on locally
941           0x02 -> Access this computer from network
942           0x04 -> Log on as a batch job
943           0x10 -> Log on as a service
944           
945           they can be ORed together
946         */
947
948         r_u->access=map.systemaccount;
949
950         return r_u->status;
951 }
952
953 /***************************************************************************
954   update the systemaccount information
955  ***************************************************************************/
956
957 NTSTATUS _lsa_setsystemaccount(pipes_struct *p, LSA_Q_SETSYSTEMACCOUNT *q_u, LSA_R_SETSYSTEMACCOUNT *r_u)
958 {
959         struct lsa_info *info=NULL;
960         GROUP_MAP map;
961         r_u->status = NT_STATUS_OK;
962
963         /* find the connection policy handle. */
964         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
965                 return NT_STATUS_INVALID_HANDLE;
966
967         if (!get_group_map_from_sid(info->sid, &map, MAPPING_WITH_PRIV))
968                 return NT_STATUS_NO_SUCH_GROUP;
969
970         map.systemaccount=q_u->access;
971
972         if(!add_mapping_entry(&map, TDB_REPLACE))
973                 return NT_STATUS_NO_SUCH_GROUP;
974
975         free_privilege(&map.priv_set);
976
977         return r_u->status;
978 }
979
980 /***************************************************************************
981  For a given SID, add some privileges.
982  ***************************************************************************/
983
984 NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u)
985 {
986         struct lsa_info *info=NULL;
987         GROUP_MAP map;
988         int i=0;
989
990         LUID_ATTR *luid_attr=NULL;
991         PRIVILEGE_SET *set=NULL;
992
993         r_u->status = NT_STATUS_OK;
994
995         /* find the connection policy handle. */
996         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
997                 return NT_STATUS_INVALID_HANDLE;
998
999         if (!get_group_map_from_sid(info->sid, &map, MAPPING_WITH_PRIV))
1000                 return NT_STATUS_NO_SUCH_GROUP;
1001
1002         set=&q_u->set;
1003
1004         for (i=0; i<set->count; i++) {
1005                 luid_attr=&set->set[i];
1006                 
1007                 /* check if the privilege is already there */
1008                 if (check_priv_in_privilege(&map.priv_set, *luid_attr)){
1009                         free_privilege(&map.priv_set);
1010                         return NT_STATUS_NO_SUCH_PRIVILEGE;
1011                 }
1012                 
1013                 add_privilege(&map.priv_set, *luid_attr);
1014         }
1015
1016         if(!add_mapping_entry(&map, TDB_REPLACE))
1017                 return NT_STATUS_NO_SUCH_GROUP;
1018         
1019         free_privilege(&map.priv_set);  
1020
1021         return r_u->status;
1022 }
1023
1024 /***************************************************************************
1025  For a given SID, remove some privileges.
1026  ***************************************************************************/
1027
1028 NTSTATUS _lsa_removeprivs(pipes_struct *p, LSA_Q_REMOVEPRIVS *q_u, LSA_R_REMOVEPRIVS *r_u)
1029 {
1030         struct lsa_info *info=NULL;
1031         GROUP_MAP map;
1032         int i=0;
1033
1034         LUID_ATTR *luid_attr=NULL;
1035         PRIVILEGE_SET *set=NULL;
1036
1037         r_u->status = NT_STATUS_OK;
1038
1039         /* find the connection policy handle. */
1040         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
1041                 return NT_STATUS_INVALID_HANDLE;
1042
1043         if (!get_group_map_from_sid(info->sid, &map, MAPPING_WITH_PRIV))
1044                 return NT_STATUS_NO_SUCH_GROUP;
1045
1046         if (q_u->allrights!=0) {
1047                 /* log it and return, until I see one myself don't do anything */
1048                 DEBUG(5,("_lsa_removeprivs: trying to remove all privileges ?\n"));
1049                 return NT_STATUS_OK;
1050         }
1051
1052         if (q_u->ptr==0) {
1053                 /* log it and return, until I see one myself don't do anything */
1054                 DEBUG(5,("_lsa_removeprivs: no privileges to remove ?\n"));
1055                 return NT_STATUS_OK;
1056         }
1057
1058         set=&q_u->set;
1059
1060         for (i=0; i<set->count; i++) {
1061                 luid_attr=&set->set[i];
1062                 
1063                 /* if we don't have the privilege, we're trying to remove, give up */
1064                 /* what else can we do ??? JFM. */
1065                 if (!check_priv_in_privilege(&map.priv_set, *luid_attr)){
1066                         free_privilege(&map.priv_set);
1067                         return NT_STATUS_NO_SUCH_PRIVILEGE;
1068                 }
1069                 
1070                 remove_privilege(&map.priv_set, *luid_attr);
1071         }
1072
1073         if(!add_mapping_entry(&map, TDB_REPLACE))
1074                 return NT_STATUS_NO_SUCH_GROUP;
1075         
1076         free_privilege(&map.priv_set);  
1077
1078         return r_u->status;
1079 }
1080
1081 /***************************************************************************
1082  For a given SID, remove some privileges.
1083  ***************************************************************************/
1084
1085 NTSTATUS _lsa_query_secobj(pipes_struct *p, LSA_Q_QUERY_SEC_OBJ *q_u, LSA_R_QUERY_SEC_OBJ *r_u)
1086 {
1087         struct lsa_info *handle=NULL;
1088         SEC_DESC *psd = NULL;
1089         size_t sd_size;
1090         NTSTATUS status;
1091
1092         r_u->status = NT_STATUS_OK;
1093
1094         /* find the connection policy handle. */
1095         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
1096                 return NT_STATUS_INVALID_HANDLE;
1097
1098         /* check if the user have enough rights */
1099         if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
1100                 return NT_STATUS_ACCESS_DENIED;
1101
1102
1103         switch (q_u->sec_info) {
1104         case 1:
1105                 /* SD contains only the owner */
1106
1107                 status=lsa_get_generic_sd(p->mem_ctx, &psd, &sd_size);
1108                 if(!NT_STATUS_IS_OK(status))
1109                         return NT_STATUS_NO_MEMORY;
1110
1111
1112                 if((r_u->buf = make_sec_desc_buf(p->mem_ctx, sd_size, psd)) == NULL)
1113                         return NT_STATUS_NO_MEMORY;
1114                 break;
1115         case 4:
1116                 /* SD contains only the ACL */
1117
1118                 status=lsa_get_generic_sd(p->mem_ctx, &psd, &sd_size);
1119                 if(!NT_STATUS_IS_OK(status))
1120                         return NT_STATUS_NO_MEMORY;
1121
1122                 if((r_u->buf = make_sec_desc_buf(p->mem_ctx, sd_size, psd)) == NULL)
1123                         return NT_STATUS_NO_MEMORY;
1124                 break;
1125         default:
1126                 return NT_STATUS_INVALID_LEVEL;
1127         }
1128
1129         r_u->ptr=1;
1130
1131         return r_u->status;
1132 }
1133
1134