r11291: Fix implementation of LookupNames4.
[kai/samba-autobuild/.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    endpoint server for the lsarpc pipe
5
6    Copyright (C) Andrew Tridgell 2004
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
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 "librpc/gen_ndr/ndr_lsa.h"
26 #include "librpc/gen_ndr/ndr_samr.h"
27 #include "rpc_server/dcerpc_server.h"
28 #include "rpc_server/common/common.h"
29 #include "lib/ldb/include/ldb.h"
30 #include "system/time.h"
31 #include "db_wrap.h"
32 #include "auth/auth.h"
33
34 /*
35   this type allows us to distinguish handle types
36 */
37 enum lsa_handle {
38         LSA_HANDLE_POLICY,
39         LSA_HANDLE_ACCOUNT,
40         LSA_HANDLE_SECRET,
41         LSA_HANDLE_TRUSTED_DOMAIN
42 };
43
44 /*
45   state associated with a lsa_OpenPolicy() operation
46 */
47 struct lsa_policy_state {
48         struct dcesrv_handle *handle;
49         struct ldb_context *sam_ldb;
50         struct sidmap_context *sidmap;
51         uint32_t access_mask;
52         const struct ldb_dn *domain_dn;
53         const struct ldb_dn *builtin_dn;
54         const struct ldb_dn *system_dn;
55         const char *domain_name;
56         struct dom_sid *domain_sid;
57         struct dom_sid *builtin_sid;
58 };
59
60
61 /*
62   state associated with a lsa_OpenAccount() operation
63 */
64 struct lsa_account_state {
65         struct lsa_policy_state *policy;
66         uint32_t access_mask;
67         struct dom_sid *account_sid;
68         const struct ldb_dn *account_dn;
69 };
70
71
72 /*
73   state associated with a lsa_OpenSecret() operation
74 */
75 struct lsa_secret_state {
76         struct lsa_policy_state *policy;
77         uint32_t access_mask;
78         const struct ldb_dn *secret_dn;
79         struct ldb_context *sam_ldb;
80         BOOL global;
81 };
82
83 /*
84   state associated with a lsa_OpenTrustedDomain() operation
85 */
86 struct lsa_trusted_domain_state {
87         struct lsa_policy_state *policy;
88         uint32_t access_mask;
89         const struct ldb_dn *trusted_domain_dn;
90 };
91
92 /* 
93   lsa_Close 
94 */
95 static NTSTATUS lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
96                           struct lsa_Close *r)
97 {
98         struct dcesrv_handle *h;
99
100         *r->out.handle = *r->in.handle;
101
102         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
103
104         talloc_free(h);
105
106         ZERO_STRUCTP(r->out.handle);
107
108         return NT_STATUS_OK;
109 }
110
111
112 /* 
113   lsa_Delete 
114 */
115 static NTSTATUS lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
116                            struct lsa_Delete *r)
117 {
118         struct dcesrv_handle *h;
119         int ret;
120
121         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
122         if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
123                 struct lsa_secret_state *secret_state = h->data;
124                 ret = samdb_delete(secret_state->sam_ldb, mem_ctx, secret_state->secret_dn);
125                 talloc_free(h);
126                 if (ret != 0) {
127                         return NT_STATUS_INVALID_HANDLE;
128                 }
129
130                 return NT_STATUS_OK;
131         } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
132                 struct lsa_trusted_domain_state *trusted_domain_state = h->data;
133                 ret = samdb_delete(trusted_domain_state->policy->sam_ldb, mem_ctx, 
134                                    trusted_domain_state->trusted_domain_dn);
135                 talloc_free(h);
136                 if (ret != 0) {
137                         return NT_STATUS_INVALID_HANDLE;
138                 }
139
140                 return NT_STATUS_OK;
141         } 
142         
143         return NT_STATUS_INVALID_HANDLE;
144 }
145
146
147 /* 
148   lsa_EnumPrivs 
149 */
150 static NTSTATUS lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
151                               struct lsa_EnumPrivs *r)
152 {
153         struct dcesrv_handle *h;
154         struct lsa_policy_state *state;
155         int i;
156         const char *privname;
157
158         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
159
160         state = h->data;
161
162         i = *r->in.resume_handle;
163         if (i == 0) i = 1;
164
165         while ((privname = sec_privilege_name(i)) &&
166                r->out.privs->count < r->in.max_count) {
167                 struct lsa_PrivEntry *e;
168
169                 r->out.privs->privs = talloc_realloc(r->out.privs,
170                                                        r->out.privs->privs, 
171                                                        struct lsa_PrivEntry, 
172                                                        r->out.privs->count+1);
173                 if (r->out.privs->privs == NULL) {
174                         return NT_STATUS_NO_MEMORY;
175                 }
176                 e = &r->out.privs->privs[r->out.privs->count];
177                 e->luid.low = i;
178                 e->luid.high = 0;
179                 e->name.string = privname;
180                 r->out.privs->count++;
181                 i++;
182         }
183
184         *r->out.resume_handle = i;
185
186         return NT_STATUS_OK;
187 }
188
189
190 /* 
191   lsa_QuerySecObj 
192 */
193 static NTSTATUS lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
194                                   struct lsa_QuerySecurity *r)
195 {
196         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
197 }
198
199
200 /* 
201   lsa_SetSecObj 
202 */
203 static NTSTATUS lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
204                               struct lsa_SetSecObj *r)
205 {
206         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
207 }
208
209
210 /* 
211   lsa_ChangePassword 
212 */
213 static NTSTATUS lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
214                                    struct lsa_ChangePassword *r)
215 {
216         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
217 }
218
219 static NTSTATUS lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
220                                      struct lsa_policy_state **_state)
221 {
222         struct lsa_policy_state *state;
223
224         state = talloc(mem_ctx, struct lsa_policy_state);
225         if (!state) {
226                 return NT_STATUS_NO_MEMORY;
227         }
228
229         /* make sure the sam database is accessible */
230         state->sam_ldb = samdb_connect(state, dce_call->conn->auth_state.session_info); 
231         if (state->sam_ldb == NULL) {
232                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
233         }
234
235         state->sidmap = sidmap_open(state);
236         if (state->sidmap == NULL) {
237                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
238         }
239
240         /* work out the domain_dn - useful for so many calls its worth
241            fetching here */
242         state->domain_dn = samdb_base_dn(state);
243         if (!state->domain_dn) {
244                 return NT_STATUS_NO_MEMORY;             
245         }
246
247         state->domain_name
248                 = samdb_search_string(state->sam_ldb, state, NULL, "nETBIOSName", 
249                                       "(&(objectclass=crossRef)(ncName=%s))", ldb_dn_linearize(mem_ctx, state->domain_dn));
250         
251         if (!state->domain_name) {
252                 return NT_STATUS_NO_SUCH_DOMAIN;                
253         }
254         talloc_steal(state, state->domain_name);
255
256         /* work out the builtin_dn - useful for so many calls its worth
257            fetching here */
258         state->builtin_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(objectClass=builtinDomain)");
259         if (!state->builtin_dn) {
260                 return NT_STATUS_NO_SUCH_DOMAIN;                
261         }
262
263         /* work out the system_dn - useful for so many calls its worth
264            fetching here */
265         state->system_dn = samdb_search_dn(state->sam_ldb, state,
266                                            state->domain_dn, "(&(objectClass=container)(cn=System))");
267         if (!state->system_dn) {
268                 return NT_STATUS_NO_SUCH_DOMAIN;                
269         }
270
271         state->domain_sid = samdb_search_dom_sid(state->sam_ldb, state,
272                                                  state->domain_dn, "objectSid", NULL);
273         if (!state->domain_sid) {
274                 return NT_STATUS_NO_SUCH_DOMAIN;                
275         }
276
277         talloc_steal(state, state->domain_sid);
278
279         state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN);
280         if (!state->builtin_sid) {
281                 return NT_STATUS_NO_SUCH_DOMAIN;                
282         }
283
284         *_state = state;
285
286         return NT_STATUS_OK;
287 }
288
289 /* 
290   lsa_OpenPolicy2
291 */
292 static NTSTATUS lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
293                                struct lsa_OpenPolicy2 *r)
294 {
295         NTSTATUS status;
296         struct lsa_policy_state *state;
297         struct dcesrv_handle *handle;
298
299         ZERO_STRUCTP(r->out.handle);
300
301         status = lsa_get_policy_state(dce_call, mem_ctx, &state);
302         if (!NT_STATUS_IS_OK(status)) {
303                 return status;
304         }
305
306         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_POLICY);
307         if (!handle) {
308                 return NT_STATUS_NO_MEMORY;
309         }
310
311         handle->data = talloc_steal(handle, state);
312
313         state->access_mask = r->in.access_mask;
314         state->handle = handle;
315         *r->out.handle = handle->wire_handle;
316
317         /* note that we have completely ignored the attr element of
318            the OpenPolicy. As far as I can tell, this is what w2k3
319            does */
320
321         return NT_STATUS_OK;
322 }
323
324 /* 
325   lsa_OpenPolicy
326   a wrapper around lsa_OpenPolicy2
327 */
328 static NTSTATUS lsa_OpenPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
329                                 struct lsa_OpenPolicy *r)
330 {
331         struct lsa_OpenPolicy2 r2;
332
333         r2.in.system_name = NULL;
334         r2.in.attr = r->in.attr;
335         r2.in.access_mask = r->in.access_mask;
336         r2.out.handle = r->out.handle;
337
338         return lsa_OpenPolicy2(dce_call, mem_ctx, &r2);
339 }
340
341
342
343
344 /*
345   fill in the AccountDomain info
346 */
347 static NTSTATUS lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
348                                        struct lsa_DomainInfo *info)
349 {
350         info->name.string = state->domain_name;
351         info->sid         = state->domain_sid;
352
353         return NT_STATUS_OK;
354 }
355
356 /*
357   fill in the DNS domain info
358 */
359 static NTSTATUS lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
360                              struct lsa_DnsDomainInfo *info)
361 {
362         const char * const attrs[] = { "dnsDomain", "objectGUID", "objectSid", NULL };
363         int ret;
364         struct ldb_message **res;
365
366         ret = gendb_search_dn(state->sam_ldb, mem_ctx, state->domain_dn, &res, attrs);
367         if (ret != 1) {
368                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
369         }
370
371         info->name.string = state->domain_name;
372         info->sid         = state->domain_sid;
373         info->dns_domain.string = samdb_result_string(res[0],           "dnsDomain", NULL);
374         info->dns_forest.string = samdb_result_string(res[0],           "dnsDomain", NULL);
375         info->domain_guid       = samdb_result_guid(res[0],             "objectGUID");
376
377         return NT_STATUS_OK;
378 }
379
380 /* 
381   lsa_QueryInfoPolicy2
382 */
383 static NTSTATUS lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
384                                      struct lsa_QueryInfoPolicy2 *r)
385 {
386         struct lsa_policy_state *state;
387         struct dcesrv_handle *h;
388
389         r->out.info = NULL;
390
391         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
392
393         state = h->data;
394
395         r->out.info = talloc(mem_ctx, union lsa_PolicyInformation);
396         if (!r->out.info) {
397                 return NT_STATUS_NO_MEMORY;
398         }
399
400         ZERO_STRUCTP(r->out.info);
401
402         switch (r->in.level) {
403         case LSA_POLICY_INFO_DOMAIN:
404         case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
405                 return lsa_info_AccountDomain(state, mem_ctx, &r->out.info->account_domain);
406
407         case LSA_POLICY_INFO_DNS:
408                 return lsa_info_DNS(state, mem_ctx, &r->out.info->dns);
409         }
410
411         return NT_STATUS_INVALID_INFO_CLASS;
412 }
413
414 /* 
415   lsa_QueryInfoPolicy 
416 */
417 static NTSTATUS lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
418                                     struct lsa_QueryInfoPolicy *r)
419 {
420         struct lsa_QueryInfoPolicy2 r2;
421         NTSTATUS status;
422
423         r2.in.handle = r->in.handle;
424         r2.in.level = r->in.level;
425         
426         status = lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
427
428         r->out.info = r2.out.info;
429
430         return status;
431 }
432
433 /* 
434   lsa_SetInfoPolicy 
435 */
436 static NTSTATUS lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
437                                   struct lsa_SetInfoPolicy *r)
438 {
439         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
440 }
441
442
443 /* 
444   lsa_ClearAuditLog 
445 */
446 static NTSTATUS lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
447                                   struct lsa_ClearAuditLog *r)
448 {
449         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
450 }
451
452
453 /* 
454   lsa_CreateAccount 
455 */
456 static NTSTATUS lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
457                                   struct lsa_CreateAccount *r)
458 {
459         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
460 }
461
462
463 /* 
464   lsa_EnumAccounts 
465 */
466 static NTSTATUS lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
467                                  struct lsa_EnumAccounts *r)
468 {
469         struct dcesrv_handle *h;
470         struct lsa_policy_state *state;
471         int ret, i;
472         struct ldb_message **res;
473         const char * const attrs[] = { "objectSid", NULL};
474         uint32_t count;
475
476         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
477
478         state = h->data;
479
480         ret = gendb_search(state->sam_ldb, mem_ctx, state->builtin_dn, &res, attrs, 
481                            "(|(privilege=*)(objectSid=*))");
482         if (ret <= 0) {
483                 return NT_STATUS_NO_SUCH_USER;
484         }
485
486         if (*r->in.resume_handle >= ret) {
487                 return NT_STATUS_NO_MORE_ENTRIES;
488         }
489
490         count = ret - *r->in.resume_handle;
491         if (count > r->in.num_entries) {
492                 count = r->in.num_entries;
493         }
494
495         if (count == 0) {
496                 return NT_STATUS_NO_MORE_ENTRIES;
497         }
498
499         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
500         if (r->out.sids->sids == NULL) {
501                 return NT_STATUS_NO_MEMORY;
502         }
503
504         for (i=0;i<count;i++) {
505                 r->out.sids->sids[i].sid = 
506                         samdb_result_dom_sid(r->out.sids->sids, 
507                                              res[i + *r->in.resume_handle],
508                                              "objectSid");
509                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
510         }
511
512         r->out.sids->num_sids = count;
513         *r->out.resume_handle = count + *r->in.resume_handle;
514
515         return NT_STATUS_OK;
516         
517 }
518
519
520 /*
521   lsa_CreateTrustedDomainEx2
522 */
523 static NTSTATUS lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
524                                            TALLOC_CTX *mem_ctx,
525                                            struct lsa_CreateTrustedDomainEx2 *r)
526 {
527         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
528 }
529
530 /*
531   lsa_CreateTrustedDomainEx
532 */
533 static NTSTATUS lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
534                                           TALLOC_CTX *mem_ctx,
535                                           struct lsa_CreateTrustedDomainEx *r)
536 {
537         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
538 }
539
540 /* 
541   lsa_CreateTrustedDomain 
542 */
543 static NTSTATUS lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
544                                         struct lsa_CreateTrustedDomain *r)
545 {
546         struct dcesrv_handle *policy_handle;
547         struct lsa_policy_state *policy_state;
548         struct lsa_trusted_domain_state *trusted_domain_state;
549         struct dcesrv_handle *handle;
550         struct ldb_message **msgs, *msg;
551         const char *attrs[] = {
552                 NULL
553         };
554         const char *name;
555         int ret;
556
557         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
558         ZERO_STRUCTP(r->out.trustdom_handle);
559         
560         policy_state = policy_handle->data;
561
562         if (!r->in.info->name.string) {
563                 return NT_STATUS_INVALID_PARAMETER;
564         }
565         name = r->in.info->name.string;
566         
567         trusted_domain_state = talloc(mem_ctx, struct lsa_trusted_domain_state);
568         if (!trusted_domain_state) {
569                 return NT_STATUS_NO_MEMORY;
570         }
571         trusted_domain_state->policy = policy_state;
572
573         msg = ldb_msg_new(mem_ctx);
574         if (msg == NULL) {
575                 return NT_STATUS_NO_MEMORY;
576         }
577
578         /* search for the trusted_domain record */
579         ret = gendb_search(trusted_domain_state->policy->sam_ldb,
580                            mem_ctx, policy_state->system_dn, &msgs, attrs,
581                            "(&(cn=%s)(objectclass=trustedDomain))", 
582                            r->in.info->name.string);
583         if (ret > 0) {
584                 return NT_STATUS_OBJECT_NAME_COLLISION;
585         }
586         
587         if (ret < 0 || ret > 1) {
588                 DEBUG(0,("Found %d records matching DN %s\n", ret,
589                          ldb_dn_linearize(mem_ctx, policy_state->system_dn)));
590                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
591         }
592         
593         msg->dn = ldb_dn_build_child(mem_ctx, "cn",
594                                      r->in.info->name.string, 
595                                      policy_state->system_dn);
596         if (!msg->dn) {
597                 return NT_STATUS_NO_MEMORY;
598         }
599         
600         samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "cn", name);
601         samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "flatname", name);
602
603         if (r->in.info->sid) {
604                 const char *sid_string = dom_sid_string(mem_ctx, r->in.info->sid);
605                 if (!sid_string) {
606                         return NT_STATUS_NO_MEMORY;
607                 }
608                         
609                 samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "securityIdentifier", sid_string);
610         }
611
612         samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "objectClass", "trustedDomain");
613         
614         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
615
616         /* create the trusted_domain */
617         ret = samdb_add(trusted_domain_state->policy->sam_ldb, mem_ctx, msg);
618         if (ret != 0) {
619                 DEBUG(0,("Failed to create trusted_domain record %s\n",
620                          ldb_dn_linearize(mem_ctx, msg->dn)));
621                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
622         }
623
624         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
625         if (!handle) {
626                 return NT_STATUS_NO_MEMORY;
627         }
628         
629         handle->data = talloc_steal(handle, trusted_domain_state);
630         
631         trusted_domain_state->access_mask = r->in.access_mask;
632         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
633         
634         *r->out.trustdom_handle = handle->wire_handle;
635         
636         return NT_STATUS_OK;
637 }
638
639 /* 
640   lsa_OpenTrustedDomain
641 */
642 static NTSTATUS lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
643                                       struct lsa_OpenTrustedDomain *r)
644 {
645         struct dcesrv_handle *policy_handle;
646         
647         struct lsa_policy_state *policy_state;
648         struct lsa_trusted_domain_state *trusted_domain_state;
649         struct dcesrv_handle *handle;
650         struct ldb_message **msgs;
651         const char *attrs[] = {
652                 NULL
653         };
654
655         const char *sid_string;
656         int ret;
657
658         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
659         ZERO_STRUCTP(r->out.trustdom_handle);
660         policy_state = policy_handle->data;
661
662         trusted_domain_state = talloc(mem_ctx, struct lsa_trusted_domain_state);
663         if (!trusted_domain_state) {
664                 return NT_STATUS_NO_MEMORY;
665         }
666         trusted_domain_state->policy = policy_state;
667
668         sid_string = dom_sid_string(mem_ctx, r->in.sid);
669         if (!sid_string) {
670                 return NT_STATUS_NO_MEMORY;
671         }
672
673         /* search for the trusted_domain record */
674         ret = gendb_search(trusted_domain_state->policy->sam_ldb,
675                            mem_ctx, policy_state->system_dn, &msgs, attrs,
676                            "(&(securityIdentifier=%s)(objectclass=trustedDomain))", 
677                            sid_string);
678         if (ret == 0) {
679                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
680         }
681         
682         if (ret != 1) {
683                 DEBUG(0,("Found %d records matching DN %s\n", ret,
684                          ldb_dn_linearize(mem_ctx, policy_state->system_dn)));
685                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
686         }
687
688         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
689         
690         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
691         if (!handle) {
692                 return NT_STATUS_NO_MEMORY;
693         }
694         
695         handle->data = talloc_steal(handle, trusted_domain_state);
696         
697         trusted_domain_state->access_mask = r->in.access_mask;
698         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
699         
700         *r->out.trustdom_handle = handle->wire_handle;
701         
702         return NT_STATUS_OK;
703 }
704
705
706 /*
707   lsa_OpenTrustedDomainByName
708 */
709 static NTSTATUS lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
710                                             TALLOC_CTX *mem_ctx,
711                                             struct lsa_OpenTrustedDomainByName *r)
712 {
713         struct dcesrv_handle *policy_handle;
714         
715         struct lsa_policy_state *policy_state;
716         struct lsa_trusted_domain_state *trusted_domain_state;
717         struct dcesrv_handle *handle;
718         struct ldb_message **msgs;
719         const char *attrs[] = {
720                 NULL
721         };
722
723         int ret;
724
725         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
726         ZERO_STRUCTP(r->out.trustdom_handle);
727         policy_state = policy_handle->data;
728
729         if (!r->in.name.string) {
730                 return NT_STATUS_INVALID_PARAMETER;
731         }
732         
733         trusted_domain_state = talloc(mem_ctx, struct lsa_trusted_domain_state);
734         if (!trusted_domain_state) {
735                 return NT_STATUS_NO_MEMORY;
736         }
737         trusted_domain_state->policy = policy_state;
738
739         /* search for the trusted_domain record */
740         ret = gendb_search(trusted_domain_state->policy->sam_ldb,
741                            mem_ctx, policy_state->system_dn, &msgs, attrs,
742                            "(&(flatname=%s)(objectclass=trustedDomain))", 
743                            r->in.name.string);
744         if (ret == 0) {
745                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
746         }
747         
748         if (ret != 1) {
749                 DEBUG(0,("Found %d records matching DN %s\n", ret,
750                          ldb_dn_linearize(mem_ctx, policy_state->system_dn)));
751                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
752         }
753
754         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
755         
756         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
757         if (!handle) {
758                 return NT_STATUS_NO_MEMORY;
759         }
760         
761         handle->data = talloc_steal(handle, trusted_domain_state);
762         
763         trusted_domain_state->access_mask = r->in.access_mask;
764         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
765         
766         *r->out.trustdom_handle = handle->wire_handle;
767         
768         return NT_STATUS_OK;
769 }
770
771
772 /* 
773   lsa_QueryTrustedDomainInfoBySid
774 */
775 static NTSTATUS lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
776                                                 struct lsa_QueryTrustedDomainInfoBySid *r)
777 {
778         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
779 }
780
781
782 /* 
783   lsa_SetTrustDomainInfo
784 */
785 static NTSTATUS lsa_SetTrustDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
786                        struct lsa_SetTrustDomainInfo *r)
787 {
788         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
789 }
790
791
792 /* 
793   lsa_DeleteTrustDomain
794 */
795 static NTSTATUS lsa_DeleteTrustDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
796                                       struct lsa_DeleteTrustDomain *r)
797 {
798         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
799 }
800
801
802 /* 
803   lsa_QueryTrustedDomainInfo
804 */
805 static NTSTATUS lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
806                                            struct lsa_QueryTrustedDomainInfo *r)
807 {
808         struct dcesrv_handle *h;
809         struct lsa_trusted_domain_state *trusted_domain_state;
810         struct ldb_message *msg;
811         int ret;
812         struct ldb_message **res;
813         const char *attrs[] = {
814                 "cn",
815                 "flatname",
816                 "posixOffset",
817                 "securityIdentifier",
818                 NULL
819         };
820
821         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
822
823         trusted_domain_state = h->data;
824
825         /* pull all the user attributes */
826         ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
827                               trusted_domain_state->trusted_domain_dn, &res, attrs);
828         if (ret != 1) {
829                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
830         }
831         msg = res[0];
832         
833         r->out.info = talloc(mem_ctx, union lsa_TrustedDomainInfo);
834         if (!r->out.info) {
835                 return NT_STATUS_NO_MEMORY;
836         }
837         switch (r->in.level) {
838         case LSA_TRUSTED_DOMAIN_INFO_NAME:
839                 r->out.info->name.netbios_name.string
840                         = samdb_result_string(msg, "flatname", NULL);                                      
841                 break;
842         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
843                 r->out.info->posix_offset.posix_offset
844                         = samdb_result_uint(msg, "posixOffset", 0);                                        
845                 break;
846         default:
847                 /* oops, we don't want to return the info after all */
848                 talloc_free(r->out.info);
849                 r->out.info = NULL;
850                 return NT_STATUS_INVALID_INFO_CLASS;
851         }
852
853         return NT_STATUS_OK;
854 }
855
856
857 /* 
858   lsa_SetInformationTrustedDomain
859 */
860 static NTSTATUS lsa_SetInformationTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
861                        struct lsa_SetInformationTrustedDomain *r)
862 {
863         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
864 }
865
866
867 /*
868   lsa_QueryTrustedDomainInfoByName
869 */
870 static NTSTATUS lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
871                                                  TALLOC_CTX *mem_ctx,
872                                                  struct lsa_QueryTrustedDomainInfoByName *r)
873 {
874         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
875 }
876
877 /*
878   lsa_SetTrustedDomainInfoByName
879 */
880 static NTSTATUS lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
881                                                TALLOC_CTX *mem_ctx,
882                                                struct lsa_SetTrustedDomainInfoByName *r)
883 {
884         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
885 }
886
887 /*
888   lsa_EnumTrustedDomainsEx
889 */
890 static NTSTATUS lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call,
891                                          TALLOC_CTX *mem_ctx,
892                                          struct lsa_EnumTrustedDomainsEx *r)
893 {
894         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
895 }
896
897 /*
898   lsa_CloseTrustedDomainEx
899 */
900 static NTSTATUS lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
901                                          TALLOC_CTX *mem_ctx,
902                                          struct lsa_CloseTrustedDomainEx *r)
903 {
904         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
905 }
906
907
908 /*
909   comparison function for sorting lsa_DomainInformation array
910 */
911 static int compare_DomainInformation(struct lsa_DomainInformation *e1, struct lsa_DomainInformation *e2)
912 {
913         return strcasecmp(e1->name.string, e2->name.string);
914 }
915
916 /* 
917   lsa_EnumTrustDom 
918 */
919 static NTSTATUS lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
920                                  struct lsa_EnumTrustDom *r)
921 {
922         struct dcesrv_handle *policy_handle;
923         struct lsa_DomainInformation *entries;
924         struct lsa_policy_state *policy_state;
925         struct ldb_message **domains;
926         const char *attrs[] = {
927                 "flatname", 
928                 "securityIdentifier",
929                 NULL
930         };
931
932
933         int count, i;
934
935         *r->out.resume_handle = 0;
936
937         r->out.domains->domains = NULL;
938         r->out.domains->count = 0;
939
940         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
941
942         policy_state = policy_handle->data;
943
944         /* search for all users in this domain. This could possibly be cached and 
945            resumed based on resume_key */
946         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs, 
947                              "objectclass=trustedDomain");
948         if (count == -1) {
949                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
950         }
951         if (count == 0 || r->in.max_size == 0) {
952                 return NT_STATUS_OK;
953         }
954
955         /* convert to lsa_DomainInformation format */
956         entries = talloc_array(mem_ctx, struct lsa_DomainInformation, count);
957         if (!entries) {
958                 return NT_STATUS_NO_MEMORY;
959         }
960         for (i=0;i<count;i++) {
961                 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
962                 entries[i].name.string = samdb_result_string(domains[i], "flatname", NULL);
963         }
964
965         /* sort the results by name */
966         qsort(entries, count, sizeof(struct lsa_DomainInformation), 
967               (comparison_fn_t)compare_DomainInformation);
968
969         if (*r->in.resume_handle >= count) {
970                 *r->out.resume_handle = -1;
971
972                 return NT_STATUS_NO_MORE_ENTRIES;
973         }
974
975         /* return the rest, limit by max_size. Note that we 
976            use the w2k3 element size value of 60 */
977         r->out.domains->count = count - *r->in.resume_handle;
978         r->out.domains->count = MIN(r->out.domains->count, 
979                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
980
981         r->out.domains->domains = entries + *r->in.resume_handle;
982         r->out.domains->count = r->out.domains->count;
983
984         if (r->out.domains->count < count - *r->in.resume_handle) {
985                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
986                 return STATUS_MORE_ENTRIES;
987         }
988
989         return NT_STATUS_OK;
990 }
991
992
993 /*
994   return the authority name and authority sid, given a sid
995 */
996 static NTSTATUS lsa_authority_name(struct lsa_policy_state *state,
997                                    TALLOC_CTX *mem_ctx, struct dom_sid *sid,
998                                    const char **authority_name,
999                                    struct dom_sid **authority_sid)
1000 {
1001         if (dom_sid_in_domain(state->domain_sid, sid)) {
1002                 *authority_name = state->domain_name;
1003                 *authority_sid = state->domain_sid;
1004                 return NT_STATUS_OK;
1005         }
1006
1007         if (dom_sid_in_domain(state->builtin_sid, sid)) {
1008                 *authority_name = "BUILTIN";
1009                 *authority_sid = state->builtin_sid;
1010                 return NT_STATUS_OK;
1011         }
1012
1013         *authority_sid = dom_sid_dup(mem_ctx, sid);
1014         if (*authority_sid == NULL) {
1015                 return NT_STATUS_NO_MEMORY;
1016         }
1017         (*authority_sid)->num_auths = 0;
1018         *authority_name = dom_sid_string(mem_ctx, *authority_sid);
1019         if (*authority_name == NULL) {
1020                 return NT_STATUS_NO_MEMORY;
1021         }
1022
1023         return NT_STATUS_OK;
1024 }
1025
1026 /*
1027   add to the lsa_RefDomainList for LookupSids and LookupNames
1028 */
1029 static NTSTATUS lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx, 
1030                                    struct dom_sid *sid, 
1031                                    struct lsa_RefDomainList *domains,
1032                                    uint32_t *sid_index)
1033 {
1034         NTSTATUS status;
1035         const char *authority_name;
1036         struct dom_sid *authority_sid;
1037         int i;
1038
1039         /* work out the authority name */
1040         status = lsa_authority_name(state, mem_ctx, sid, 
1041                                     &authority_name, &authority_sid);
1042         if (!NT_STATUS_IS_OK(status)) {
1043                 return status;
1044         }
1045         
1046         /* see if we've already done this authority name */
1047         for (i=0;i<domains->count;i++) {
1048                 if (strcmp(authority_name, domains->domains[i].name.string) == 0) {
1049                         *sid_index = i;
1050                         return NT_STATUS_OK;
1051                 }
1052         }
1053
1054         domains->domains = talloc_realloc(domains, 
1055                                           domains->domains,
1056                                           struct lsa_TrustInformation,
1057                                           domains->count+1);
1058         if (domains->domains == NULL) {
1059                 return NT_STATUS_NO_MEMORY;
1060         }
1061         domains->domains[i].name.string = authority_name;
1062         domains->domains[i].sid         = authority_sid;
1063         domains->count++;
1064         *sid_index = i;
1065         
1066         return NT_STATUS_OK;
1067 }
1068
1069 /*
1070   lookup a name for 1 SID
1071 */
1072 static NTSTATUS lsa_lookup_sid(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
1073                                struct dom_sid *sid, const char *sid_str,
1074                                const char **name, uint32_t *atype)
1075 {
1076         int ret;
1077         struct ldb_message **res;
1078         const char * const attrs[] = { "sAMAccountName", "sAMAccountType", "name", NULL};
1079         NTSTATUS status;
1080
1081         ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, 
1082                            "objectSid=%s", ldap_encode_ndr_dom_sid(mem_ctx, sid));
1083         if (ret == 1) {
1084                 *name = ldb_msg_find_string(res[0], "sAMAccountName", NULL);
1085                 if (!*name) {
1086                         *name = ldb_msg_find_string(res[0], "name", NULL);
1087                         if (!*name) {
1088                                 *name = talloc_strdup(mem_ctx, sid_str);
1089                                 NTSTATUS_TALLOC_CHECK(*name);
1090                         }
1091                 }
1092
1093                 *atype = samdb_result_uint(res[0], "sAMAccountType", 0);
1094
1095                 return NT_STATUS_OK;
1096         }
1097
1098         status = sidmap_allocated_sid_lookup(state->sidmap, mem_ctx, sid, name, atype);
1099
1100         return status;
1101 }
1102
1103
1104 /*
1105   lsa_LookupSids3
1106 */
1107 static NTSTATUS lsa_LookupSids3(struct dcesrv_call_state *dce_call,
1108                                 TALLOC_CTX *mem_ctx,
1109                                 struct lsa_LookupSids3 *r)
1110 {
1111         struct lsa_policy_state *state;
1112         int i;
1113         NTSTATUS status = NT_STATUS_OK;
1114
1115         r->out.domains = NULL;
1116
1117         status = lsa_get_policy_state(dce_call, mem_ctx, &state);
1118         if (!NT_STATUS_IS_OK(status)) {
1119                 return status;
1120         }
1121
1122         r->out.domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
1123         if (r->out.domains == NULL) {
1124                 return NT_STATUS_NO_MEMORY;
1125         }
1126
1127         r->out.names = talloc_zero(mem_ctx,  struct lsa_TransNameArray2);
1128         if (r->out.names == NULL) {
1129                 return NT_STATUS_NO_MEMORY;
1130         }
1131
1132         *r->out.count = 0;
1133
1134         r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName2, 
1135                                              r->in.sids->num_sids);
1136         if (r->out.names->names == NULL) {
1137                 return NT_STATUS_NO_MEMORY;
1138         }
1139
1140         for (i=0;i<r->in.sids->num_sids;i++) {
1141                 struct dom_sid *sid = r->in.sids->sids[i].sid;
1142                 char *sid_str = dom_sid_string(mem_ctx, sid);
1143                 const char *name;
1144                 uint32_t atype, rtype, sid_index;
1145                 NTSTATUS status2;
1146
1147                 r->out.names->count++;
1148                 (*r->out.count)++;
1149
1150                 r->out.names->names[i].sid_type    = SID_NAME_UNKNOWN;
1151                 r->out.names->names[i].name.string = sid_str;
1152                 r->out.names->names[i].sid_index   = 0xFFFFFFFF;
1153                 r->out.names->names[i].unknown     = 0;
1154
1155                 if (sid_str == NULL) {
1156                         r->out.names->names[i].name.string = "(SIDERROR)";
1157                         status = STATUS_SOME_UNMAPPED;
1158                         continue;
1159                 }
1160
1161                 /* work out the authority name */
1162                 status2 = lsa_authority_list(state, mem_ctx, sid, r->out.domains, &sid_index);
1163                 if (!NT_STATUS_IS_OK(status2)) {
1164                         return status2;
1165                 }
1166
1167                 status2 = lsa_lookup_sid(state, mem_ctx, sid, sid_str, 
1168                                          &name, &atype);
1169                 if (!NT_STATUS_IS_OK(status2)) {
1170                         status = STATUS_SOME_UNMAPPED;
1171                         continue;
1172                 }
1173
1174                 rtype = samdb_atype_map(atype);
1175                 if (rtype == SID_NAME_UNKNOWN) {
1176                         status = STATUS_SOME_UNMAPPED;
1177                         continue;
1178                 }
1179
1180                 r->out.names->names[i].sid_type    = rtype;
1181                 r->out.names->names[i].name.string = name;
1182                 r->out.names->names[i].sid_index   = sid_index;
1183                 r->out.names->names[i].unknown     = 0;
1184         }
1185         
1186         return status;
1187 }
1188
1189
1190 /*
1191   lsa_LookupSids2
1192 */
1193 static NTSTATUS lsa_LookupSids2(struct dcesrv_call_state *dce_call,
1194                                 TALLOC_CTX *mem_ctx,
1195                                 struct lsa_LookupSids2 *r)
1196 {
1197         struct lsa_LookupSids3 r3;
1198         NTSTATUS status;
1199
1200         r3.in.sids     = r->in.sids;
1201         r3.in.names    = r->in.names;
1202         r3.in.level    = r->in.level;
1203         r3.in.count    = r->in.count;
1204         r3.in.unknown1 = r->in.unknown1;
1205         r3.in.unknown2 = r->in.unknown2;
1206         r3.out.count   = r->out.count;
1207         r3.out.names   = r->out.names;
1208
1209         status = lsa_LookupSids3(dce_call, mem_ctx, &r3);
1210         if (dce_call->fault_code != 0) {
1211                 return status;
1212         }
1213
1214         r->out.domains = r3.out.domains;
1215         r->out.names   = r3.out.names;
1216         r->out.count   = r3.out.count;
1217
1218         return status;
1219 }
1220
1221
1222 /* 
1223   lsa_LookupSids 
1224 */
1225 static NTSTATUS lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1226                                struct lsa_LookupSids *r)
1227 {
1228         struct lsa_LookupSids3 r3;
1229         NTSTATUS status;
1230         int i;
1231
1232         r3.in.sids     = r->in.sids;
1233         r3.in.names    = NULL;
1234         r3.in.level    = r->in.level;
1235         r3.in.count    = r->in.count;
1236         r3.in.unknown1 = 0;
1237         r3.in.unknown2 = 0;
1238         r3.out.count   = r->out.count;
1239         r3.out.names   = NULL;
1240
1241         status = lsa_LookupSids3(dce_call, mem_ctx, &r3);
1242         if (dce_call->fault_code != 0) {
1243                 return status;
1244         }
1245
1246         r->out.domains = r3.out.domains;
1247         if (!r3.out.names) {
1248                 r->out.names = NULL;
1249                 return status;
1250         }
1251
1252         r->out.names = talloc(mem_ctx, struct lsa_TransNameArray);
1253         if (r->out.names == NULL) {
1254                 return NT_STATUS_NO_MEMORY;
1255         }
1256         r->out.names->count = r3.out.names->count;
1257         r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName, 
1258                                              r->out.names->count);
1259         if (r->out.names->names == NULL) {
1260                 return NT_STATUS_NO_MEMORY;
1261         }
1262         for (i=0;i<r->out.names->count;i++) {
1263                 r->out.names->names[i].sid_type    = r3.out.names->names[i].sid_type;
1264                 r->out.names->names[i].name.string = r3.out.names->names[i].name.string;
1265                 r->out.names->names[i].sid_index   = r3.out.names->names[i].sid_index;
1266         }
1267
1268         return status;
1269 }
1270
1271
1272 /* 
1273   lsa_OpenAccount 
1274 */
1275 static NTSTATUS lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1276                                 struct lsa_OpenAccount *r)
1277 {
1278         struct dcesrv_handle *h, *ah;
1279         struct lsa_policy_state *state;
1280         struct lsa_account_state *astate;
1281
1282         ZERO_STRUCTP(r->out.acct_handle);
1283
1284         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
1285
1286         state = h->data;
1287
1288         astate = talloc(dce_call->conn, struct lsa_account_state);
1289         if (astate == NULL) {
1290                 return NT_STATUS_NO_MEMORY;
1291         }
1292
1293         astate->account_sid = dom_sid_dup(astate, r->in.sid);
1294         if (astate->account_sid == NULL) {
1295                 talloc_free(astate);
1296                 return NT_STATUS_NO_MEMORY;
1297         }
1298         
1299         /* check it really exists */
1300         astate->account_dn = samdb_search_dn(state->sam_ldb, astate,
1301                                              NULL, "(&(objectSid=%s)(objectClass=group))", 
1302                                              ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid));
1303         if (astate->account_dn == NULL) {
1304                 talloc_free(astate);
1305                 return NT_STATUS_NO_SUCH_USER;
1306         }
1307         
1308         astate->policy = talloc_reference(astate, state);
1309         astate->access_mask = r->in.access_mask;
1310
1311         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
1312         if (!ah) {
1313                 talloc_free(astate);
1314                 return NT_STATUS_NO_MEMORY;
1315         }
1316
1317         ah->data = talloc_steal(ah, astate);
1318
1319         *r->out.acct_handle = ah->wire_handle;
1320
1321         return NT_STATUS_OK;
1322 }
1323
1324
1325 /* 
1326   lsa_EnumPrivsAccount 
1327 */
1328 static NTSTATUS lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call, 
1329                                      TALLOC_CTX *mem_ctx,
1330                                      struct lsa_EnumPrivsAccount *r)
1331 {
1332         struct dcesrv_handle *h;
1333         struct lsa_account_state *astate;
1334         int ret, i;
1335         struct ldb_message **res;
1336         const char * const attrs[] = { "privilege", NULL};
1337         struct ldb_message_element *el;
1338
1339         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
1340
1341         astate = h->data;
1342
1343         r->out.privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
1344         r->out.privs->count = 0;
1345         r->out.privs->unknown = 0;
1346         r->out.privs->set = NULL;
1347
1348         ret = gendb_search_dn(astate->policy->sam_ldb, mem_ctx,
1349                               astate->account_dn, &res, attrs);
1350         if (ret != 1) {
1351                 return NT_STATUS_OK;
1352         }
1353
1354         el = ldb_msg_find_element(res[0], "privilege");
1355         if (el == NULL || el->num_values == 0) {
1356                 return NT_STATUS_OK;
1357         }
1358
1359         r->out.privs->set = talloc_array(r->out.privs, 
1360                                            struct lsa_LUIDAttribute, el->num_values);
1361         if (r->out.privs->set == NULL) {
1362                 return NT_STATUS_NO_MEMORY;
1363         }
1364
1365         for (i=0;i<el->num_values;i++) {
1366                 int id = sec_privilege_id((const char *)el->values[i].data);
1367                 if (id == -1) {
1368                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1369                 }
1370                 r->out.privs->set[i].attribute = 0;
1371                 r->out.privs->set[i].luid.low = id;
1372                 r->out.privs->set[i].luid.high = 0;
1373         }
1374
1375         r->out.privs->count = el->num_values;
1376
1377         return NT_STATUS_OK;
1378 }
1379
1380 /* 
1381   lsa_EnumAccountRights 
1382 */
1383 static NTSTATUS lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, 
1384                                       TALLOC_CTX *mem_ctx,
1385                                       struct lsa_EnumAccountRights *r)
1386 {
1387         struct dcesrv_handle *h;
1388         struct lsa_policy_state *state;
1389         int ret, i;
1390         struct ldb_message **res;
1391         const char * const attrs[] = { "privilege", NULL};
1392         const char *sidstr;
1393         struct ldb_message_element *el;
1394
1395         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
1396
1397         state = h->data;
1398
1399         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
1400         if (sidstr == NULL) {
1401                 return NT_STATUS_NO_MEMORY;
1402         }
1403
1404         ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, 
1405                            "objectSid=%s", sidstr);
1406         if (ret != 1) {
1407                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1408         }
1409
1410         el = ldb_msg_find_element(res[0], "privilege");
1411         if (el == NULL || el->num_values == 0) {
1412                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1413         }
1414
1415         r->out.rights->count = el->num_values;
1416         r->out.rights->names = talloc_array(r->out.rights, 
1417                                               struct lsa_String, r->out.rights->count);
1418         if (r->out.rights->names == NULL) {
1419                 return NT_STATUS_NO_MEMORY;
1420         }
1421
1422         for (i=0;i<el->num_values;i++) {
1423                 r->out.rights->names[i].string = (const char *)el->values[i].data;
1424         }
1425
1426         return NT_STATUS_OK;
1427 }
1428
1429
1430
1431 /* 
1432   helper for lsa_AddAccountRights and lsa_RemoveAccountRights
1433 */
1434 static NTSTATUS lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, 
1435                                            TALLOC_CTX *mem_ctx,
1436                                            struct lsa_policy_state *state,
1437                                            int ldb_flag,
1438                                            struct dom_sid *sid,
1439                                            const struct lsa_RightSet *rights)
1440 {
1441         const char *sidstr;
1442         struct ldb_message *msg;
1443         struct ldb_message_element el;
1444         int i, ret;
1445         struct lsa_EnumAccountRights r2;
1446
1447         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, sid);
1448         if (sidstr == NULL) {
1449                 return NT_STATUS_NO_MEMORY;
1450         }
1451
1452         msg = ldb_msg_new(mem_ctx);
1453         if (msg == NULL) {
1454                 return NT_STATUS_NO_MEMORY;
1455         }
1456
1457         msg->dn = samdb_search_dn(state->sam_ldb, mem_ctx, NULL, "objectSid=%s", sidstr);
1458         if (msg->dn == NULL) {
1459                 return NT_STATUS_NO_SUCH_USER;
1460         }
1461
1462         if (ldb_msg_add_empty(msg, "privilege", ldb_flag)) {
1463                 return NT_STATUS_NO_MEMORY;
1464         }
1465
1466         if (ldb_flag == LDB_FLAG_MOD_ADD) {
1467                 NTSTATUS status;
1468
1469                 r2.in.handle = &state->handle->wire_handle;
1470                 r2.in.sid = sid;
1471                 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
1472
1473                 status = lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
1474                 if (!NT_STATUS_IS_OK(status)) {
1475                         ZERO_STRUCTP(r2.out.rights);
1476                 }
1477         }
1478
1479         el.num_values = 0;
1480         el.values = talloc_array(mem_ctx, struct ldb_val, rights->count);
1481         if (el.values == NULL) {
1482                 return NT_STATUS_NO_MEMORY;
1483         }
1484         for (i=0;i<rights->count;i++) {
1485                 if (sec_privilege_id(rights->names[i].string) == -1) {
1486                         return NT_STATUS_NO_SUCH_PRIVILEGE;
1487                 }
1488
1489                 if (ldb_flag == LDB_FLAG_MOD_ADD) {
1490                         int j;
1491                         for (j=0;j<r2.out.rights->count;j++) {
1492                                 if (strcasecmp_m(r2.out.rights->names[j].string, 
1493                                                rights->names[i].string) == 0) {
1494                                         break;
1495                                 }
1496                         }
1497                         if (j != r2.out.rights->count) continue;
1498                 }
1499
1500
1501                 el.values[el.num_values].length = strlen(rights->names[i].string);
1502                 el.values[el.num_values].data = (uint8_t *)talloc_strdup(mem_ctx, rights->names[i].string);
1503                 if (el.values[el.num_values].data == NULL) {
1504                         return NT_STATUS_NO_MEMORY;
1505                 }
1506                 el.num_values++;
1507         }
1508
1509         if (el.num_values == 0) {
1510                 return NT_STATUS_OK;
1511         }
1512
1513         ret = samdb_modify(state->sam_ldb, mem_ctx, msg);
1514         if (ret != 0) {
1515                 if (ldb_flag == LDB_FLAG_MOD_DELETE) {
1516                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1517                 }
1518                 return NT_STATUS_UNEXPECTED_IO_ERROR;
1519         }
1520
1521         return NT_STATUS_OK;
1522 }
1523
1524 /* 
1525   lsa_AddPrivilegesToAccount
1526 */
1527 static NTSTATUS lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1528                                            struct lsa_AddPrivilegesToAccount *r)
1529 {
1530         struct lsa_RightSet rights;
1531         struct dcesrv_handle *h;
1532         struct lsa_account_state *astate;
1533         int i;
1534
1535         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
1536
1537         astate = h->data;
1538
1539         rights.count = r->in.privs->count;
1540         rights.names = talloc_array(mem_ctx, struct lsa_String, rights.count);
1541         if (rights.names == NULL) {
1542                 return NT_STATUS_NO_MEMORY;
1543         }
1544         for (i=0;i<rights.count;i++) {
1545                 int id = r->in.privs->set[i].luid.low;
1546                 if (r->in.privs->set[i].luid.high) {
1547                         return NT_STATUS_NO_SUCH_PRIVILEGE;
1548                 }
1549                 rights.names[i].string = sec_privilege_name(id);
1550                 if (rights.names[i].string == NULL) {
1551                         return NT_STATUS_NO_SUCH_PRIVILEGE;
1552                 }
1553         }
1554
1555         return lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
1556                                           LDB_FLAG_MOD_ADD, astate->account_sid,
1557                                           &rights);
1558 }
1559
1560
1561 /* 
1562   lsa_RemovePrivilegesFromAccount
1563 */
1564 static NTSTATUS lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1565                                                 struct lsa_RemovePrivilegesFromAccount *r)
1566 {
1567         struct lsa_RightSet *rights;
1568         struct dcesrv_handle *h;
1569         struct lsa_account_state *astate;
1570         int i;
1571
1572         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
1573
1574         astate = h->data;
1575
1576         rights = talloc(mem_ctx, struct lsa_RightSet);
1577
1578         if (r->in.remove_all == 1 && 
1579             r->in.privs == NULL) {
1580                 struct lsa_EnumAccountRights r2;
1581                 NTSTATUS status;
1582
1583                 r2.in.handle = &astate->policy->handle->wire_handle;
1584                 r2.in.sid = astate->account_sid;
1585                 r2.out.rights = rights;
1586
1587                 status = lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
1588                 if (!NT_STATUS_IS_OK(status)) {
1589                         return status;
1590                 }
1591
1592                 return lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
1593                                                   LDB_FLAG_MOD_DELETE, astate->account_sid,
1594                                                   r2.out.rights);
1595         }
1596
1597         if (r->in.remove_all != 0) {
1598                 return NT_STATUS_INVALID_PARAMETER;
1599         }
1600
1601         rights->count = r->in.privs->count;
1602         rights->names = talloc_array(mem_ctx, struct lsa_String, rights->count);
1603         if (rights->names == NULL) {
1604                 return NT_STATUS_NO_MEMORY;
1605         }
1606         for (i=0;i<rights->count;i++) {
1607                 int id = r->in.privs->set[i].luid.low;
1608                 if (r->in.privs->set[i].luid.high) {
1609                         return NT_STATUS_NO_SUCH_PRIVILEGE;
1610                 }
1611                 rights->names[i].string = sec_privilege_name(id);
1612                 if (rights->names[i].string == NULL) {
1613                         return NT_STATUS_NO_SUCH_PRIVILEGE;
1614                 }
1615         }
1616
1617         return lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
1618                                           LDB_FLAG_MOD_DELETE, astate->account_sid,
1619                                           rights);
1620 }
1621
1622
1623 /* 
1624   lsa_GetQuotasForAccount
1625 */
1626 static NTSTATUS lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1627                        struct lsa_GetQuotasForAccount *r)
1628 {
1629         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1630 }
1631
1632
1633 /* 
1634   lsa_SetQuotasForAccount
1635 */
1636 static NTSTATUS lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1637                        struct lsa_SetQuotasForAccount *r)
1638 {
1639         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1640 }
1641
1642
1643 /* 
1644   lsa_GetSystemAccessAccount
1645 */
1646 static NTSTATUS lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1647                        struct lsa_GetSystemAccessAccount *r)
1648 {
1649         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1650 }
1651
1652
1653 /* 
1654   lsa_SetSystemAccessAccount
1655 */
1656 static NTSTATUS lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1657                        struct lsa_SetSystemAccessAccount *r)
1658 {
1659         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1660 }
1661
1662
1663 /* 
1664   lsa_CreateSecret 
1665 */
1666 static NTSTATUS lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1667                                  struct lsa_CreateSecret *r)
1668 {
1669         struct dcesrv_handle *policy_handle;
1670         struct lsa_policy_state *policy_state;
1671         struct lsa_secret_state *secret_state;
1672         struct dcesrv_handle *handle;
1673         struct ldb_message **msgs, *msg;
1674         const char *attrs[] = {
1675                 NULL
1676         };
1677
1678         const char *name;
1679
1680         int ret;
1681
1682         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1683         ZERO_STRUCTP(r->out.sec_handle);
1684         
1685         policy_state = policy_handle->data;
1686
1687         if (!r->in.name.string) {
1688                 return NT_STATUS_INVALID_PARAMETER;
1689         }
1690         
1691         secret_state = talloc(mem_ctx, struct lsa_secret_state);
1692         if (!secret_state) {
1693                 return NT_STATUS_NO_MEMORY;
1694         }
1695         secret_state->policy = policy_state;
1696
1697         msg = ldb_msg_new(mem_ctx);
1698         if (msg == NULL) {
1699                 return NT_STATUS_NO_MEMORY;
1700         }
1701
1702         if (strncmp("G$", r->in.name.string, 2) == 0) {
1703                 const char *name2;
1704                 name = &r->in.name.string[2];
1705                 secret_state->sam_ldb = talloc_reference(secret_state, policy_state->sam_ldb);
1706                 secret_state->global = True;
1707
1708                 if (strlen(name) < 1) {
1709                         return NT_STATUS_INVALID_PARAMETER;
1710                 }
1711
1712                 name2 = talloc_asprintf(mem_ctx, "%s Secret", name);
1713                 /* search for the secret record */
1714                 ret = gendb_search(secret_state->sam_ldb,
1715                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
1716                                    "(&(cn=%s)(objectclass=secret))", 
1717                                    name2);
1718                 if (ret > 0) {
1719                         return NT_STATUS_OBJECT_NAME_COLLISION;
1720                 }
1721                 
1722                 if (ret < 0 || ret > 1) {
1723                         DEBUG(0,("Found %d records matching DN %s\n", ret,
1724                                  ldb_dn_linearize(mem_ctx, policy_state->system_dn)));
1725                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1726                 }
1727
1728                 msg->dn = ldb_dn_build_child(mem_ctx, "cn", name2, policy_state->system_dn);
1729                 if (!name2 || !msg->dn) {
1730                         return NT_STATUS_NO_MEMORY;
1731                 }
1732                 
1733                 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name2);
1734         
1735         } else {
1736                 secret_state->global = False;
1737
1738                 name = r->in.name.string;
1739                 if (strlen(name) < 1) {
1740                         return NT_STATUS_INVALID_PARAMETER;
1741                 }
1742
1743                 secret_state->sam_ldb = talloc_reference(secret_state, secrets_db_connect(mem_ctx));
1744                 /* search for the secret record */
1745                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
1746                                    ldb_dn_explode(mem_ctx, "cn=LSA Secrets"),
1747                                    &msgs, attrs,
1748                                    "(&(cn=%s)(objectclass=secret))", name);
1749                 if (ret > 0) {
1750                         return NT_STATUS_OBJECT_NAME_COLLISION;
1751                 }
1752                 
1753                 if (ret < 0 || ret > 1) {
1754                         DEBUG(0,("Found %d records matching DN %s\n", ret,
1755                                  ldb_dn_linearize(mem_ctx, policy_state->system_dn)));
1756                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1757                 }
1758
1759                 msg->dn = ldb_dn_string_compose(mem_ctx, NULL, "cn=%s,cn=LSA Secrets", name);
1760                 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name);
1761         } 
1762
1763         /* pull in all the template attributes.  Note this is always from the global samdb */
1764         ret = samdb_copy_template(secret_state->policy->sam_ldb, mem_ctx, msg, 
1765                                   "(&(name=TemplateSecret)(objectclass=secretTemplate))");
1766         if (ret != 0) {
1767                 DEBUG(0,("Failed to load TemplateSecret from samdb\n"));
1768                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1769         }
1770
1771         samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "objectClass", "secret");
1772         
1773         secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
1774
1775         /* create the secret */
1776         ret = samdb_add(secret_state->sam_ldb, mem_ctx, msg);
1777         if (ret != 0) {
1778                 DEBUG(0,("Failed to create secret record %s\n",
1779                          ldb_dn_linearize(mem_ctx, msg->dn)));
1780                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1781         }
1782
1783         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
1784         if (!handle) {
1785                 return NT_STATUS_NO_MEMORY;
1786         }
1787         
1788         handle->data = talloc_steal(handle, secret_state);
1789         
1790         secret_state->access_mask = r->in.access_mask;
1791         secret_state->policy = talloc_reference(secret_state, policy_state);
1792         
1793         *r->out.sec_handle = handle->wire_handle;
1794         
1795         return NT_STATUS_OK;
1796 }
1797
1798
1799 /* 
1800   lsa_OpenSecret 
1801 */
1802 static NTSTATUS lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1803                                struct lsa_OpenSecret *r)
1804 {
1805         struct dcesrv_handle *policy_handle;
1806         
1807         struct lsa_policy_state *policy_state;
1808         struct lsa_secret_state *secret_state;
1809         struct dcesrv_handle *handle;
1810         struct ldb_message **msgs;
1811         const char *attrs[] = {
1812                 NULL
1813         };
1814
1815         const char *name;
1816
1817         int ret;
1818
1819         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1820         ZERO_STRUCTP(r->out.sec_handle);
1821         policy_state = policy_handle->data;
1822
1823         if (!r->in.name.string) {
1824                 return NT_STATUS_INVALID_PARAMETER;
1825         }
1826         
1827         secret_state = talloc(mem_ctx, struct lsa_secret_state);
1828         if (!secret_state) {
1829                 return NT_STATUS_NO_MEMORY;
1830         }
1831         secret_state->policy = policy_state;
1832
1833         if (strncmp("G$", r->in.name.string, 2) == 0) {
1834                 name = &r->in.name.string[2];
1835                 secret_state->sam_ldb = talloc_reference(secret_state, policy_state->sam_ldb);
1836                 secret_state->global = True;
1837
1838                 if (strlen(name) < 1) {
1839                         return NT_STATUS_INVALID_PARAMETER;
1840                 }
1841
1842                 /* search for the secret record */
1843                 ret = gendb_search(secret_state->sam_ldb,
1844                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
1845                                    "(&(cn=%s Secret)(objectclass=secret))", 
1846                                    name);
1847                 if (ret == 0) {
1848                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1849                 }
1850                 
1851                 if (ret != 1) {
1852                         DEBUG(0,("Found %d records matching DN %s\n", ret,
1853                                  ldb_dn_linearize(mem_ctx, policy_state->system_dn)));
1854                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1855                 }
1856         
1857         } else {
1858                 secret_state->sam_ldb = talloc_reference(secret_state, secrets_db_connect(mem_ctx));
1859
1860                 secret_state->global = False;
1861                 name = r->in.name.string;
1862                 if (strlen(name) < 1) {
1863                         return NT_STATUS_INVALID_PARAMETER;
1864                 }
1865
1866                 /* search for the secret record */
1867                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
1868                                    ldb_dn_explode(mem_ctx, "cn=LSA Secrets"),
1869                                    &msgs, attrs,
1870                                    "(&(cn=%s)(objectclass=secret))", name);
1871                 if (ret == 0) {
1872                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1873                 }
1874                 
1875                 if (ret != 1) {
1876                         DEBUG(0,("Found %d records matching DN %s\n", ret,
1877                                  ldb_dn_linearize(mem_ctx, policy_state->system_dn)));
1878                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1879                 }
1880         } 
1881
1882         secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
1883         
1884         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
1885         if (!handle) {
1886                 return NT_STATUS_NO_MEMORY;
1887         }
1888         
1889         handle->data = talloc_steal(handle, secret_state);
1890         
1891         secret_state->access_mask = r->in.access_mask;
1892         secret_state->policy = talloc_reference(secret_state, policy_state);
1893         
1894         *r->out.sec_handle = handle->wire_handle;
1895         
1896         return NT_STATUS_OK;
1897 }
1898
1899
1900 /* 
1901   lsa_SetSecret 
1902 */
1903 static NTSTATUS lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1904                               struct lsa_SetSecret *r)
1905 {
1906
1907         struct dcesrv_handle *h;
1908         struct lsa_secret_state *secret_state;
1909         struct ldb_message *msg;
1910         DATA_BLOB session_key;
1911         DATA_BLOB crypt_secret, secret;
1912         struct ldb_val val;
1913         int ret;
1914         NTSTATUS status = NT_STATUS_OK;
1915
1916         struct timeval now = timeval_current();
1917         NTTIME nt_now = timeval_to_nttime(&now);
1918
1919         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
1920
1921         secret_state = h->data;
1922
1923         msg = ldb_msg_new(mem_ctx);
1924         if (msg == NULL) {
1925                 return NT_STATUS_NO_MEMORY;
1926         }
1927
1928         msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
1929         if (!msg->dn) {
1930                 return NT_STATUS_NO_MEMORY;
1931         }
1932         status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
1933         if (!NT_STATUS_IS_OK(status)) {
1934                 return status;
1935         }
1936
1937         if (r->in.old_val) {
1938                 /* Decrypt */
1939                 crypt_secret.data = r->in.old_val->data;
1940                 crypt_secret.length = r->in.old_val->size;
1941                 
1942                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
1943                 if (!NT_STATUS_IS_OK(status)) {
1944                         return status;
1945                 }
1946                 
1947                 val.data = secret.data;
1948                 val.length = secret.length;
1949                 
1950                 /* set value */
1951                 if (samdb_msg_add_value(secret_state->sam_ldb, 
1952                                         mem_ctx, msg, "priorSecret", &val) != 0) {
1953                         return NT_STATUS_NO_MEMORY; 
1954                 }
1955                 
1956                 /* set old value mtime */
1957                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
1958                                          mem_ctx, msg, "priorSetTime", nt_now) != 0) { 
1959                         return NT_STATUS_NO_MEMORY; 
1960                 }
1961
1962                 if (!r->in.new_val) {
1963                         /* This behaviour varies depending of if this is a local, or a global secret... */
1964                         if (secret_state->global) {
1965                                 /* set old value mtime */
1966                                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
1967                                                          mem_ctx, msg, "lastSetTime", nt_now) != 0) { 
1968                                         return NT_STATUS_NO_MEMORY; 
1969                                 }
1970                         } else {
1971                                 if (samdb_msg_add_delete(secret_state->sam_ldb, 
1972                                                          mem_ctx, msg, "secret")) {
1973                                         return NT_STATUS_NO_MEMORY;
1974                                 }
1975                                 if (samdb_msg_add_delete(secret_state->sam_ldb, 
1976                                                          mem_ctx, msg, "lastSetTime")) {
1977                                         return NT_STATUS_NO_MEMORY;
1978                                 }
1979                         }
1980                 }
1981         }
1982
1983         if (r->in.new_val) {
1984                 /* Decrypt */
1985                 crypt_secret.data = r->in.new_val->data;
1986                 crypt_secret.length = r->in.new_val->size;
1987                 
1988                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
1989                 if (!NT_STATUS_IS_OK(status)) {
1990                         return status;
1991                 }
1992                 
1993                 val.data = secret.data;
1994                 val.length = secret.length;
1995                 
1996                 /* set value */
1997                 if (samdb_msg_add_value(secret_state->sam_ldb, 
1998                                         mem_ctx, msg, "secret", &val) != 0) {
1999                         return NT_STATUS_NO_MEMORY; 
2000                 }
2001                 
2002                 /* set new value mtime */
2003                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2004                                          mem_ctx, msg, "lastSetTime", nt_now) != 0) { 
2005                         return NT_STATUS_NO_MEMORY; 
2006                 }
2007                 
2008                 /* If the old value is not set, then migrate the
2009                  * current value to the old value */
2010                 if (!r->in.old_val) {
2011                         const struct ldb_val *new_val;
2012                         NTTIME last_set_time;
2013                         struct ldb_message **res;
2014                         const char *attrs[] = {
2015                                 "secret",
2016                                 "lastSetTime",
2017                                 NULL
2018                         };
2019                         
2020                         /* search for the secret record */
2021                         ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
2022                                               secret_state->secret_dn, &res, attrs);
2023                         if (ret == 0) {
2024                                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2025                         }
2026                         
2027                         if (ret != 1) {
2028                                 DEBUG(0,("Found %d records matching dn=%s\n", ret,
2029                                          ldb_dn_linearize(mem_ctx, secret_state->secret_dn)));
2030                                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2031                         }
2032
2033                         new_val = ldb_msg_find_ldb_val(res[0], "secret");
2034                         last_set_time = ldb_msg_find_uint64(res[0], "lastSetTime", 0);
2035                         
2036                         if (new_val) {
2037                                 /* set value */
2038                                 if (samdb_msg_add_value(secret_state->sam_ldb, 
2039                                                         mem_ctx, msg, "priorSecret", 
2040                                                         new_val) != 0) {
2041                                         return NT_STATUS_NO_MEMORY; 
2042                                 }
2043                         }
2044                         
2045                         /* set new value mtime */
2046                         if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
2047                                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2048                                                          mem_ctx, msg, "priorSetTime", last_set_time) != 0) { 
2049                                         return NT_STATUS_NO_MEMORY; 
2050                                 }
2051                         }
2052                 }
2053         }
2054
2055         /* modify the samdb record */
2056         ret = samdb_replace(secret_state->sam_ldb, mem_ctx, msg);
2057         if (ret != 0) {
2058                 /* we really need samdb.c to return NTSTATUS */
2059                 return NT_STATUS_UNSUCCESSFUL;
2060         }
2061
2062         return NT_STATUS_OK;
2063 }
2064
2065
2066 /* 
2067   lsa_QuerySecret 
2068 */
2069 static NTSTATUS lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2070                                 struct lsa_QuerySecret *r)
2071 {
2072         struct dcesrv_handle *h;
2073         struct lsa_secret_state *secret_state;
2074         struct ldb_message *msg;
2075         DATA_BLOB session_key;
2076         DATA_BLOB crypt_secret, secret;
2077         int ret;
2078         struct ldb_message **res;
2079         const char *attrs[] = {
2080                 "secret",
2081                 "priorSecret",
2082                 "lastSetTime",
2083                 "priorSetTime", 
2084                 NULL
2085         };
2086
2087         NTSTATUS nt_status;
2088
2089         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
2090
2091         secret_state = h->data;
2092
2093         /* pull all the user attributes */
2094         ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
2095                               secret_state->secret_dn, &res, attrs);
2096         if (ret != 1) {
2097                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2098         }
2099         msg = res[0];
2100         
2101         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
2102         if (!NT_STATUS_IS_OK(nt_status)) {
2103                 return nt_status;
2104         }
2105         
2106         if (r->in.old_val) {
2107                 const struct ldb_val *prior_val;
2108                 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
2109                 if (!r->out.old_val) {
2110                         return NT_STATUS_NO_MEMORY;
2111                 }
2112                 /* Decrypt */
2113                 prior_val = ldb_msg_find_ldb_val(res[0], "priorSecret");
2114                 
2115                 if (prior_val && prior_val->length) {
2116                         secret.data = prior_val->data;
2117                         secret.length = prior_val->length;
2118                 
2119                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
2120                         if (!crypt_secret.length) {
2121                                 return NT_STATUS_NO_MEMORY;
2122                         }
2123                         r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
2124                         if (!r->out.old_val->buf) {
2125                                 return NT_STATUS_NO_MEMORY;
2126                         }
2127                         r->out.old_val->buf->size = crypt_secret.length;
2128                         r->out.old_val->buf->length = crypt_secret.length;
2129                         r->out.old_val->buf->data = crypt_secret.data;
2130                 }
2131         }
2132         
2133         if (r->in.old_mtime) {
2134                 r->out.old_mtime = talloc(mem_ctx, NTTIME);
2135                 if (!r->out.old_mtime) {
2136                         return NT_STATUS_NO_MEMORY;
2137                 }
2138                 *r->out.old_mtime = ldb_msg_find_uint64(res[0], "priorSetTime", 0);
2139         }
2140         
2141         if (r->in.new_val) {
2142                 const struct ldb_val *new_val;
2143                 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
2144                 if (!r->out.new_val) {
2145                         return NT_STATUS_NO_MEMORY;
2146                 }
2147
2148                 /* Decrypt */
2149                 new_val = ldb_msg_find_ldb_val(res[0], "secret");
2150                 
2151                 if (new_val && new_val->length) {
2152                         secret.data = new_val->data;
2153                         secret.length = new_val->length;
2154                 
2155                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
2156                         if (!crypt_secret.length) {
2157                                 return NT_STATUS_NO_MEMORY;
2158                         }
2159                         r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
2160                         if (!r->out.new_val->buf) {
2161                                 return NT_STATUS_NO_MEMORY;
2162                         }
2163                         r->out.new_val->buf->length = crypt_secret.length;
2164                         r->out.new_val->buf->size = crypt_secret.length;
2165                         r->out.new_val->buf->data = crypt_secret.data;
2166                 }
2167         }
2168         
2169         if (r->in.new_mtime) {
2170                 r->out.new_mtime = talloc(mem_ctx, NTTIME);
2171                 if (!r->out.new_mtime) {
2172                         return NT_STATUS_NO_MEMORY;
2173                 }
2174                 *r->out.new_mtime = ldb_msg_find_uint64(res[0], "lastSetTime", 0);
2175         }
2176         
2177         return NT_STATUS_OK;
2178 }
2179
2180
2181 /* 
2182   lsa_LookupPrivValue
2183 */
2184 static NTSTATUS lsa_LookupPrivValue(struct dcesrv_call_state *dce_call, 
2185                                     TALLOC_CTX *mem_ctx,
2186                                     struct lsa_LookupPrivValue *r)
2187 {
2188         struct dcesrv_handle *h;
2189         struct lsa_policy_state *state;
2190         int id;
2191
2192         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2193
2194         state = h->data;
2195
2196         id = sec_privilege_id(r->in.name->string);
2197         if (id == -1) {
2198                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2199         }
2200
2201         r->out.luid->low = id;
2202         r->out.luid->high = 0;
2203
2204         return NT_STATUS_OK;    
2205 }
2206
2207
2208 /* 
2209   lsa_LookupPrivName 
2210 */
2211 static NTSTATUS lsa_LookupPrivName(struct dcesrv_call_state *dce_call, 
2212                                    TALLOC_CTX *mem_ctx,
2213                                    struct lsa_LookupPrivName *r)
2214 {
2215         struct dcesrv_handle *h;
2216         struct lsa_policy_state *state;
2217         const char *privname;
2218
2219         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2220
2221         state = h->data;
2222
2223         if (r->in.luid->high != 0) {
2224                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2225         }
2226
2227         privname = sec_privilege_name(r->in.luid->low);
2228         if (privname == NULL) {
2229                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2230         }
2231
2232         r->out.name = talloc(mem_ctx, struct lsa_String);
2233         if (r->out.name == NULL) {
2234                 return NT_STATUS_NO_MEMORY;
2235         }
2236         r->out.name->string = privname;
2237
2238         return NT_STATUS_OK;    
2239 }
2240
2241
2242 /* 
2243   lsa_LookupPrivDisplayName
2244 */
2245 static NTSTATUS lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call, 
2246                                           TALLOC_CTX *mem_ctx,
2247                                           struct lsa_LookupPrivDisplayName *r)
2248 {
2249         struct dcesrv_handle *h;
2250         struct lsa_policy_state *state;
2251         int id;
2252
2253         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2254
2255         state = h->data;
2256
2257         id = sec_privilege_id(r->in.name->string);
2258         if (id == -1) {
2259                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2260         }
2261         
2262         r->out.disp_name = talloc(mem_ctx, struct lsa_String);
2263         if (r->out.disp_name == NULL) {
2264                 return NT_STATUS_NO_MEMORY;
2265         }
2266
2267         r->out.disp_name->string = sec_privilege_display_name(id, r->in.language_id);
2268         if (r->out.disp_name->string == NULL) {
2269                 return NT_STATUS_INTERNAL_ERROR;
2270         }
2271
2272         return NT_STATUS_OK;
2273 }
2274
2275
2276 /* 
2277   lsa_DeleteObject
2278 */
2279 static NTSTATUS lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2280                        struct lsa_DeleteObject *r)
2281 {
2282         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2283 }
2284
2285
2286 /* 
2287   lsa_EnumAccountsWithUserRight
2288 */
2289 static NTSTATUS lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call, 
2290                                               TALLOC_CTX *mem_ctx,
2291                                               struct lsa_EnumAccountsWithUserRight *r)
2292 {
2293         struct dcesrv_handle *h;
2294         struct lsa_policy_state *state;
2295         int ret, i;
2296         struct ldb_message **res;
2297         const char * const attrs[] = { "objectSid", NULL};
2298         const char *privname;
2299
2300         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2301
2302         state = h->data;
2303
2304         if (r->in.name == NULL) {
2305                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2306         } 
2307
2308         privname = r->in.name->string;
2309         if (sec_privilege_id(privname) == -1) {
2310                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2311         }
2312
2313         ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, 
2314                            "privilege=%s", privname);
2315         if (ret <= 0) {
2316                 return NT_STATUS_NO_SUCH_USER;
2317         }
2318
2319         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
2320         if (r->out.sids->sids == NULL) {
2321                 return NT_STATUS_NO_MEMORY;
2322         }
2323         for (i=0;i<ret;i++) {
2324                 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
2325                                                                 res[i], "objectSid");
2326                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
2327         }
2328         r->out.sids->num_sids = ret;
2329
2330         return NT_STATUS_OK;
2331 }
2332
2333
2334 /* 
2335   lsa_AddAccountRights
2336 */
2337 static NTSTATUS lsa_AddAccountRights(struct dcesrv_call_state *dce_call, 
2338                                      TALLOC_CTX *mem_ctx,
2339                                      struct lsa_AddAccountRights *r)
2340 {
2341         struct dcesrv_handle *h;
2342         struct lsa_policy_state *state;
2343
2344         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2345
2346         state = h->data;
2347
2348         return lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
2349                                           LDB_FLAG_MOD_ADD,
2350                                           r->in.sid, r->in.rights);
2351 }
2352
2353
2354 /* 
2355   lsa_RemoveAccountRights
2356 */
2357 static NTSTATUS lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call, 
2358                                         TALLOC_CTX *mem_ctx,
2359                                         struct lsa_RemoveAccountRights *r)
2360 {
2361         struct dcesrv_handle *h;
2362         struct lsa_policy_state *state;
2363
2364         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2365
2366         state = h->data;
2367
2368         return lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
2369                                           LDB_FLAG_MOD_DELETE,
2370                                           r->in.sid, r->in.rights);
2371 }
2372
2373
2374 /* 
2375   lsa_StorePrivateData
2376 */
2377 static NTSTATUS lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2378                        struct lsa_StorePrivateData *r)
2379 {
2380         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2381 }
2382
2383
2384 /* 
2385   lsa_RetrievePrivateData
2386 */
2387 static NTSTATUS lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2388                        struct lsa_RetrievePrivateData *r)
2389 {
2390         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2391 }
2392
2393
2394 /* 
2395   lsa_GetUserName
2396 */
2397 static NTSTATUS lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2398                                 struct lsa_GetUserName *r)
2399 {
2400         NTSTATUS status = NT_STATUS_OK;
2401         const char *account_name;
2402         const char *authority_name;
2403         struct lsa_String *_account_name;
2404         struct lsa_StringPointer *_authority_name = NULL;
2405
2406         /* this is what w2k3 does */
2407         r->out.account_name = r->in.account_name;
2408         r->out.authority_name = r->in.authority_name;
2409
2410         if (r->in.account_name && r->in.account_name->string) {
2411                 return NT_STATUS_INVALID_PARAMETER;
2412         }
2413
2414         if (r->in.authority_name &&
2415             r->in.authority_name->string &&
2416             r->in.authority_name->string->string) {
2417                 return NT_STATUS_INVALID_PARAMETER;
2418         }
2419
2420         account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->account_name);
2421         authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->domain_name);
2422
2423         _account_name = talloc(mem_ctx, struct lsa_String);
2424         NTSTATUS_TALLOC_CHECK(_account_name);
2425         _account_name->string = account_name;
2426
2427         if (r->in.authority_name) {
2428                 _authority_name = talloc(mem_ctx, struct lsa_StringPointer);
2429                 NTSTATUS_TALLOC_CHECK(_authority_name);
2430                 _authority_name->string = talloc(mem_ctx, struct lsa_String);
2431                 NTSTATUS_TALLOC_CHECK(_authority_name->string);
2432                 _authority_name->string->string = authority_name;
2433         }
2434
2435         r->out.account_name = _account_name;
2436         r->out.authority_name = _authority_name;
2437
2438         return status;
2439 }
2440
2441 /*
2442   lsa_SetInfoPolicy2
2443 */
2444 static NTSTATUS lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
2445                                    TALLOC_CTX *mem_ctx,
2446                                    struct lsa_SetInfoPolicy2 *r)
2447 {
2448         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2449 }
2450
2451 /*
2452   lsa_QueryDomainInformationPolicy
2453 */
2454 static NTSTATUS lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
2455                                                  TALLOC_CTX *mem_ctx,
2456                                                  struct lsa_QueryDomainInformationPolicy *r)
2457 {
2458         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2459 }
2460
2461 /*
2462   lsa_SetDomInfoPolicy
2463 */
2464 static NTSTATUS lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
2465                                               TALLOC_CTX *mem_ctx,
2466                                               struct lsa_SetDomainInformationPolicy *r)
2467 {
2468         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2469 }
2470
2471 /*
2472   lsa_TestCall
2473 */
2474 static NTSTATUS lsa_TestCall(struct dcesrv_call_state *dce_call,
2475                              TALLOC_CTX *mem_ctx,
2476                              struct lsa_TestCall *r)
2477 {
2478         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2479 }
2480
2481 /*
2482   lookup a SID for 1 name
2483 */
2484 static NTSTATUS lsa_lookup_name(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
2485                                 const char *name, struct dom_sid **sid, uint32_t *atype)
2486 {
2487         int ret;
2488         struct ldb_message **res;
2489         const char * const attrs[] = { "objectSid", "sAMAccountType", NULL};
2490         const char *p;
2491
2492         p = strchr_m(name, '\\');
2493         if (p != NULL) {
2494                 /* TODO: properly parse the domain prefix here, and use it to 
2495                    limit the search */
2496                 name = p + 1;
2497         }
2498
2499         ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, "sAMAccountName=%s", name);
2500         if (ret == 1) {
2501                 *sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
2502                 if (*sid == NULL) {
2503                         return NT_STATUS_INVALID_SID;
2504                 }
2505
2506                 *atype = samdb_result_uint(res[0], "sAMAccountType", 0);
2507
2508                 return NT_STATUS_OK;
2509         }
2510
2511         /* need to add a call into sidmap to check for a allocated sid */
2512
2513         return NT_STATUS_INVALID_SID;
2514 }
2515
2516
2517 /*
2518   lsa_LookupNames4
2519 */
2520 static NTSTATUS lsa_LookupNames4(struct dcesrv_call_state *dce_call,
2521                                  TALLOC_CTX *mem_ctx,
2522                                  struct lsa_LookupNames4 *r)
2523 {
2524         struct lsa_policy_state *state;
2525         int i;
2526         NTSTATUS status = NT_STATUS_OK;
2527
2528         status = lsa_get_policy_state(dce_call, mem_ctx, &state);
2529         if (!NT_STATUS_IS_OK(status)) {
2530                 return status;
2531         }
2532
2533         r->out.domains = NULL;
2534
2535         r->out.domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
2536         if (r->out.domains == NULL) {
2537                 return NT_STATUS_NO_MEMORY;
2538         }
2539
2540         r->out.sids = talloc_zero(mem_ctx,  struct lsa_TransSidArray3);
2541         if (r->out.sids == NULL) {
2542                 return NT_STATUS_NO_MEMORY;
2543         }
2544
2545         *r->out.count = 0;
2546
2547         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid3, 
2548                                            r->in.num_names);
2549         if (r->out.sids->sids == NULL) {
2550                 return NT_STATUS_NO_MEMORY;
2551         }
2552
2553         for (i=0;i<r->in.num_names;i++) {
2554                 const char *name = r->in.names[i].string;
2555                 struct dom_sid *sid;
2556                 uint32_t atype, rtype, sid_index;
2557                 NTSTATUS status2;
2558
2559                 r->out.sids->count++;
2560                 (*r->out.count)++;
2561
2562                 r->out.sids->sids[i].sid_type    = SID_NAME_UNKNOWN;
2563                 r->out.sids->sids[i].sid         = NULL;
2564                 r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
2565                 r->out.sids->sids[i].unknown     = 0;
2566
2567                 status2 = lsa_lookup_name(state, mem_ctx, name, &sid, &atype);
2568                 if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
2569                         status = STATUS_SOME_UNMAPPED;
2570                         continue;
2571                 }
2572
2573                 rtype = samdb_atype_map(atype);
2574                 if (rtype == SID_NAME_UNKNOWN) {
2575                         status = STATUS_SOME_UNMAPPED;
2576                         continue;
2577                 }
2578
2579                 status2 = lsa_authority_list(state, mem_ctx, sid, r->out.domains, &sid_index);
2580                 if (!NT_STATUS_IS_OK(status2)) {
2581                         return status2;
2582                 }
2583
2584                 r->out.sids->sids[i].sid_type    = rtype;
2585                 r->out.sids->sids[i].sid         = sid;
2586                 r->out.sids->sids[i].sid_index   = sid_index;
2587                 r->out.sids->sids[i].unknown     = 0;
2588         }
2589         
2590         return status;
2591 }
2592
2593 /* 
2594   lsa_LookupNames3
2595 */
2596 static NTSTATUS lsa_LookupNames3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2597                                  struct lsa_LookupNames3 *r)
2598 {
2599         struct lsa_LookupNames4 r2;
2600         NTSTATUS status;
2601         struct dcesrv_handle *h;
2602         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2603         
2604         r2.in.num_names = r->in.num_names;
2605         r2.in.names = r->in.names;
2606         r2.in.sids = r->in.sids;
2607         r2.in.count = r->in.count;
2608         r2.in.unknown1 = r->in.unknown1;
2609         r2.in.unknown2 = r->in.unknown2;
2610         r2.out.domains = r->out.domains;
2611         r2.out.sids = r->out.sids;
2612         r2.out.count = r->out.count;
2613         
2614         status = lsa_LookupNames4(dce_call, mem_ctx, &r2);
2615         if (dce_call->fault_code != 0) {
2616                 return status;
2617         }
2618         
2619         r->out.domains = r2.out.domains;
2620         r->out.sids = r2.out.sids;
2621         r->out.count = r2.out.count;
2622         return status;
2623 }
2624
2625 /*
2626   lsa_LookupNames2
2627 */
2628 static NTSTATUS lsa_LookupNames2(struct dcesrv_call_state *dce_call,
2629                                  TALLOC_CTX *mem_ctx,
2630                                  struct lsa_LookupNames2 *r)
2631 {
2632         struct lsa_policy_state *state;
2633         struct dcesrv_handle *h;
2634         int i;
2635         NTSTATUS status = NT_STATUS_OK;
2636
2637         r->out.domains = NULL;
2638
2639         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2640
2641         state = h->data;
2642
2643         r->out.domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
2644         if (r->out.domains == NULL) {
2645                 return NT_STATUS_NO_MEMORY;
2646         }
2647
2648         r->out.sids = talloc_zero(mem_ctx,  struct lsa_TransSidArray2);
2649         if (r->out.sids == NULL) {
2650                 return NT_STATUS_NO_MEMORY;
2651         }
2652
2653         *r->out.count = 0;
2654
2655         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid2, 
2656                                            r->in.num_names);
2657         if (r->out.sids->sids == NULL) {
2658                 return NT_STATUS_NO_MEMORY;
2659         }
2660
2661         for (i=0;i<r->in.num_names;i++) {
2662                 const char *name = r->in.names[i].string;
2663                 struct dom_sid *sid;
2664                 uint32_t atype, rtype, sid_index;
2665                 NTSTATUS status2;
2666
2667                 r->out.sids->count++;
2668                 (*r->out.count)++;
2669
2670                 r->out.sids->sids[i].sid_type    = SID_NAME_UNKNOWN;
2671                 r->out.sids->sids[i].rid         = 0xFFFFFFFF;
2672                 r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
2673                 r->out.sids->sids[i].unknown     = 0;
2674
2675                 status2 = lsa_lookup_name(state, mem_ctx, name, &sid, &atype);
2676                 if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
2677                         status = STATUS_SOME_UNMAPPED;
2678                         continue;
2679                 }
2680
2681                 rtype = samdb_atype_map(atype);
2682                 if (rtype == SID_NAME_UNKNOWN) {
2683                         status = STATUS_SOME_UNMAPPED;
2684                         continue;
2685                 }
2686
2687                 status2 = lsa_authority_list(state, mem_ctx, sid, r->out.domains, &sid_index);
2688                 if (!NT_STATUS_IS_OK(status2)) {
2689                         return status2;
2690                 }
2691
2692                 r->out.sids->sids[i].sid_type    = rtype;
2693                 r->out.sids->sids[i].rid         = sid->sub_auths[sid->num_auths-1];
2694                 r->out.sids->sids[i].sid_index   = sid_index;
2695                 r->out.sids->sids[i].unknown     = 0;
2696         }
2697         
2698         return status;
2699 }
2700
2701 /* 
2702   lsa_LookupNames 
2703 */
2704 static NTSTATUS lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2705                        struct lsa_LookupNames *r)
2706 {
2707         struct lsa_LookupNames2 r2;
2708         NTSTATUS status;
2709         int i;
2710
2711         r2.in.handle    = r->in.handle;
2712         r2.in.num_names = r->in.num_names;
2713         r2.in.names     = r->in.names;
2714         r2.in.sids      = NULL;
2715         r2.in.level     = r->in.level;
2716         r2.in.count     = r->in.count;
2717         r2.in.unknown1  = 0;
2718         r2.in.unknown2  = 0;
2719         r2.out.count    = r->out.count;
2720
2721         status = lsa_LookupNames2(dce_call, mem_ctx, &r2);
2722         if (dce_call->fault_code != 0) {
2723                 return status;
2724         }
2725
2726         r->out.domains = r2.out.domains;
2727         r->out.sids = talloc(mem_ctx, struct lsa_TransSidArray);
2728         if (r->out.sids == NULL) {
2729                 return NT_STATUS_NO_MEMORY;
2730         }
2731         r->out.sids->count = r2.out.sids->count;
2732         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid, 
2733                                            r->out.sids->count);
2734         if (r->out.sids->sids == NULL) {
2735                 return NT_STATUS_NO_MEMORY;
2736         }
2737         for (i=0;i<r->out.sids->count;i++) {
2738                 r->out.sids->sids[i].sid_type    = r2.out.sids->sids[i].sid_type;
2739                 r->out.sids->sids[i].rid         = r2.out.sids->sids[i].rid;
2740                 r->out.sids->sids[i].sid_index   = r2.out.sids->sids[i].sid_index;
2741         }
2742
2743         return status;
2744 }
2745
2746 /* 
2747   lsa_CREDRWRITE 
2748 */
2749 static NTSTATUS lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2750                        struct lsa_CREDRWRITE *r)
2751 {
2752         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2753 }
2754
2755
2756 /* 
2757   lsa_CREDRREAD 
2758 */
2759 static NTSTATUS lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2760                        struct lsa_CREDRREAD *r)
2761 {
2762         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2763 }
2764
2765
2766 /* 
2767   lsa_CREDRENUMERATE 
2768 */
2769 static NTSTATUS lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2770                        struct lsa_CREDRENUMERATE *r)
2771 {
2772         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2773 }
2774
2775
2776 /* 
2777   lsa_CREDRWRITEDOMAINCREDENTIALS 
2778 */
2779 static NTSTATUS lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2780                        struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
2781 {
2782         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2783 }
2784
2785
2786 /* 
2787   lsa_CREDRREADDOMAINCREDENTIALS 
2788 */
2789 static NTSTATUS lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2790                        struct lsa_CREDRREADDOMAINCREDENTIALS *r)
2791 {
2792         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2793 }
2794
2795
2796 /* 
2797   lsa_CREDRDELETE 
2798 */
2799 static NTSTATUS lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2800                        struct lsa_CREDRDELETE *r)
2801 {
2802         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2803 }
2804
2805
2806 /* 
2807   lsa_CREDRGETTARGETINFO 
2808 */
2809 static NTSTATUS lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2810                        struct lsa_CREDRGETTARGETINFO *r)
2811 {
2812         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2813 }
2814
2815
2816 /* 
2817   lsa_CREDRPROFILELOADED 
2818 */
2819 static NTSTATUS lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2820                        struct lsa_CREDRPROFILELOADED *r)
2821 {
2822         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2823 }
2824
2825
2826 /* 
2827   lsa_CREDRGETSESSIONTYPES 
2828 */
2829 static NTSTATUS lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2830                        struct lsa_CREDRGETSESSIONTYPES *r)
2831 {
2832         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2833 }
2834
2835
2836 /* 
2837   lsa_LSARREGISTERAUDITEVENT 
2838 */
2839 static NTSTATUS lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2840                        struct lsa_LSARREGISTERAUDITEVENT *r)
2841 {
2842         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2843 }
2844
2845
2846 /* 
2847   lsa_LSARGENAUDITEVENT 
2848 */
2849 static NTSTATUS lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2850                        struct lsa_LSARGENAUDITEVENT *r)
2851 {
2852         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2853 }
2854
2855
2856 /* 
2857   lsa_LSARUNREGISTERAUDITEVENT 
2858 */
2859 static NTSTATUS lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2860                        struct lsa_LSARUNREGISTERAUDITEVENT *r)
2861 {
2862         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2863 }
2864
2865
2866 /* 
2867   lsa_LSARQUERYFORESTTRUSTINFORMATION 
2868 */
2869 static NTSTATUS lsa_LSARQUERYFORESTTRUSTINFORMATION(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2870                        struct lsa_LSARQUERYFORESTTRUSTINFORMATION *r)
2871 {
2872         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2873 }
2874
2875
2876 /* 
2877   lsa_LSARSETFORESTTRUSTINFORMATION 
2878 */
2879 static NTSTATUS lsa_LSARSETFORESTTRUSTINFORMATION(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2880                        struct lsa_LSARSETFORESTTRUSTINFORMATION *r)
2881 {
2882         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2883 }
2884
2885
2886 /* 
2887   lsa_CREDRRENAME 
2888 */
2889 static NTSTATUS lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2890                        struct lsa_CREDRRENAME *r)
2891 {
2892         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2893 }
2894
2895
2896
2897 /* 
2898   lsa_LSAROPENPOLICYSCE 
2899 */
2900 static NTSTATUS lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2901                        struct lsa_LSAROPENPOLICYSCE *r)
2902 {
2903         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2904 }
2905
2906
2907 /* 
2908   lsa_LSARADTREGISTERSECURITYEVENTSOURCE 
2909 */
2910 static NTSTATUS lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2911                        struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
2912 {
2913         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2914 }
2915
2916
2917 /* 
2918   lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE 
2919 */
2920 static NTSTATUS lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2921                        struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
2922 {
2923         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2924 }
2925
2926
2927 /* 
2928   lsa_LSARADTREPORTSECURITYEVENT 
2929 */
2930 static NTSTATUS lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2931                        struct lsa_LSARADTREPORTSECURITYEVENT *r)
2932 {
2933         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2934 }
2935
2936
2937 /* include the generated boilerplate */
2938 #include "librpc/gen_ndr/ndr_lsa_s.c"