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