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