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