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