r17529: Simo doesn't like the use of the internal ldb_errstring in functions
[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_attr_as_string(res[0], "sAMAccountName", NULL);
1171                 if (!*name) {
1172                         *name = ldb_msg_find_attr_as_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         char *errstr;
1773         const char *attrs[] = {
1774                 NULL
1775         };
1776
1777         const char *name;
1778
1779         int ret;
1780
1781         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1782         ZERO_STRUCTP(r->out.sec_handle);
1783         
1784         policy_state = policy_handle->data;
1785
1786         if (!r->in.name.string) {
1787                 return NT_STATUS_INVALID_PARAMETER;
1788         }
1789         
1790         secret_state = talloc(mem_ctx, struct lsa_secret_state);
1791         if (!secret_state) {
1792                 return NT_STATUS_NO_MEMORY;
1793         }
1794         secret_state->policy = policy_state;
1795
1796         msg = ldb_msg_new(mem_ctx);
1797         if (msg == NULL) {
1798                 return NT_STATUS_NO_MEMORY;
1799         }
1800
1801         if (strncmp("G$", r->in.name.string, 2) == 0) {
1802                 const char *name2;
1803                 name = &r->in.name.string[2];
1804                 secret_state->sam_ldb = talloc_reference(secret_state, policy_state->sam_ldb);
1805                 secret_state->global = True;
1806
1807                 if (strlen(name) < 1) {
1808                         return NT_STATUS_INVALID_PARAMETER;
1809                 }
1810
1811                 name2 = talloc_asprintf(mem_ctx, "%s Secret", ldb_binary_encode_string(mem_ctx, name));
1812                 /* search for the secret record */
1813                 ret = gendb_search(secret_state->sam_ldb,
1814                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
1815                                    "(&(cn=%s)(objectclass=secret))", 
1816                                    name2);
1817                 if (ret > 0) {
1818                         return NT_STATUS_OBJECT_NAME_COLLISION;
1819                 }
1820                 
1821                 if (ret == -1) {
1822                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
1823                                  name2, ldb_errstring(secret_state->sam_ldb)));
1824                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1825                 }
1826
1827                 msg->dn = ldb_dn_build_child(mem_ctx, "cn", name2, policy_state->system_dn);
1828                 if (!name2 || !msg->dn) {
1829                         return NT_STATUS_NO_MEMORY;
1830                 }
1831                 
1832                 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name2);
1833         
1834         } else {
1835                 secret_state->global = False;
1836
1837                 name = r->in.name.string;
1838                 if (strlen(name) < 1) {
1839                         return NT_STATUS_INVALID_PARAMETER;
1840                 }
1841
1842                 secret_state->sam_ldb = talloc_reference(secret_state, secrets_db_connect(mem_ctx));
1843                 /* search for the secret record */
1844                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
1845                                    ldb_dn_explode(mem_ctx, "cn=LSA Secrets"),
1846                                    &msgs, attrs,
1847                                    "(&(cn=%s)(objectclass=secret))", 
1848                                    ldb_binary_encode_string(mem_ctx, name));
1849                 if (ret > 0) {
1850                         return NT_STATUS_OBJECT_NAME_COLLISION;
1851                 }
1852                 
1853                 if (ret == -1) {
1854                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
1855                                  name, ldb_errstring(secret_state->sam_ldb)));
1856                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1857                 }
1858
1859                 msg->dn = ldb_dn_string_compose(mem_ctx, NULL, "cn=%s,cn=LSA Secrets", name);
1860                 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name);
1861         } 
1862
1863         /* pull in all the template attributes.  Note this is always from the global samdb */
1864         ret = samdb_copy_template(secret_state->policy->sam_ldb, msg, 
1865                                   "(&(cn=TemplateSecret)(objectclass=secretTemplate))", &errstr);
1866         if (ret != 0) {
1867                 DEBUG(0,("Failed to load TemplateSecret from samdb: %s\n",
1868                          errstr));
1869                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1870         }
1871
1872         samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "objectClass", "secret");
1873         
1874         secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
1875
1876         /* create the secret */
1877         ret = samdb_add(secret_state->sam_ldb, mem_ctx, msg);
1878         if (ret != 0) {
1879                 DEBUG(0,("Failed to create secret record %s: %s\n",
1880                          ldb_dn_linearize(mem_ctx, msg->dn), 
1881                          ldb_errstring(secret_state->sam_ldb)));
1882                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1883         }
1884
1885         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
1886         if (!handle) {
1887                 return NT_STATUS_NO_MEMORY;
1888         }
1889         
1890         handle->data = talloc_steal(handle, secret_state);
1891         
1892         secret_state->access_mask = r->in.access_mask;
1893         secret_state->policy = talloc_reference(secret_state, policy_state);
1894         
1895         *r->out.sec_handle = handle->wire_handle;
1896         
1897         return NT_STATUS_OK;
1898 }
1899
1900
1901 /* 
1902   lsa_OpenSecret 
1903 */
1904 static NTSTATUS lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1905                                struct lsa_OpenSecret *r)
1906 {
1907         struct dcesrv_handle *policy_handle;
1908         
1909         struct lsa_policy_state *policy_state;
1910         struct lsa_secret_state *secret_state;
1911         struct dcesrv_handle *handle;
1912         struct ldb_message **msgs;
1913         const char *attrs[] = {
1914                 NULL
1915         };
1916
1917         const char *name;
1918
1919         int ret;
1920
1921         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1922         ZERO_STRUCTP(r->out.sec_handle);
1923         policy_state = policy_handle->data;
1924
1925         if (!r->in.name.string) {
1926                 return NT_STATUS_INVALID_PARAMETER;
1927         }
1928         
1929         secret_state = talloc(mem_ctx, struct lsa_secret_state);
1930         if (!secret_state) {
1931                 return NT_STATUS_NO_MEMORY;
1932         }
1933         secret_state->policy = policy_state;
1934
1935         if (strncmp("G$", r->in.name.string, 2) == 0) {
1936                 name = &r->in.name.string[2];
1937                 secret_state->sam_ldb = talloc_reference(secret_state, policy_state->sam_ldb);
1938                 secret_state->global = True;
1939
1940                 if (strlen(name) < 1) {
1941                         return NT_STATUS_INVALID_PARAMETER;
1942                 }
1943
1944                 /* search for the secret record */
1945                 ret = gendb_search(secret_state->sam_ldb,
1946                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
1947                                    "(&(cn=%s Secret)(objectclass=secret))", 
1948                                    ldb_binary_encode_string(mem_ctx, name));
1949                 if (ret == 0) {
1950                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1951                 }
1952                 
1953                 if (ret != 1) {
1954                         DEBUG(0,("Found %d records matching DN %s\n", ret,
1955                                  ldb_dn_linearize(mem_ctx, policy_state->system_dn)));
1956                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1957                 }
1958         
1959         } else {
1960                 secret_state->sam_ldb = talloc_reference(secret_state, secrets_db_connect(mem_ctx));
1961
1962                 secret_state->global = False;
1963                 name = r->in.name.string;
1964                 if (strlen(name) < 1) {
1965                         return NT_STATUS_INVALID_PARAMETER;
1966                 }
1967
1968                 /* search for the secret record */
1969                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
1970                                    ldb_dn_explode(mem_ctx, "cn=LSA Secrets"),
1971                                    &msgs, attrs,
1972                                    "(&(cn=%s)(objectclass=secret))", 
1973                                    ldb_binary_encode_string(mem_ctx, name));
1974                 if (ret == 0) {
1975                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1976                 }
1977                 
1978                 if (ret != 1) {
1979                         DEBUG(0,("Found %d records matching DN %s\n", ret,
1980                                  ldb_dn_linearize(mem_ctx, policy_state->system_dn)));
1981                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1982                 }
1983         } 
1984
1985         secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
1986         
1987         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
1988         if (!handle) {
1989                 return NT_STATUS_NO_MEMORY;
1990         }
1991         
1992         handle->data = talloc_steal(handle, secret_state);
1993         
1994         secret_state->access_mask = r->in.access_mask;
1995         secret_state->policy = talloc_reference(secret_state, policy_state);
1996         
1997         *r->out.sec_handle = handle->wire_handle;
1998         
1999         return NT_STATUS_OK;
2000 }
2001
2002
2003 /* 
2004   lsa_SetSecret 
2005 */
2006 static NTSTATUS lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2007                               struct lsa_SetSecret *r)
2008 {
2009
2010         struct dcesrv_handle *h;
2011         struct lsa_secret_state *secret_state;
2012         struct ldb_message *msg;
2013         DATA_BLOB session_key;
2014         DATA_BLOB crypt_secret, secret;
2015         struct ldb_val val;
2016         int ret;
2017         NTSTATUS status = NT_STATUS_OK;
2018
2019         struct timeval now = timeval_current();
2020         NTTIME nt_now = timeval_to_nttime(&now);
2021
2022         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
2023
2024         secret_state = h->data;
2025
2026         msg = ldb_msg_new(mem_ctx);
2027         if (msg == NULL) {
2028                 return NT_STATUS_NO_MEMORY;
2029         }
2030
2031         msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
2032         if (!msg->dn) {
2033                 return NT_STATUS_NO_MEMORY;
2034         }
2035         status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
2036         if (!NT_STATUS_IS_OK(status)) {
2037                 return status;
2038         }
2039
2040         if (r->in.old_val) {
2041                 /* Decrypt */
2042                 crypt_secret.data = r->in.old_val->data;
2043                 crypt_secret.length = r->in.old_val->size;
2044                 
2045                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
2046                 if (!NT_STATUS_IS_OK(status)) {
2047                         return status;
2048                 }
2049                 
2050                 val.data = secret.data;
2051                 val.length = secret.length;
2052                 
2053                 /* set value */
2054                 if (samdb_msg_add_value(secret_state->sam_ldb, 
2055                                         mem_ctx, msg, "priorSecret", &val) != 0) {
2056                         return NT_STATUS_NO_MEMORY; 
2057                 }
2058                 
2059                 /* set old value mtime */
2060                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2061                                          mem_ctx, msg, "priorSetTime", nt_now) != 0) { 
2062                         return NT_STATUS_NO_MEMORY; 
2063                 }
2064
2065                 if (!r->in.new_val) {
2066                         /* This behaviour varies depending of if this is a local, or a global secret... */
2067                         if (secret_state->global) {
2068                                 /* set old value mtime */
2069                                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2070                                                          mem_ctx, msg, "lastSetTime", nt_now) != 0) { 
2071                                         return NT_STATUS_NO_MEMORY; 
2072                                 }
2073                         } else {
2074                                 if (samdb_msg_add_delete(secret_state->sam_ldb, 
2075                                                          mem_ctx, msg, "secret")) {
2076                                         return NT_STATUS_NO_MEMORY;
2077                                 }
2078                                 if (samdb_msg_add_delete(secret_state->sam_ldb, 
2079                                                          mem_ctx, msg, "lastSetTime")) {
2080                                         return NT_STATUS_NO_MEMORY;
2081                                 }
2082                         }
2083                 }
2084         }
2085
2086         if (r->in.new_val) {
2087                 /* Decrypt */
2088                 crypt_secret.data = r->in.new_val->data;
2089                 crypt_secret.length = r->in.new_val->size;
2090                 
2091                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
2092                 if (!NT_STATUS_IS_OK(status)) {
2093                         return status;
2094                 }
2095                 
2096                 val.data = secret.data;
2097                 val.length = secret.length;
2098                 
2099                 /* set value */
2100                 if (samdb_msg_add_value(secret_state->sam_ldb, 
2101                                         mem_ctx, msg, "secret", &val) != 0) {
2102                         return NT_STATUS_NO_MEMORY; 
2103                 }
2104                 
2105                 /* set new value mtime */
2106                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2107                                          mem_ctx, msg, "lastSetTime", nt_now) != 0) { 
2108                         return NT_STATUS_NO_MEMORY; 
2109                 }
2110                 
2111                 /* If the old value is not set, then migrate the
2112                  * current value to the old value */
2113                 if (!r->in.old_val) {
2114                         const struct ldb_val *new_val;
2115                         NTTIME last_set_time;
2116                         struct ldb_message **res;
2117                         const char *attrs[] = {
2118                                 "secret",
2119                                 "lastSetTime",
2120                                 NULL
2121                         };
2122                         
2123                         /* search for the secret record */
2124                         ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
2125                                               secret_state->secret_dn, &res, attrs);
2126                         if (ret == 0) {
2127                                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2128                         }
2129                         
2130                         if (ret != 1) {
2131                                 DEBUG(0,("Found %d records matching dn=%s\n", ret,
2132                                          ldb_dn_linearize(mem_ctx, secret_state->secret_dn)));
2133                                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2134                         }
2135
2136                         new_val = ldb_msg_find_ldb_val(res[0], "secret");
2137                         last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
2138                         
2139                         if (new_val) {
2140                                 /* set value */
2141                                 if (samdb_msg_add_value(secret_state->sam_ldb, 
2142                                                         mem_ctx, msg, "priorSecret", 
2143                                                         new_val) != 0) {
2144                                         return NT_STATUS_NO_MEMORY; 
2145                                 }
2146                         }
2147                         
2148                         /* set new value mtime */
2149                         if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
2150                                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2151                                                          mem_ctx, msg, "priorSetTime", last_set_time) != 0) { 
2152                                         return NT_STATUS_NO_MEMORY; 
2153                                 }
2154                         }
2155                 }
2156         }
2157
2158         /* modify the samdb record */
2159         ret = samdb_replace(secret_state->sam_ldb, mem_ctx, msg);
2160         if (ret != 0) {
2161                 /* we really need samdb.c to return NTSTATUS */
2162                 return NT_STATUS_UNSUCCESSFUL;
2163         }
2164
2165         return NT_STATUS_OK;
2166 }
2167
2168
2169 /* 
2170   lsa_QuerySecret 
2171 */
2172 static NTSTATUS lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2173                                 struct lsa_QuerySecret *r)
2174 {
2175         struct dcesrv_handle *h;
2176         struct lsa_secret_state *secret_state;
2177         struct ldb_message *msg;
2178         DATA_BLOB session_key;
2179         DATA_BLOB crypt_secret, secret;
2180         int ret;
2181         struct ldb_message **res;
2182         const char *attrs[] = {
2183                 "secret",
2184                 "priorSecret",
2185                 "lastSetTime",
2186                 "priorSetTime", 
2187                 NULL
2188         };
2189
2190         NTSTATUS nt_status;
2191
2192         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
2193
2194         secret_state = h->data;
2195
2196         /* pull all the user attributes */
2197         ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
2198                               secret_state->secret_dn, &res, attrs);
2199         if (ret != 1) {
2200                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2201         }
2202         msg = res[0];
2203         
2204         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
2205         if (!NT_STATUS_IS_OK(nt_status)) {
2206                 return nt_status;
2207         }
2208         
2209         if (r->in.old_val) {
2210                 const struct ldb_val *prior_val;
2211                 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
2212                 if (!r->out.old_val) {
2213                         return NT_STATUS_NO_MEMORY;
2214                 }
2215                 /* Decrypt */
2216                 prior_val = ldb_msg_find_ldb_val(res[0], "priorSecret");
2217                 
2218                 if (prior_val && prior_val->length) {
2219                         secret.data = prior_val->data;
2220                         secret.length = prior_val->length;
2221                 
2222                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
2223                         if (!crypt_secret.length) {
2224                                 return NT_STATUS_NO_MEMORY;
2225                         }
2226                         r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
2227                         if (!r->out.old_val->buf) {
2228                                 return NT_STATUS_NO_MEMORY;
2229                         }
2230                         r->out.old_val->buf->size = crypt_secret.length;
2231                         r->out.old_val->buf->length = crypt_secret.length;
2232                         r->out.old_val->buf->data = crypt_secret.data;
2233                 }
2234         }
2235         
2236         if (r->in.old_mtime) {
2237                 r->out.old_mtime = talloc(mem_ctx, NTTIME);
2238                 if (!r->out.old_mtime) {
2239                         return NT_STATUS_NO_MEMORY;
2240                 }
2241                 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
2242         }
2243         
2244         if (r->in.new_val) {
2245                 const struct ldb_val *new_val;
2246                 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
2247                 if (!r->out.new_val) {
2248                         return NT_STATUS_NO_MEMORY;
2249                 }
2250
2251                 /* Decrypt */
2252                 new_val = ldb_msg_find_ldb_val(res[0], "secret");
2253                 
2254                 if (new_val && new_val->length) {
2255                         secret.data = new_val->data;
2256                         secret.length = new_val->length;
2257                 
2258                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
2259                         if (!crypt_secret.length) {
2260                                 return NT_STATUS_NO_MEMORY;
2261                         }
2262                         r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
2263                         if (!r->out.new_val->buf) {
2264                                 return NT_STATUS_NO_MEMORY;
2265                         }
2266                         r->out.new_val->buf->length = crypt_secret.length;
2267                         r->out.new_val->buf->size = crypt_secret.length;
2268                         r->out.new_val->buf->data = crypt_secret.data;
2269                 }
2270         }
2271         
2272         if (r->in.new_mtime) {
2273                 r->out.new_mtime = talloc(mem_ctx, NTTIME);
2274                 if (!r->out.new_mtime) {
2275                         return NT_STATUS_NO_MEMORY;
2276                 }
2277                 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
2278         }
2279         
2280         return NT_STATUS_OK;
2281 }
2282
2283
2284 /* 
2285   lsa_LookupPrivValue
2286 */
2287 static NTSTATUS lsa_LookupPrivValue(struct dcesrv_call_state *dce_call, 
2288                                     TALLOC_CTX *mem_ctx,
2289                                     struct lsa_LookupPrivValue *r)
2290 {
2291         struct dcesrv_handle *h;
2292         struct lsa_policy_state *state;
2293         int id;
2294
2295         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2296
2297         state = h->data;
2298
2299         id = sec_privilege_id(r->in.name->string);
2300         if (id == -1) {
2301                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2302         }
2303
2304         r->out.luid->low = id;
2305         r->out.luid->high = 0;
2306
2307         return NT_STATUS_OK;    
2308 }
2309
2310
2311 /* 
2312   lsa_LookupPrivName 
2313 */
2314 static NTSTATUS lsa_LookupPrivName(struct dcesrv_call_state *dce_call, 
2315                                    TALLOC_CTX *mem_ctx,
2316                                    struct lsa_LookupPrivName *r)
2317 {
2318         struct dcesrv_handle *h;
2319         struct lsa_policy_state *state;
2320         const char *privname;
2321
2322         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2323
2324         state = h->data;
2325
2326         if (r->in.luid->high != 0) {
2327                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2328         }
2329
2330         privname = sec_privilege_name(r->in.luid->low);
2331         if (privname == NULL) {
2332                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2333         }
2334
2335         r->out.name = talloc(mem_ctx, struct lsa_StringLarge);
2336         if (r->out.name == NULL) {
2337                 return NT_STATUS_NO_MEMORY;
2338         }
2339         r->out.name->string = privname;
2340
2341         return NT_STATUS_OK;    
2342 }
2343
2344
2345 /* 
2346   lsa_LookupPrivDisplayName
2347 */
2348 static NTSTATUS lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call, 
2349                                           TALLOC_CTX *mem_ctx,
2350                                           struct lsa_LookupPrivDisplayName *r)
2351 {
2352         struct dcesrv_handle *h;
2353         struct lsa_policy_state *state;
2354         int id;
2355
2356         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2357
2358         state = h->data;
2359
2360         id = sec_privilege_id(r->in.name->string);
2361         if (id == -1) {
2362                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2363         }
2364         
2365         r->out.disp_name = talloc(mem_ctx, struct lsa_StringLarge);
2366         if (r->out.disp_name == NULL) {
2367                 return NT_STATUS_NO_MEMORY;
2368         }
2369
2370         r->out.disp_name->string = sec_privilege_display_name(id, r->in.language_id);
2371         if (r->out.disp_name->string == NULL) {
2372                 return NT_STATUS_INTERNAL_ERROR;
2373         }
2374
2375         return NT_STATUS_OK;
2376 }
2377
2378
2379 /* 
2380   lsa_DeleteObject
2381 */
2382 static NTSTATUS lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2383                        struct lsa_DeleteObject *r)
2384 {
2385         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2386 }
2387
2388
2389 /* 
2390   lsa_EnumAccountsWithUserRight
2391 */
2392 static NTSTATUS lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call, 
2393                                               TALLOC_CTX *mem_ctx,
2394                                               struct lsa_EnumAccountsWithUserRight *r)
2395 {
2396         struct dcesrv_handle *h;
2397         struct lsa_policy_state *state;
2398         int ret, i;
2399         struct ldb_message **res;
2400         const char * const attrs[] = { "objectSid", NULL};
2401         const char *privname;
2402
2403         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2404
2405         state = h->data;
2406
2407         if (r->in.name == NULL) {
2408                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2409         } 
2410
2411         privname = r->in.name->string;
2412         if (sec_privilege_id(privname) == -1) {
2413                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2414         }
2415
2416         ret = gendb_search(state->sam_ldb, mem_ctx, samdb_base_dn(mem_ctx), &res, attrs, 
2417                            "privilege=%s", privname);
2418         if (ret == -1) {
2419                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2420         }
2421         if (ret == 0) {
2422                 return NT_STATUS_NO_MORE_ENTRIES;
2423         }
2424
2425         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
2426         if (r->out.sids->sids == NULL) {
2427                 return NT_STATUS_NO_MEMORY;
2428         }
2429         for (i=0;i<ret;i++) {
2430                 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
2431                                                                 res[i], "objectSid");
2432                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
2433         }
2434         r->out.sids->num_sids = ret;
2435
2436         return NT_STATUS_OK;
2437 }
2438
2439
2440 /* 
2441   lsa_AddAccountRights
2442 */
2443 static NTSTATUS lsa_AddAccountRights(struct dcesrv_call_state *dce_call, 
2444                                      TALLOC_CTX *mem_ctx,
2445                                      struct lsa_AddAccountRights *r)
2446 {
2447         struct dcesrv_handle *h;
2448         struct lsa_policy_state *state;
2449
2450         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2451
2452         state = h->data;
2453
2454         return lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
2455                                           LDB_FLAG_MOD_ADD,
2456                                           r->in.sid, r->in.rights);
2457 }
2458
2459
2460 /* 
2461   lsa_RemoveAccountRights
2462 */
2463 static NTSTATUS lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call, 
2464                                         TALLOC_CTX *mem_ctx,
2465                                         struct lsa_RemoveAccountRights *r)
2466 {
2467         struct dcesrv_handle *h;
2468         struct lsa_policy_state *state;
2469
2470         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2471
2472         state = h->data;
2473
2474         return lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
2475                                           LDB_FLAG_MOD_DELETE,
2476                                           r->in.sid, r->in.rights);
2477 }
2478
2479
2480 /* 
2481   lsa_StorePrivateData
2482 */
2483 static NTSTATUS lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2484                        struct lsa_StorePrivateData *r)
2485 {
2486         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2487 }
2488
2489
2490 /* 
2491   lsa_RetrievePrivateData
2492 */
2493 static NTSTATUS lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2494                        struct lsa_RetrievePrivateData *r)
2495 {
2496         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2497 }
2498
2499
2500 /* 
2501   lsa_GetUserName
2502 */
2503 static NTSTATUS lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2504                                 struct lsa_GetUserName *r)
2505 {
2506         NTSTATUS status = NT_STATUS_OK;
2507         const char *account_name;
2508         const char *authority_name;
2509         struct lsa_String *_account_name;
2510         struct lsa_StringPointer *_authority_name = NULL;
2511
2512         /* this is what w2k3 does */
2513         r->out.account_name = r->in.account_name;
2514         r->out.authority_name = r->in.authority_name;
2515
2516         if (r->in.account_name && r->in.account_name->string) {
2517                 return NT_STATUS_INVALID_PARAMETER;
2518         }
2519
2520         if (r->in.authority_name &&
2521             r->in.authority_name->string &&
2522             r->in.authority_name->string->string) {
2523                 return NT_STATUS_INVALID_PARAMETER;
2524         }
2525
2526         account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->account_name);
2527         authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->domain_name);
2528
2529         _account_name = talloc(mem_ctx, struct lsa_String);
2530         NT_STATUS_HAVE_NO_MEMORY(_account_name);
2531         _account_name->string = account_name;
2532
2533         if (r->in.authority_name) {
2534                 _authority_name = talloc(mem_ctx, struct lsa_StringPointer);
2535                 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
2536                 _authority_name->string = talloc(mem_ctx, struct lsa_String);
2537                 NT_STATUS_HAVE_NO_MEMORY(_authority_name->string);
2538                 _authority_name->string->string = authority_name;
2539         }
2540
2541         r->out.account_name = _account_name;
2542         r->out.authority_name = _authority_name;
2543
2544         return status;
2545 }
2546
2547 /*
2548   lsa_SetInfoPolicy2
2549 */
2550 static NTSTATUS lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
2551                                    TALLOC_CTX *mem_ctx,
2552                                    struct lsa_SetInfoPolicy2 *r)
2553 {
2554         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2555 }
2556
2557 /*
2558   lsa_QueryDomainInformationPolicy
2559 */
2560 static NTSTATUS lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
2561                                                  TALLOC_CTX *mem_ctx,
2562                                                  struct lsa_QueryDomainInformationPolicy *r)
2563 {
2564         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2565 }
2566
2567 /*
2568   lsa_SetDomInfoPolicy
2569 */
2570 static NTSTATUS lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
2571                                               TALLOC_CTX *mem_ctx,
2572                                               struct lsa_SetDomainInformationPolicy *r)
2573 {
2574         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2575 }
2576
2577 /*
2578   lsa_TestCall
2579 */
2580 static NTSTATUS lsa_TestCall(struct dcesrv_call_state *dce_call,
2581                              TALLOC_CTX *mem_ctx,
2582                              struct lsa_TestCall *r)
2583 {
2584         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2585 }
2586
2587 /*
2588   lookup a SID for 1 name
2589 */
2590 static NTSTATUS lsa_lookup_name(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
2591                                 const char *name, struct dom_sid **sid, uint32_t *atype)
2592 {
2593         int ret;
2594         struct ldb_message **res;
2595         const char * const attrs[] = { "objectSid", "sAMAccountType", NULL};
2596         const char *p;
2597
2598         p = strchr_m(name, '\\');
2599         if (p != NULL) {
2600                 /* TODO: properly parse the domain prefix here, and use it to 
2601                    limit the search */
2602                 name = p + 1;
2603         }
2604
2605         ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, "sAMAccountName=%s", ldb_binary_encode_string(mem_ctx, name));
2606         if (ret == 1) {
2607                 *sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
2608                 if (*sid == NULL) {
2609                         return NT_STATUS_INVALID_SID;
2610                 }
2611
2612                 *atype = samdb_result_uint(res[0], "sAMAccountType", 0);
2613
2614                 return NT_STATUS_OK;
2615         }
2616
2617         /* need to add a call into sidmap to check for a allocated sid */
2618
2619         return NT_STATUS_INVALID_SID;
2620 }
2621
2622
2623 /*
2624   lsa_LookupNames4
2625 */
2626 static NTSTATUS lsa_LookupNames4(struct dcesrv_call_state *dce_call,
2627                                  TALLOC_CTX *mem_ctx,
2628                                  struct lsa_LookupNames4 *r)
2629 {
2630         struct lsa_policy_state *state;
2631         int i;
2632         NTSTATUS status = NT_STATUS_OK;
2633
2634         status = lsa_get_policy_state(dce_call, mem_ctx, &state);
2635         if (!NT_STATUS_IS_OK(status)) {
2636                 return status;
2637         }
2638
2639         r->out.domains = NULL;
2640
2641         r->out.domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
2642         if (r->out.domains == NULL) {
2643                 return NT_STATUS_NO_MEMORY;
2644         }
2645
2646         r->out.sids = talloc_zero(mem_ctx,  struct lsa_TransSidArray3);
2647         if (r->out.sids == NULL) {
2648                 return NT_STATUS_NO_MEMORY;
2649         }
2650
2651         *r->out.count = 0;
2652
2653         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid3, 
2654                                            r->in.num_names);
2655         if (r->out.sids->sids == NULL) {
2656                 return NT_STATUS_NO_MEMORY;
2657         }
2658
2659         for (i=0;i<r->in.num_names;i++) {
2660                 const char *name = r->in.names[i].string;
2661                 struct dom_sid *sid;
2662                 uint32_t atype, rtype, sid_index;
2663                 NTSTATUS status2;
2664
2665                 r->out.sids->count++;
2666                 (*r->out.count)++;
2667
2668                 r->out.sids->sids[i].sid_type    = SID_NAME_UNKNOWN;
2669                 r->out.sids->sids[i].sid         = NULL;
2670                 r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
2671                 r->out.sids->sids[i].unknown     = 0;
2672
2673                 status2 = lsa_lookup_name(state, mem_ctx, name, &sid, &atype);
2674                 if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
2675                         status = STATUS_SOME_UNMAPPED;
2676                         continue;
2677                 }
2678
2679                 rtype = samdb_atype_map(atype);
2680                 if (rtype == SID_NAME_UNKNOWN) {
2681                         status = STATUS_SOME_UNMAPPED;
2682                         continue;
2683                 }
2684
2685                 status2 = lsa_authority_list(state, mem_ctx, sid, r->out.domains, &sid_index);
2686                 if (!NT_STATUS_IS_OK(status2)) {
2687                         return status2;
2688                 }
2689
2690                 r->out.sids->sids[i].sid_type    = rtype;
2691                 r->out.sids->sids[i].sid         = sid;
2692                 r->out.sids->sids[i].sid_index   = sid_index;
2693                 r->out.sids->sids[i].unknown     = 0;
2694         }
2695         
2696         return status;
2697 }
2698
2699 /* 
2700   lsa_LookupNames3
2701 */
2702 static NTSTATUS lsa_LookupNames3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2703                                  struct lsa_LookupNames3 *r)
2704 {
2705         struct lsa_LookupNames4 r2;
2706         NTSTATUS status;
2707         struct dcesrv_handle *h;
2708         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2709         
2710         r2.in.num_names = r->in.num_names;
2711         r2.in.names = r->in.names;
2712         r2.in.sids = r->in.sids;
2713         r2.in.count = r->in.count;
2714         r2.in.unknown1 = r->in.unknown1;
2715         r2.in.unknown2 = r->in.unknown2;
2716         r2.out.domains = r->out.domains;
2717         r2.out.sids = r->out.sids;
2718         r2.out.count = r->out.count;
2719         
2720         status = lsa_LookupNames4(dce_call, mem_ctx, &r2);
2721         if (dce_call->fault_code != 0) {
2722                 return status;
2723         }
2724         
2725         r->out.domains = r2.out.domains;
2726         r->out.sids = r2.out.sids;
2727         r->out.count = r2.out.count;
2728         return status;
2729 }
2730
2731 /*
2732   lsa_LookupNames2
2733 */
2734 static NTSTATUS lsa_LookupNames2(struct dcesrv_call_state *dce_call,
2735                                  TALLOC_CTX *mem_ctx,
2736                                  struct lsa_LookupNames2 *r)
2737 {
2738         struct lsa_policy_state *state;
2739         struct dcesrv_handle *h;
2740         int i;
2741         NTSTATUS status = NT_STATUS_OK;
2742
2743         r->out.domains = NULL;
2744
2745         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2746
2747         state = h->data;
2748
2749         r->out.domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
2750         if (r->out.domains == NULL) {
2751                 return NT_STATUS_NO_MEMORY;
2752         }
2753
2754         r->out.sids = talloc_zero(mem_ctx,  struct lsa_TransSidArray2);
2755         if (r->out.sids == NULL) {
2756                 return NT_STATUS_NO_MEMORY;
2757         }
2758
2759         *r->out.count = 0;
2760
2761         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid2, 
2762                                            r->in.num_names);
2763         if (r->out.sids->sids == NULL) {
2764                 return NT_STATUS_NO_MEMORY;
2765         }
2766
2767         for (i=0;i<r->in.num_names;i++) {
2768                 const char *name = r->in.names[i].string;
2769                 struct dom_sid *sid;
2770                 uint32_t atype, rtype, sid_index;
2771                 NTSTATUS status2;
2772
2773                 r->out.sids->count++;
2774                 (*r->out.count)++;
2775
2776                 r->out.sids->sids[i].sid_type    = SID_NAME_UNKNOWN;
2777                 r->out.sids->sids[i].rid         = 0xFFFFFFFF;
2778                 r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
2779                 r->out.sids->sids[i].unknown     = 0;
2780
2781                 status2 = lsa_lookup_name(state, mem_ctx, name, &sid, &atype);
2782                 if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
2783                         status = STATUS_SOME_UNMAPPED;
2784                         continue;
2785                 }
2786
2787                 rtype = samdb_atype_map(atype);
2788                 if (rtype == SID_NAME_UNKNOWN) {
2789                         status = STATUS_SOME_UNMAPPED;
2790                         continue;
2791                 }
2792
2793                 status2 = lsa_authority_list(state, mem_ctx, sid, r->out.domains, &sid_index);
2794                 if (!NT_STATUS_IS_OK(status2)) {
2795                         return status2;
2796                 }
2797
2798                 r->out.sids->sids[i].sid_type    = rtype;
2799                 r->out.sids->sids[i].rid         = sid->sub_auths[sid->num_auths-1];
2800                 r->out.sids->sids[i].sid_index   = sid_index;
2801                 r->out.sids->sids[i].unknown     = 0;
2802         }
2803         
2804         return status;
2805 }
2806
2807 /* 
2808   lsa_LookupNames 
2809 */
2810 static NTSTATUS lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2811                        struct lsa_LookupNames *r)
2812 {
2813         struct lsa_LookupNames2 r2;
2814         NTSTATUS status;
2815         int i;
2816
2817         r2.in.handle    = r->in.handle;
2818         r2.in.num_names = r->in.num_names;
2819         r2.in.names     = r->in.names;
2820         r2.in.sids      = NULL;
2821         r2.in.level     = r->in.level;
2822         r2.in.count     = r->in.count;
2823         r2.in.unknown1  = 0;
2824         r2.in.unknown2  = 0;
2825         r2.out.count    = r->out.count;
2826
2827         status = lsa_LookupNames2(dce_call, mem_ctx, &r2);
2828         if (dce_call->fault_code != 0) {
2829                 return status;
2830         }
2831
2832         r->out.domains = r2.out.domains;
2833         r->out.sids = talloc(mem_ctx, struct lsa_TransSidArray);
2834         if (r->out.sids == NULL) {
2835                 return NT_STATUS_NO_MEMORY;
2836         }
2837         r->out.sids->count = r2.out.sids->count;
2838         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid, 
2839                                            r->out.sids->count);
2840         if (r->out.sids->sids == NULL) {
2841                 return NT_STATUS_NO_MEMORY;
2842         }
2843         for (i=0;i<r->out.sids->count;i++) {
2844                 r->out.sids->sids[i].sid_type    = r2.out.sids->sids[i].sid_type;
2845                 r->out.sids->sids[i].rid         = r2.out.sids->sids[i].rid;
2846                 r->out.sids->sids[i].sid_index   = r2.out.sids->sids[i].sid_index;
2847         }
2848
2849         return status;
2850 }
2851
2852 /* 
2853   lsa_CREDRWRITE 
2854 */
2855 static NTSTATUS lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2856                        struct lsa_CREDRWRITE *r)
2857 {
2858         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2859 }
2860
2861
2862 /* 
2863   lsa_CREDRREAD 
2864 */
2865 static NTSTATUS lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2866                        struct lsa_CREDRREAD *r)
2867 {
2868         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2869 }
2870
2871
2872 /* 
2873   lsa_CREDRENUMERATE 
2874 */
2875 static NTSTATUS lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2876                        struct lsa_CREDRENUMERATE *r)
2877 {
2878         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2879 }
2880
2881
2882 /* 
2883   lsa_CREDRWRITEDOMAINCREDENTIALS 
2884 */
2885 static NTSTATUS lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2886                        struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
2887 {
2888         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2889 }
2890
2891
2892 /* 
2893   lsa_CREDRREADDOMAINCREDENTIALS 
2894 */
2895 static NTSTATUS lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2896                        struct lsa_CREDRREADDOMAINCREDENTIALS *r)
2897 {
2898         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2899 }
2900
2901
2902 /* 
2903   lsa_CREDRDELETE 
2904 */
2905 static NTSTATUS lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2906                        struct lsa_CREDRDELETE *r)
2907 {
2908         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2909 }
2910
2911
2912 /* 
2913   lsa_CREDRGETTARGETINFO 
2914 */
2915 static NTSTATUS lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2916                        struct lsa_CREDRGETTARGETINFO *r)
2917 {
2918         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2919 }
2920
2921
2922 /* 
2923   lsa_CREDRPROFILELOADED 
2924 */
2925 static NTSTATUS lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2926                        struct lsa_CREDRPROFILELOADED *r)
2927 {
2928         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2929 }
2930
2931
2932 /* 
2933   lsa_CREDRGETSESSIONTYPES 
2934 */
2935 static NTSTATUS lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2936                        struct lsa_CREDRGETSESSIONTYPES *r)
2937 {
2938         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2939 }
2940
2941
2942 /* 
2943   lsa_LSARREGISTERAUDITEVENT 
2944 */
2945 static NTSTATUS lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2946                        struct lsa_LSARREGISTERAUDITEVENT *r)
2947 {
2948         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2949 }
2950
2951
2952 /* 
2953   lsa_LSARGENAUDITEVENT 
2954 */
2955 static NTSTATUS lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2956                        struct lsa_LSARGENAUDITEVENT *r)
2957 {
2958         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2959 }
2960
2961
2962 /* 
2963   lsa_LSARUNREGISTERAUDITEVENT 
2964 */
2965 static NTSTATUS lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2966                        struct lsa_LSARUNREGISTERAUDITEVENT *r)
2967 {
2968         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2969 }
2970
2971
2972 /* 
2973   lsa_LSARQUERYFORESTTRUSTINFORMATION 
2974 */
2975 static NTSTATUS lsa_LSARQUERYFORESTTRUSTINFORMATION(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2976                        struct lsa_LSARQUERYFORESTTRUSTINFORMATION *r)
2977 {
2978         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2979 }
2980
2981
2982 /* 
2983   lsa_LSARSETFORESTTRUSTINFORMATION 
2984 */
2985 static NTSTATUS lsa_LSARSETFORESTTRUSTINFORMATION(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2986                        struct lsa_LSARSETFORESTTRUSTINFORMATION *r)
2987 {
2988         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2989 }
2990
2991
2992 /* 
2993   lsa_CREDRRENAME 
2994 */
2995 static NTSTATUS lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2996                        struct lsa_CREDRRENAME *r)
2997 {
2998         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2999 }
3000
3001
3002
3003 /* 
3004   lsa_LSAROPENPOLICYSCE 
3005 */
3006 static NTSTATUS lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3007                        struct lsa_LSAROPENPOLICYSCE *r)
3008 {
3009         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3010 }
3011
3012
3013 /* 
3014   lsa_LSARADTREGISTERSECURITYEVENTSOURCE 
3015 */
3016 static NTSTATUS lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3017                        struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
3018 {
3019         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3020 }
3021
3022
3023 /* 
3024   lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE 
3025 */
3026 static NTSTATUS lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3027                        struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
3028 {
3029         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3030 }
3031
3032
3033 /* 
3034   lsa_LSARADTREPORTSECURITYEVENT 
3035 */
3036 static NTSTATUS lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3037                        struct lsa_LSARADTREPORTSECURITYEVENT *r)
3038 {
3039         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3040 }
3041
3042
3043 /* include the generated boilerplate */
3044 #include "librpc/gen_ndr/ndr_lsa_s.c"