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