s4-lsasrv: make sure only admins can alter privileges
[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
32 /*
33   this type allows us to distinguish handle types
34 */
35
36 /*
37   state associated with a lsa_OpenAccount() operation
38 */
39 struct lsa_account_state {
40         struct lsa_policy_state *policy;
41         uint32_t access_mask;
42         struct dom_sid *account_sid;
43 };
44
45
46 /*
47   state associated with a lsa_OpenSecret() operation
48 */
49 struct lsa_secret_state {
50         struct lsa_policy_state *policy;
51         uint32_t access_mask;
52         struct ldb_dn *secret_dn;
53         struct ldb_context *sam_ldb;
54         bool global;
55 };
56
57 /*
58   state associated with a lsa_OpenTrustedDomain() operation
59 */
60 struct lsa_trusted_domain_state {
61         struct lsa_policy_state *policy;
62         uint32_t access_mask;
63         struct ldb_dn *trusted_domain_dn;
64         struct ldb_dn *trusted_domain_user_dn;
65 };
66
67 /*
68   this is based on the samba3 function make_lsa_object_sd()
69   It uses the same logic, but with samba4 helper functions
70  */
71 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx, 
72                                     struct security_descriptor **sd,
73                                     struct dom_sid *sid, 
74                                     uint32_t sid_access)
75 {
76         NTSTATUS status;
77         uint32_t rid;
78         struct dom_sid *domain_sid, *domain_admins_sid;
79         const char *domain_admins_sid_str, *sidstr;
80         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
81
82         status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
83         NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
84
85         domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
86         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid, tmp_ctx);
87
88         domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
89         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid_str, tmp_ctx);
90         
91         sidstr = dom_sid_string(tmp_ctx, sid);
92         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, tmp_ctx);
93                                                       
94         *sd = security_descriptor_dacl_create(mem_ctx,
95                                               0, sidstr, NULL,
96
97                                               SID_WORLD,
98                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
99                                               SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
100                                               
101                                               SID_BUILTIN_ADMINISTRATORS,
102                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
103                                               SEC_GENERIC_ALL, 0,
104                                               
105                                               SID_BUILTIN_ACCOUNT_OPERATORS,
106                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
107                                               SEC_GENERIC_ALL, 0,
108                                               
109                                               domain_admins_sid_str,
110                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
111                                               SEC_GENERIC_ALL, 0,
112
113                                               sidstr,
114                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
115                                               sid_access, 0,
116
117                                               NULL);
118         talloc_free(tmp_ctx);
119
120         NT_STATUS_HAVE_NO_MEMORY(*sd);
121
122         return NT_STATUS_OK;
123 }
124
125
126 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, 
127                                       TALLOC_CTX *mem_ctx,
128                                       struct lsa_EnumAccountRights *r);
129
130 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, 
131                                            TALLOC_CTX *mem_ctx,
132                                            struct lsa_policy_state *state,
133                                            int ldb_flag,
134                                            struct dom_sid *sid,
135                                            const struct lsa_RightSet *rights);
136
137 /* 
138   lsa_Close 
139 */
140 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
141                           struct lsa_Close *r)
142 {
143         struct dcesrv_handle *h;
144
145         *r->out.handle = *r->in.handle;
146
147         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
148
149         talloc_free(h);
150
151         ZERO_STRUCTP(r->out.handle);
152
153         return NT_STATUS_OK;
154 }
155
156
157 /* 
158   lsa_Delete 
159 */
160 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
161                            struct lsa_Delete *r)
162 {
163         return NT_STATUS_NOT_SUPPORTED;
164 }
165
166
167 /* 
168   lsa_DeleteObject
169 */
170 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
171                        struct lsa_DeleteObject *r)
172 {
173         struct dcesrv_handle *h;
174         int ret;
175
176         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
177
178         if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
179                 struct lsa_secret_state *secret_state = h->data;
180
181                 /* Ensure user is permitted to delete this... */
182                 switch (security_session_user_level(dce_call->conn->auth_state.session_info))
183                 {
184                 case SECURITY_SYSTEM:
185                 case SECURITY_ADMINISTRATOR:
186                         break;
187                 default:
188                         /* Users and annonymous are not allowed delete things */
189                         return NT_STATUS_ACCESS_DENIED;
190                 }
191
192                 ret = ldb_delete(secret_state->sam_ldb, 
193                                  secret_state->secret_dn);
194                 talloc_free(h);
195                 if (ret != 0) {
196                         return NT_STATUS_INVALID_HANDLE;
197                 }
198
199                 ZERO_STRUCTP(r->out.handle);
200
201                 return NT_STATUS_OK;
202         } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
203                 struct lsa_trusted_domain_state *trusted_domain_state = 
204                         talloc_get_type(h->data, struct lsa_trusted_domain_state);
205                 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
206                 if (ret != 0) {
207                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
208                 }
209
210                 ret = ldb_delete(trusted_domain_state->policy->sam_ldb, 
211                                  trusted_domain_state->trusted_domain_dn);
212                 if (ret != 0) {
213                         ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
214                         return NT_STATUS_INVALID_HANDLE;
215                 }
216
217                 if (trusted_domain_state->trusted_domain_user_dn) {
218                         ret = ldb_delete(trusted_domain_state->policy->sam_ldb, 
219                                          trusted_domain_state->trusted_domain_user_dn);
220                         if (ret != 0) {
221                                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
222                                 return NT_STATUS_INVALID_HANDLE;
223                         }
224                 }
225
226                 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
227                 if (ret != 0) {
228                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
229                 }
230                 talloc_free(h);
231                 ZERO_STRUCTP(r->out.handle);
232
233                 return NT_STATUS_OK;
234         } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
235                 struct lsa_RightSet *rights;
236                 struct lsa_account_state *astate;
237                 struct lsa_EnumAccountRights r2;
238                 NTSTATUS status;
239
240                 rights = talloc(mem_ctx, struct lsa_RightSet);
241
242                 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
243                 
244                 astate = h->data;
245
246                 r2.in.handle = &astate->policy->handle->wire_handle;
247                 r2.in.sid = astate->account_sid;
248                 r2.out.rights = rights;
249
250                 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
251                    but we have a LSA_HANDLE_ACCOUNT here, so this call
252                    will always fail */
253                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
254                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
255                         return NT_STATUS_OK;
256                 }
257
258                 if (!NT_STATUS_IS_OK(status)) {
259                         return status;
260                 }
261
262                 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
263                                                     LDB_FLAG_MOD_DELETE, astate->account_sid,
264                                                     r2.out.rights);
265                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
266                         return NT_STATUS_OK;
267                 }
268
269                 if (!NT_STATUS_IS_OK(status)) {
270                         return status;
271                 }
272
273                 ZERO_STRUCTP(r->out.handle);
274         } 
275         
276         return NT_STATUS_INVALID_HANDLE;
277 }
278
279
280 /* 
281   lsa_EnumPrivs 
282 */
283 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
284                               struct lsa_EnumPrivs *r)
285 {
286         struct dcesrv_handle *h;
287         struct lsa_policy_state *state;
288         int i;
289         const char *privname;
290
291         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
292
293         state = h->data;
294
295         i = *r->in.resume_handle;
296         if (i == 0) i = 1;
297
298         while ((privname = sec_privilege_name(i)) &&
299                r->out.privs->count < r->in.max_count) {
300                 struct lsa_PrivEntry *e;
301
302                 r->out.privs->privs = talloc_realloc(r->out.privs,
303                                                        r->out.privs->privs, 
304                                                        struct lsa_PrivEntry, 
305                                                        r->out.privs->count+1);
306                 if (r->out.privs->privs == NULL) {
307                         return NT_STATUS_NO_MEMORY;
308                 }
309                 e = &r->out.privs->privs[r->out.privs->count];
310                 e->luid.low = i;
311                 e->luid.high = 0;
312                 e->name.string = privname;
313                 r->out.privs->count++;
314                 i++;
315         }
316
317         *r->out.resume_handle = i;
318
319         return NT_STATUS_OK;
320 }
321
322
323 /* 
324   lsa_QuerySecObj 
325 */
326 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
327                                          struct lsa_QuerySecurity *r)
328 {
329         struct dcesrv_handle *h;
330         struct security_descriptor *sd;
331         NTSTATUS status;
332         struct dom_sid *sid;
333
334         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
335
336         sid = dce_call->conn->auth_state.session_info->security_token->user_sid;
337
338         if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
339                 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 0);
340         } else  if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
341                 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 
342                                              LSA_ACCOUNT_ALL_ACCESS);
343         } else {
344                 return NT_STATUS_INVALID_HANDLE;
345         }
346         NT_STATUS_NOT_OK_RETURN(status);
347
348         (*r->out.sdbuf) = talloc(mem_ctx, struct sec_desc_buf);
349         NT_STATUS_HAVE_NO_MEMORY(*r->out.sdbuf);
350
351         (*r->out.sdbuf)->sd = sd;
352         
353         return NT_STATUS_OK;
354 }
355
356
357 /* 
358   lsa_SetSecObj 
359 */
360 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
361                               struct lsa_SetSecObj *r)
362 {
363         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
364 }
365
366
367 /* 
368   lsa_ChangePassword 
369 */
370 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
371                                    struct lsa_ChangePassword *r)
372 {
373         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
374 }
375
376 /* 
377   dssetup_DsRoleGetPrimaryDomainInformation 
378
379   This is not an LSA call, but is the only call left on the DSSETUP
380   pipe (after the pipe was truncated), and needs lsa_get_policy_state
381 */
382 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call, 
383                                                  TALLOC_CTX *mem_ctx,
384                                                  struct dssetup_DsRoleGetPrimaryDomainInformation *r)
385 {
386         union dssetup_DsRoleInfo *info;
387
388         info = talloc(mem_ctx, union dssetup_DsRoleInfo);
389         W_ERROR_HAVE_NO_MEMORY(info);
390
391         switch (r->in.level) {
392         case DS_ROLE_BASIC_INFORMATION:
393         {
394                 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
395                 uint32_t flags = 0;
396                 const char *domain = NULL;
397                 const char *dns_domain = NULL;
398                 const char *forest = NULL;
399                 struct GUID domain_guid;
400                 struct lsa_policy_state *state;
401
402                 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
403                 if (!NT_STATUS_IS_OK(status)) {
404                         return ntstatus_to_werror(status);
405                 }
406
407                 ZERO_STRUCT(domain_guid);
408
409                 switch (lp_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
410                 case ROLE_STANDALONE:
411                         role            = DS_ROLE_STANDALONE_SERVER;
412                         break;
413                 case ROLE_DOMAIN_MEMBER:
414                         role            = DS_ROLE_MEMBER_SERVER;
415                         break;
416                 case ROLE_DOMAIN_CONTROLLER:
417                         if (samdb_is_pdc(state->sam_ldb)) {
418                                 role    = DS_ROLE_PRIMARY_DC;
419                         } else {
420                                 role    = DS_ROLE_BACKUP_DC;
421                         }
422                         break;
423                 }
424
425                 switch (lp_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
426                 case ROLE_STANDALONE:
427                         domain          = talloc_strdup(mem_ctx, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx));
428                         W_ERROR_HAVE_NO_MEMORY(domain);
429                         break;
430                 case ROLE_DOMAIN_MEMBER:
431                         domain          = talloc_strdup(mem_ctx, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx));
432                         W_ERROR_HAVE_NO_MEMORY(domain);
433                         /* TODO: what is with dns_domain and forest and guid? */
434                         break;
435                 case ROLE_DOMAIN_CONTROLLER:
436                         flags           = DS_ROLE_PRIMARY_DS_RUNNING;
437
438                         if (state->mixed_domain == 1) {
439                                 flags   |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
440                         }
441                         
442                         domain          = state->domain_name;
443                         dns_domain      = state->domain_dns;
444                         forest          = state->forest_dns;
445
446                         domain_guid     = state->domain_guid;
447                         flags   |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
448                         break;
449                 }
450
451                 info->basic.role        = role; 
452                 info->basic.flags       = flags;
453                 info->basic.domain      = domain;
454                 info->basic.dns_domain  = dns_domain;
455                 info->basic.forest      = forest;
456                 info->basic.domain_guid = domain_guid;
457
458                 r->out.info = info;
459                 return WERR_OK;
460         }
461         case DS_ROLE_UPGRADE_STATUS:
462         {
463                 info->upgrade.upgrading     = DS_ROLE_NOT_UPGRADING;
464                 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
465
466                 r->out.info = info;
467                 return WERR_OK;
468         }
469         case DS_ROLE_OP_STATUS:
470         {
471                 info->opstatus.status = DS_ROLE_OP_IDLE;
472
473                 r->out.info = info;
474                 return WERR_OK;
475         }
476         default:
477                 return WERR_INVALID_PARAM;
478         }
479
480         return WERR_INVALID_PARAM;
481 }
482
483 /*
484   fill in the AccountDomain info
485 */
486 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
487                                        struct lsa_DomainInfo *info)
488 {
489         info->name.string = state->domain_name;
490         info->sid         = state->domain_sid;
491
492         return NT_STATUS_OK;
493 }
494
495 /*
496   fill in the DNS domain info
497 */
498 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
499                              struct lsa_DnsDomainInfo *info)
500 {
501         info->name.string = state->domain_name;
502         info->sid         = state->domain_sid;
503         info->dns_domain.string = state->domain_dns;
504         info->dns_forest.string = state->forest_dns;
505         info->domain_guid       = state->domain_guid;
506
507         return NT_STATUS_OK;
508 }
509
510 /* 
511   lsa_QueryInfoPolicy2
512 */
513 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
514                                      struct lsa_QueryInfoPolicy2 *r)
515 {
516         struct lsa_policy_state *state;
517         struct dcesrv_handle *h;
518         union lsa_PolicyInformation *info;
519
520         *r->out.info = NULL;
521
522         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
523
524         state = h->data;
525
526         info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
527         if (!info) {
528                 return NT_STATUS_NO_MEMORY;
529         }
530         *r->out.info = info;
531
532         switch (r->in.level) {
533         case LSA_POLICY_INFO_AUDIT_LOG:
534                 /* we don't need to fill in any of this */
535                 ZERO_STRUCT(info->audit_log);
536                 return NT_STATUS_OK;
537         case LSA_POLICY_INFO_AUDIT_EVENTS:
538                 /* we don't need to fill in any of this */
539                 ZERO_STRUCT(info->audit_events);
540                 return NT_STATUS_OK;
541         case LSA_POLICY_INFO_PD:
542                 /* we don't need to fill in any of this */
543                 ZERO_STRUCT(info->pd);
544                 return NT_STATUS_OK;
545
546         case LSA_POLICY_INFO_DOMAIN:
547                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
548         case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
549                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
550         case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
551                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
552
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         qsort(entries, count, sizeof(*entries), 
1641               (comparison_fn_t)compare_DomainInfo);
1642
1643         if (*r->in.resume_handle >= count) {
1644                 *r->out.resume_handle = -1;
1645
1646                 return NT_STATUS_NO_MORE_ENTRIES;
1647         }
1648
1649         /* return the rest, limit by max_size. Note that we 
1650            use the w2k3 element size value of 60 */
1651         r->out.domains->count = count - *r->in.resume_handle;
1652         r->out.domains->count = MIN(r->out.domains->count, 
1653                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
1654
1655         r->out.domains->domains = entries + *r->in.resume_handle;
1656         r->out.domains->count = r->out.domains->count;
1657
1658         if (r->out.domains->count < count - *r->in.resume_handle) {
1659                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
1660                 return STATUS_MORE_ENTRIES;
1661         }
1662
1663         return NT_STATUS_OK;
1664 }
1665
1666 /*
1667   comparison function for sorting lsa_DomainInformation array
1668 */
1669 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
1670 {
1671         return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
1672 }
1673
1674 /* 
1675   lsa_EnumTrustedDomainsEx 
1676 */
1677 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1678                                         struct lsa_EnumTrustedDomainsEx *r)
1679 {
1680         struct dcesrv_handle *policy_handle;
1681         struct lsa_TrustDomainInfoInfoEx *entries;
1682         struct lsa_policy_state *policy_state;
1683         struct ldb_message **domains;
1684         const char *attrs[] = {
1685                 "flatname", 
1686                 "trustPartner",
1687                 "securityIdentifier",
1688                 "trustDirection",
1689                 "trustType",
1690                 "trustAttributes", 
1691                 NULL
1692         };
1693         NTSTATUS nt_status;
1694
1695         int count, i;
1696
1697         *r->out.resume_handle = 0;
1698
1699         r->out.domains->domains = NULL;
1700         r->out.domains->count = 0;
1701
1702         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1703
1704         policy_state = policy_handle->data;
1705
1706         /* search for all users in this domain. This could possibly be cached and 
1707            resumed based on resume_key */
1708         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs, 
1709                              "objectclass=trustedDomain");
1710         if (count == -1) {
1711                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1712         }
1713
1714         /* convert to lsa_DomainInformation format */
1715         entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
1716         if (!entries) {
1717                 return NT_STATUS_NO_MEMORY;
1718         }
1719         for (i=0;i<count;i++) {
1720                 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
1721                 if (!NT_STATUS_IS_OK(nt_status)) {
1722                         return nt_status;
1723                 }
1724         }
1725
1726         /* sort the results by name */
1727         qsort(entries, count, sizeof(*entries), 
1728               (comparison_fn_t)compare_TrustDomainInfoInfoEx);
1729
1730         if (*r->in.resume_handle >= count) {
1731                 *r->out.resume_handle = -1;
1732
1733                 return NT_STATUS_NO_MORE_ENTRIES;
1734         }
1735
1736         /* return the rest, limit by max_size. Note that we 
1737            use the w2k3 element size value of 60 */
1738         r->out.domains->count = count - *r->in.resume_handle;
1739         r->out.domains->count = MIN(r->out.domains->count, 
1740                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
1741
1742         r->out.domains->domains = entries + *r->in.resume_handle;
1743         r->out.domains->count = r->out.domains->count;
1744
1745         if (r->out.domains->count < count - *r->in.resume_handle) {
1746                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
1747                 return STATUS_MORE_ENTRIES;
1748         }
1749
1750         return NT_STATUS_OK;
1751 }
1752
1753
1754 /* 
1755   lsa_OpenAccount 
1756 */
1757 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1758                                 struct lsa_OpenAccount *r)
1759 {
1760         struct dcesrv_handle *h, *ah;
1761         struct lsa_policy_state *state;
1762         struct lsa_account_state *astate;
1763
1764         ZERO_STRUCTP(r->out.acct_handle);
1765
1766         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
1767
1768         state = h->data;
1769
1770         astate = talloc(dce_call->conn, struct lsa_account_state);
1771         if (astate == NULL) {
1772                 return NT_STATUS_NO_MEMORY;
1773         }
1774
1775         astate->account_sid = dom_sid_dup(astate, r->in.sid);
1776         if (astate->account_sid == NULL) {
1777                 talloc_free(astate);
1778                 return NT_STATUS_NO_MEMORY;
1779         }
1780         
1781         astate->policy = talloc_reference(astate, state);
1782         astate->access_mask = r->in.access_mask;
1783
1784         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
1785         if (!ah) {
1786                 talloc_free(astate);
1787                 return NT_STATUS_NO_MEMORY;
1788         }
1789
1790         ah->data = talloc_steal(ah, astate);
1791
1792         *r->out.acct_handle = ah->wire_handle;
1793
1794         return NT_STATUS_OK;
1795 }
1796
1797
1798 /* 
1799   lsa_EnumPrivsAccount 
1800 */
1801 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call, 
1802                                      TALLOC_CTX *mem_ctx,
1803                                      struct lsa_EnumPrivsAccount *r)
1804 {
1805         struct dcesrv_handle *h;
1806         struct lsa_account_state *astate;
1807         int ret, i;
1808         struct ldb_message **res;
1809         const char * const attrs[] = { "privilege", NULL};
1810         struct ldb_message_element *el;
1811         const char *sidstr;
1812         struct lsa_PrivilegeSet *privs;
1813
1814         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
1815
1816         astate = h->data;
1817
1818         privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
1819         if (privs == NULL) {
1820                 return NT_STATUS_NO_MEMORY;
1821         }
1822         privs->count = 0;
1823         privs->unknown = 0;
1824         privs->set = NULL;
1825
1826         *r->out.privs = privs;
1827
1828         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
1829         if (sidstr == NULL) {
1830                 return NT_STATUS_NO_MEMORY;
1831         }
1832
1833         ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs, 
1834                            "objectSid=%s", sidstr);
1835         if (ret != 1) {
1836                 return NT_STATUS_OK;
1837         }
1838
1839         el = ldb_msg_find_element(res[0], "privilege");
1840         if (el == NULL || el->num_values == 0) {
1841                 return NT_STATUS_OK;
1842         }
1843
1844         privs->set = talloc_array(privs,
1845                                   struct lsa_LUIDAttribute, el->num_values);
1846         if (privs->set == NULL) {
1847                 return NT_STATUS_NO_MEMORY;
1848         }
1849
1850         for (i=0;i<el->num_values;i++) {
1851                 int id = sec_privilege_id((const char *)el->values[i].data);
1852                 if (id == -1) {
1853                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1854                 }
1855                 privs->set[i].attribute = 0;
1856                 privs->set[i].luid.low = id;
1857                 privs->set[i].luid.high = 0;
1858         }
1859
1860         privs->count = el->num_values;
1861
1862         return NT_STATUS_OK;
1863 }
1864
1865 /* 
1866   lsa_EnumAccountRights 
1867 */
1868 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, 
1869                                       TALLOC_CTX *mem_ctx,
1870                                       struct lsa_EnumAccountRights *r)
1871 {
1872         struct dcesrv_handle *h;
1873         struct lsa_policy_state *state;
1874         int ret, i;
1875         struct ldb_message **res;
1876         const char * const attrs[] = { "privilege", NULL};
1877         const char *sidstr;
1878         struct ldb_message_element *el;
1879
1880         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
1881
1882         state = h->data;
1883
1884         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
1885         if (sidstr == NULL) {
1886                 return NT_STATUS_NO_MEMORY;
1887         }
1888
1889         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs, 
1890                            "(&(objectSid=%s)(privilege=*))", sidstr);
1891         if (ret == 0) {
1892                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1893         }
1894         if (ret > 1) {
1895                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1896         }
1897         if (ret == -1) {
1898                 DEBUG(3, ("searching for account rights for SID: %s failed: %s", 
1899                           dom_sid_string(mem_ctx, r->in.sid),
1900                           ldb_errstring(state->pdb)));
1901                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1902         }
1903
1904         el = ldb_msg_find_element(res[0], "privilege");
1905         if (el == NULL || el->num_values == 0) {
1906                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1907         }
1908
1909         r->out.rights->count = el->num_values;
1910         r->out.rights->names = talloc_array(r->out.rights, 
1911                                             struct lsa_StringLarge, r->out.rights->count);
1912         if (r->out.rights->names == NULL) {
1913                 return NT_STATUS_NO_MEMORY;
1914         }
1915
1916         for (i=0;i<el->num_values;i++) {
1917                 r->out.rights->names[i].string = (const char *)el->values[i].data;
1918         }
1919
1920         return NT_STATUS_OK;
1921 }
1922
1923
1924
1925 /* 
1926   helper for lsa_AddAccountRights and lsa_RemoveAccountRights
1927 */
1928 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, 
1929                                            TALLOC_CTX *mem_ctx,
1930                                            struct lsa_policy_state *state,
1931                                            int ldb_flag,
1932                                            struct dom_sid *sid,
1933                                            const struct lsa_RightSet *rights)
1934 {
1935         const char *sidstr, *sidndrstr;
1936         struct ldb_message *msg;
1937         struct ldb_message_element *el;
1938         int i, ret;
1939         struct lsa_EnumAccountRights r2;
1940         char *dnstr;
1941
1942         if (security_session_user_level(dce_call->conn->auth_state.session_info) < 
1943             SECURITY_ADMINISTRATOR) {
1944                 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
1945                 return NT_STATUS_ACCESS_DENIED;
1946         }
1947
1948         msg = ldb_msg_new(mem_ctx);
1949         if (msg == NULL) {
1950                 return NT_STATUS_NO_MEMORY;
1951         }
1952
1953         sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
1954         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr, msg);
1955
1956         sidstr = dom_sid_string(msg, sid);
1957         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, msg);
1958
1959         dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
1960         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr, msg);
1961
1962         msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
1963         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg->dn, msg);
1964
1965         if (ldb_flag == LDB_FLAG_MOD_ADD) {
1966                 NTSTATUS status;
1967
1968                 r2.in.handle = &state->handle->wire_handle;
1969                 r2.in.sid = sid;
1970                 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
1971
1972                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
1973                 if (!NT_STATUS_IS_OK(status)) {
1974                         ZERO_STRUCTP(r2.out.rights);
1975                 }
1976         }
1977
1978         for (i=0;i<rights->count;i++) {
1979                 if (sec_privilege_id(rights->names[i].string) == -1) {
1980                         talloc_free(msg);
1981                         return NT_STATUS_NO_SUCH_PRIVILEGE;
1982                 }
1983
1984                 if (ldb_flag == LDB_FLAG_MOD_ADD) {
1985                         int j;
1986                         for (j=0;j<r2.out.rights->count;j++) {
1987                                 if (strcasecmp_m(r2.out.rights->names[j].string, 
1988                                                rights->names[i].string) == 0) {
1989                                         break;
1990                                 }
1991                         }
1992                         if (j != r2.out.rights->count) continue;
1993                 }
1994
1995                 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
1996                 if (ret != LDB_SUCCESS) {
1997                         talloc_free(msg);
1998                         return NT_STATUS_NO_MEMORY;
1999                 }
2000         }
2001
2002         el = ldb_msg_find_element(msg, "privilege");
2003         if (!el) {
2004                 talloc_free(msg);
2005                 return NT_STATUS_OK;
2006         }
2007
2008         el->flags = ldb_flag;
2009
2010         ret = ldb_modify(state->pdb, msg);
2011         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2012                 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2013                         talloc_free(msg);
2014                         return NT_STATUS_NO_MEMORY;
2015                 }
2016                 samdb_msg_add_string(state->pdb, msg, msg, "comment", "added via LSA");
2017                 ret = ldb_add(state->pdb, msg);         
2018         }
2019         if (ret != 0) {
2020                 if (ldb_flag == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2021                         talloc_free(msg);
2022                         return NT_STATUS_OK;
2023                 }
2024                 DEBUG(3, ("Could not %s attributes from %s: %s", 
2025                           ldb_flag == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2026                           ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2027                 talloc_free(msg);
2028                 return NT_STATUS_UNEXPECTED_IO_ERROR;
2029         }
2030
2031         talloc_free(msg);
2032         return NT_STATUS_OK;
2033 }
2034
2035 /* 
2036   lsa_AddPrivilegesToAccount
2037 */
2038 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2039                                            struct lsa_AddPrivilegesToAccount *r)
2040 {
2041         struct lsa_RightSet rights;
2042         struct dcesrv_handle *h;
2043         struct lsa_account_state *astate;
2044         int i;
2045
2046         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2047
2048         astate = h->data;
2049
2050         rights.count = r->in.privs->count;
2051         rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2052         if (rights.names == NULL) {
2053                 return NT_STATUS_NO_MEMORY;
2054         }
2055         for (i=0;i<rights.count;i++) {
2056                 int id = r->in.privs->set[i].luid.low;
2057                 if (r->in.privs->set[i].luid.high) {
2058                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2059                 }
2060                 rights.names[i].string = sec_privilege_name(id);
2061                 if (rights.names[i].string == NULL) {
2062                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2063                 }
2064         }
2065
2066         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
2067                                           LDB_FLAG_MOD_ADD, astate->account_sid,
2068                                           &rights);
2069 }
2070
2071
2072 /* 
2073   lsa_RemovePrivilegesFromAccount
2074 */
2075 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2076                                                 struct lsa_RemovePrivilegesFromAccount *r)
2077 {
2078         struct lsa_RightSet *rights;
2079         struct dcesrv_handle *h;
2080         struct lsa_account_state *astate;
2081         int i;
2082
2083         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2084
2085         astate = h->data;
2086
2087         rights = talloc(mem_ctx, struct lsa_RightSet);
2088
2089         if (r->in.remove_all == 1 && 
2090             r->in.privs == NULL) {
2091                 struct lsa_EnumAccountRights r2;
2092                 NTSTATUS status;
2093
2094                 r2.in.handle = &astate->policy->handle->wire_handle;
2095                 r2.in.sid = astate->account_sid;
2096                 r2.out.rights = rights;
2097
2098                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2099                 if (!NT_STATUS_IS_OK(status)) {
2100                         return status;
2101                 }
2102
2103                 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
2104                                                   LDB_FLAG_MOD_DELETE, astate->account_sid,
2105                                                   r2.out.rights);
2106         }
2107
2108         if (r->in.remove_all != 0) {
2109                 return NT_STATUS_INVALID_PARAMETER;
2110         }
2111
2112         rights->count = r->in.privs->count;
2113         rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2114         if (rights->names == NULL) {
2115                 return NT_STATUS_NO_MEMORY;
2116         }
2117         for (i=0;i<rights->count;i++) {
2118                 int id = r->in.privs->set[i].luid.low;
2119                 if (r->in.privs->set[i].luid.high) {
2120                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2121                 }
2122                 rights->names[i].string = sec_privilege_name(id);
2123                 if (rights->names[i].string == NULL) {
2124                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2125                 }
2126         }
2127
2128         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
2129                                           LDB_FLAG_MOD_DELETE, astate->account_sid,
2130                                           rights);
2131 }
2132
2133
2134 /* 
2135   lsa_GetQuotasForAccount
2136 */
2137 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2138                        struct lsa_GetQuotasForAccount *r)
2139 {
2140         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2141 }
2142
2143
2144 /* 
2145   lsa_SetQuotasForAccount
2146 */
2147 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2148                        struct lsa_SetQuotasForAccount *r)
2149 {
2150         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2151 }
2152
2153
2154 /* 
2155   lsa_GetSystemAccessAccount
2156 */
2157 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2158                        struct lsa_GetSystemAccessAccount *r)
2159 {
2160         int i;
2161         NTSTATUS status;
2162         struct lsa_EnumPrivsAccount enumPrivs;
2163         struct lsa_PrivilegeSet *privs;
2164
2165         privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2166         if (!privs) {
2167                 return NT_STATUS_NO_MEMORY;
2168         }
2169         privs->count = 0;
2170         privs->unknown = 0;
2171         privs->set = NULL;
2172
2173         enumPrivs.in.handle = r->in.handle;
2174         enumPrivs.out.privs = &privs;
2175
2176         status = dcesrv_lsa_EnumPrivsAccount(dce_call, mem_ctx, &enumPrivs);
2177         if (!NT_STATUS_IS_OK(status)) {
2178                 return status;
2179         }       
2180
2181         *(r->out.access_mask) = 0x00000000;
2182
2183         for (i = 0; i < privs->count; i++) {
2184                 int priv = privs->set[i].luid.low;
2185
2186                 switch (priv) {
2187                 case SEC_PRIV_INTERACTIVE_LOGON:
2188                         *(r->out.access_mask) |= LSA_POLICY_MODE_INTERACTIVE;
2189                         break;
2190                 case SEC_PRIV_NETWORK_LOGON:
2191                         *(r->out.access_mask) |= LSA_POLICY_MODE_NETWORK;
2192                         break;
2193                 case SEC_PRIV_REMOTE_INTERACTIVE_LOGON:
2194                         *(r->out.access_mask) |= LSA_POLICY_MODE_REMOTE_INTERACTIVE;
2195                         break;
2196                 }
2197         }
2198
2199         return NT_STATUS_OK;
2200 }
2201
2202
2203 /* 
2204   lsa_SetSystemAccessAccount
2205 */
2206 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2207                        struct lsa_SetSystemAccessAccount *r)
2208 {
2209         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2210 }
2211
2212
2213 /* 
2214   lsa_CreateSecret 
2215 */
2216 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2217                                  struct lsa_CreateSecret *r)
2218 {
2219         struct dcesrv_handle *policy_handle;
2220         struct lsa_policy_state *policy_state;
2221         struct lsa_secret_state *secret_state;
2222         struct dcesrv_handle *handle;
2223         struct ldb_message **msgs, *msg;
2224         const char *attrs[] = {
2225                 NULL
2226         };
2227
2228         const char *name;
2229
2230         int ret;
2231
2232         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2233         ZERO_STRUCTP(r->out.sec_handle);
2234         
2235         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
2236         {
2237         case SECURITY_SYSTEM:
2238         case SECURITY_ADMINISTRATOR:
2239                 break;
2240         default:
2241                 /* Users and annonymous are not allowed create secrets */
2242                 return NT_STATUS_ACCESS_DENIED;
2243         }
2244
2245         policy_state = policy_handle->data;
2246
2247         if (!r->in.name.string) {
2248                 return NT_STATUS_INVALID_PARAMETER;
2249         }
2250         
2251         secret_state = talloc(mem_ctx, struct lsa_secret_state);
2252         if (!secret_state) {
2253                 return NT_STATUS_NO_MEMORY;
2254         }
2255         secret_state->policy = policy_state;
2256
2257         msg = ldb_msg_new(mem_ctx);
2258         if (msg == NULL) {
2259                 return NT_STATUS_NO_MEMORY;
2260         }
2261
2262         if (strncmp("G$", r->in.name.string, 2) == 0) {
2263                 const char *name2;
2264                 name = &r->in.name.string[2];
2265                         /* 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) */
2266                 secret_state->sam_ldb = talloc_reference(secret_state, 
2267                                                          samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(secret_state, dce_call->conn->dce_ctx->lp_ctx))); 
2268                 secret_state->global = true;
2269
2270                 if (strlen(name) < 1) {
2271                         return NT_STATUS_INVALID_PARAMETER;
2272                 }
2273
2274                 name2 = talloc_asprintf(mem_ctx, "%s Secret", ldb_binary_encode_string(mem_ctx, name));
2275                 /* search for the secret record */
2276                 ret = gendb_search(secret_state->sam_ldb,
2277                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
2278                                    "(&(cn=%s)(objectclass=secret))", 
2279                                    name2);
2280                 if (ret > 0) {
2281                         return NT_STATUS_OBJECT_NAME_COLLISION;
2282                 }
2283                 
2284                 if (ret == -1) {
2285                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
2286                                  name2, ldb_errstring(secret_state->sam_ldb)));
2287                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2288                 }
2289
2290                 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2291                 if (!name2 || ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2292                         return NT_STATUS_NO_MEMORY;
2293                 }
2294                 
2295                 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name2);
2296         
2297         } else {
2298                 secret_state->global = false;
2299
2300                 name = r->in.name.string;
2301                 if (strlen(name) < 1) {
2302                         return NT_STATUS_INVALID_PARAMETER;
2303                 }
2304
2305                 secret_state->sam_ldb = talloc_reference(secret_state, 
2306                                                          secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
2307                 /* search for the secret record */
2308                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2309                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2310                                    &msgs, attrs,
2311                                    "(&(cn=%s)(objectclass=secret))", 
2312                                    ldb_binary_encode_string(mem_ctx, name));
2313                 if (ret > 0) {
2314                         return NT_STATUS_OBJECT_NAME_COLLISION;
2315                 }
2316                 
2317                 if (ret == -1) {
2318                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
2319                                  name, ldb_errstring(secret_state->sam_ldb)));
2320                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2321                 }
2322
2323                 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb, "cn=%s,cn=LSA Secrets", name);
2324                 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name);
2325         } 
2326
2327         samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "objectClass", "secret");
2328         
2329         secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
2330
2331         /* create the secret */
2332         ret = ldb_add(secret_state->sam_ldb, msg);
2333         if (ret != 0) {
2334                 DEBUG(0,("Failed to create secret record %s: %s\n",
2335                          ldb_dn_get_linearized(msg->dn), 
2336                          ldb_errstring(secret_state->sam_ldb)));
2337                 return NT_STATUS_ACCESS_DENIED;
2338         }
2339
2340         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2341         if (!handle) {
2342                 return NT_STATUS_NO_MEMORY;
2343         }
2344         
2345         handle->data = talloc_steal(handle, secret_state);
2346         
2347         secret_state->access_mask = r->in.access_mask;
2348         secret_state->policy = talloc_reference(secret_state, policy_state);
2349         
2350         *r->out.sec_handle = handle->wire_handle;
2351         
2352         return NT_STATUS_OK;
2353 }
2354
2355
2356 /* 
2357   lsa_OpenSecret 
2358 */
2359 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2360                                struct lsa_OpenSecret *r)
2361 {
2362         struct dcesrv_handle *policy_handle;
2363         
2364         struct lsa_policy_state *policy_state;
2365         struct lsa_secret_state *secret_state;
2366         struct dcesrv_handle *handle;
2367         struct ldb_message **msgs;
2368         const char *attrs[] = {
2369                 NULL
2370         };
2371
2372         const char *name;
2373
2374         int ret;
2375
2376         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2377         ZERO_STRUCTP(r->out.sec_handle);
2378         policy_state = policy_handle->data;
2379
2380         if (!r->in.name.string) {
2381                 return NT_STATUS_INVALID_PARAMETER;
2382         }
2383         
2384         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
2385         {
2386         case SECURITY_SYSTEM:
2387         case SECURITY_ADMINISTRATOR:
2388                 break;
2389         default:
2390                 /* Users and annonymous are not allowed to access secrets */
2391                 return NT_STATUS_ACCESS_DENIED;
2392         }
2393
2394         secret_state = talloc(mem_ctx, struct lsa_secret_state);
2395         if (!secret_state) {
2396                 return NT_STATUS_NO_MEMORY;
2397         }
2398         secret_state->policy = policy_state;
2399
2400         if (strncmp("G$", r->in.name.string, 2) == 0) {
2401                 name = &r->in.name.string[2];
2402                 /* 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) */
2403                 secret_state->sam_ldb = talloc_reference(secret_state, 
2404                                                          samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(secret_state, dce_call->conn->dce_ctx->lp_ctx))); 
2405                 secret_state->global = true;
2406
2407                 if (strlen(name) < 1) {
2408                         return NT_STATUS_INVALID_PARAMETER;
2409                 }
2410
2411                 /* search for the secret record */
2412                 ret = gendb_search(secret_state->sam_ldb,
2413                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
2414                                    "(&(cn=%s Secret)(objectclass=secret))", 
2415                                    ldb_binary_encode_string(mem_ctx, name));
2416                 if (ret == 0) {
2417                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2418                 }
2419                 
2420                 if (ret != 1) {
2421                         DEBUG(0,("Found %d records matching DN %s\n", ret,
2422                                  ldb_dn_get_linearized(policy_state->system_dn)));
2423                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2424                 }
2425         
2426         } else {
2427                 secret_state->global = false;
2428                 secret_state->sam_ldb = talloc_reference(secret_state, 
2429                                  secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
2430
2431                 name = r->in.name.string;
2432                 if (strlen(name) < 1) {
2433                         return NT_STATUS_INVALID_PARAMETER;
2434                 }
2435
2436                 /* search for the secret record */
2437                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2438                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2439                                    &msgs, attrs,
2440                                    "(&(cn=%s)(objectclass=secret))", 
2441                                    ldb_binary_encode_string(mem_ctx, name));
2442                 if (ret == 0) {
2443                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2444                 }
2445                 
2446                 if (ret != 1) {
2447                         DEBUG(0,("Found %d records matching CN=%s\n", 
2448                                  ret, ldb_binary_encode_string(mem_ctx, name)));
2449                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2450                 }
2451         } 
2452
2453         secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
2454         
2455         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2456         if (!handle) {
2457                 return NT_STATUS_NO_MEMORY;
2458         }
2459         
2460         handle->data = talloc_steal(handle, secret_state);
2461         
2462         secret_state->access_mask = r->in.access_mask;
2463         secret_state->policy = talloc_reference(secret_state, policy_state);
2464         
2465         *r->out.sec_handle = handle->wire_handle;
2466         
2467         return NT_STATUS_OK;
2468 }
2469
2470
2471 /* 
2472   lsa_SetSecret 
2473 */
2474 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2475                               struct lsa_SetSecret *r)
2476 {
2477
2478         struct dcesrv_handle *h;
2479         struct lsa_secret_state *secret_state;
2480         struct ldb_message *msg;
2481         DATA_BLOB session_key;
2482         DATA_BLOB crypt_secret, secret;
2483         struct ldb_val val;
2484         int ret;
2485         NTSTATUS status = NT_STATUS_OK;
2486
2487         struct timeval now = timeval_current();
2488         NTTIME nt_now = timeval_to_nttime(&now);
2489
2490         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
2491
2492         secret_state = h->data;
2493
2494         msg = ldb_msg_new(mem_ctx);
2495         if (msg == NULL) {
2496                 return NT_STATUS_NO_MEMORY;
2497         }
2498
2499         msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
2500         if (!msg->dn) {
2501                 return NT_STATUS_NO_MEMORY;
2502         }
2503         status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
2504         if (!NT_STATUS_IS_OK(status)) {
2505                 return status;
2506         }
2507
2508         if (r->in.old_val) {
2509                 /* Decrypt */
2510                 crypt_secret.data = r->in.old_val->data;
2511                 crypt_secret.length = r->in.old_val->size;
2512                 
2513                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
2514                 if (!NT_STATUS_IS_OK(status)) {
2515                         return status;
2516                 }
2517                 
2518                 val.data = secret.data;
2519                 val.length = secret.length;
2520                 
2521                 /* set value */
2522                 if (samdb_msg_add_value(secret_state->sam_ldb, 
2523                                         mem_ctx, msg, "priorValue", &val) != 0) {
2524                         return NT_STATUS_NO_MEMORY; 
2525                 }
2526                 
2527                 /* set old value mtime */
2528                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2529                                          mem_ctx, msg, "priorSetTime", nt_now) != 0) { 
2530                         return NT_STATUS_NO_MEMORY; 
2531                 }
2532
2533         } else {
2534                 /* If the old value is not set, then migrate the
2535                  * current value to the old value */
2536                 const struct ldb_val *old_val;
2537                 NTTIME last_set_time;
2538                 struct ldb_message **res;
2539                 const char *attrs[] = {
2540                         "currentValue",
2541                         "lastSetTime",
2542                         NULL
2543                 };
2544                 
2545                 /* search for the secret record */
2546                 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
2547                                       secret_state->secret_dn, &res, attrs);
2548                 if (ret == 0) {
2549                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2550                 }
2551                 
2552                 if (ret != 1) {
2553                         DEBUG(0,("Found %d records matching dn=%s\n", ret,
2554                                  ldb_dn_get_linearized(secret_state->secret_dn)));
2555                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2556                 }
2557                 
2558                 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
2559                 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
2560                 
2561                 if (old_val) {
2562                         /* set old value */
2563                         if (samdb_msg_add_value(secret_state->sam_ldb, 
2564                                                 mem_ctx, msg, "priorValue", 
2565                                                 old_val) != 0) {
2566                                 return NT_STATUS_NO_MEMORY; 
2567                         }
2568                 } else {
2569                         if (samdb_msg_add_delete(secret_state->sam_ldb, 
2570                                                  mem_ctx, msg, "priorValue")) {
2571                                 return NT_STATUS_NO_MEMORY;
2572                         }
2573                         
2574                 }
2575                 
2576                 /* set old value mtime */
2577                 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
2578                         if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2579                                                  mem_ctx, msg, "priorSetTime", last_set_time) != 0) { 
2580                                 return NT_STATUS_NO_MEMORY; 
2581                         }
2582                 } else {
2583                         if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2584                                                  mem_ctx, msg, "priorSetTime", nt_now) != 0) { 
2585                                 return NT_STATUS_NO_MEMORY; 
2586                         }
2587                 }
2588         }
2589
2590         if (r->in.new_val) {
2591                 /* Decrypt */
2592                 crypt_secret.data = r->in.new_val->data;
2593                 crypt_secret.length = r->in.new_val->size;
2594                 
2595                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
2596                 if (!NT_STATUS_IS_OK(status)) {
2597                         return status;
2598                 }
2599                 
2600                 val.data = secret.data;
2601                 val.length = secret.length;
2602                 
2603                 /* set value */
2604                 if (samdb_msg_add_value(secret_state->sam_ldb, 
2605                                         mem_ctx, msg, "currentValue", &val) != 0) {
2606                         return NT_STATUS_NO_MEMORY; 
2607                 }
2608                 
2609                 /* set new value mtime */
2610                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2611                                          mem_ctx, msg, "lastSetTime", nt_now) != 0) { 
2612                         return NT_STATUS_NO_MEMORY; 
2613                 }
2614                 
2615         } else {
2616                 /* NULL out the NEW value */
2617                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2618                                          mem_ctx, msg, "lastSetTime", nt_now) != 0) { 
2619                         return NT_STATUS_NO_MEMORY; 
2620                 }
2621                 if (samdb_msg_add_delete(secret_state->sam_ldb, 
2622                                          mem_ctx, msg, "currentValue")) {
2623                         return NT_STATUS_NO_MEMORY;
2624                 }
2625         }
2626
2627         /* modify the samdb record */
2628         ret = samdb_replace(secret_state->sam_ldb, mem_ctx, msg);
2629         if (ret != 0) {
2630                 /* we really need samdb.c to return NTSTATUS */
2631                 return NT_STATUS_UNSUCCESSFUL;
2632         }
2633
2634         return NT_STATUS_OK;
2635 }
2636
2637
2638 /* 
2639   lsa_QuerySecret 
2640 */
2641 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2642                                 struct lsa_QuerySecret *r)
2643 {
2644         struct dcesrv_handle *h;
2645         struct lsa_secret_state *secret_state;
2646         struct ldb_message *msg;
2647         DATA_BLOB session_key;
2648         DATA_BLOB crypt_secret, secret;
2649         int ret;
2650         struct ldb_message **res;
2651         const char *attrs[] = {
2652                 "currentValue",
2653                 "priorValue",
2654                 "lastSetTime",
2655                 "priorSetTime", 
2656                 NULL
2657         };
2658
2659         NTSTATUS nt_status;
2660
2661         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
2662
2663         /* Ensure user is permitted to read this... */
2664         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
2665         {
2666         case SECURITY_SYSTEM:
2667         case SECURITY_ADMINISTRATOR:
2668                 break;
2669         default:
2670                 /* Users and annonymous are not allowed to read secrets */
2671                 return NT_STATUS_ACCESS_DENIED;
2672         }
2673
2674         secret_state = h->data;
2675
2676         /* pull all the user attributes */
2677         ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
2678                               secret_state->secret_dn, &res, attrs);
2679         if (ret != 1) {
2680                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2681         }
2682         msg = res[0];
2683         
2684         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
2685         if (!NT_STATUS_IS_OK(nt_status)) {
2686                 return nt_status;
2687         }
2688         
2689         if (r->in.old_val) {
2690                 const struct ldb_val *prior_val;
2691                 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
2692                 if (!r->out.old_val) {
2693                         return NT_STATUS_NO_MEMORY;
2694                 }
2695                 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
2696                 
2697                 if (prior_val && prior_val->length) {
2698                         secret.data = prior_val->data;
2699                         secret.length = prior_val->length;
2700                 
2701                         /* Encrypt */
2702                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
2703                         if (!crypt_secret.length) {
2704                                 return NT_STATUS_NO_MEMORY;
2705                         }
2706                         r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
2707                         if (!r->out.old_val->buf) {
2708                                 return NT_STATUS_NO_MEMORY;
2709                         }
2710                         r->out.old_val->buf->size = crypt_secret.length;
2711                         r->out.old_val->buf->length = crypt_secret.length;
2712                         r->out.old_val->buf->data = crypt_secret.data;
2713                 }
2714         }
2715         
2716         if (r->in.old_mtime) {
2717                 r->out.old_mtime = talloc(mem_ctx, NTTIME);
2718                 if (!r->out.old_mtime) {
2719                         return NT_STATUS_NO_MEMORY;
2720                 }
2721                 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
2722         }
2723         
2724         if (r->in.new_val) {
2725                 const struct ldb_val *new_val;
2726                 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
2727                 if (!r->out.new_val) {
2728                         return NT_STATUS_NO_MEMORY;
2729                 }
2730
2731                 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
2732                 
2733                 if (new_val && new_val->length) {
2734                         secret.data = new_val->data;
2735                         secret.length = new_val->length;
2736                 
2737                         /* Encrypt */
2738                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
2739                         if (!crypt_secret.length) {
2740                                 return NT_STATUS_NO_MEMORY;
2741                         }
2742                         r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
2743                         if (!r->out.new_val->buf) {
2744                                 return NT_STATUS_NO_MEMORY;
2745                         }
2746                         r->out.new_val->buf->length = crypt_secret.length;
2747                         r->out.new_val->buf->size = crypt_secret.length;
2748                         r->out.new_val->buf->data = crypt_secret.data;
2749                 }
2750         }
2751         
2752         if (r->in.new_mtime) {
2753                 r->out.new_mtime = talloc(mem_ctx, NTTIME);
2754                 if (!r->out.new_mtime) {
2755                         return NT_STATUS_NO_MEMORY;
2756                 }
2757                 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
2758         }
2759         
2760         return NT_STATUS_OK;
2761 }
2762
2763
2764 /* 
2765   lsa_LookupPrivValue
2766 */
2767 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call, 
2768                                     TALLOC_CTX *mem_ctx,
2769                                     struct lsa_LookupPrivValue *r)
2770 {
2771         struct dcesrv_handle *h;
2772         struct lsa_policy_state *state;
2773         int id;
2774
2775         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2776
2777         state = h->data;
2778
2779         id = sec_privilege_id(r->in.name->string);
2780         if (id == -1) {
2781                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2782         }
2783
2784         r->out.luid->low = id;
2785         r->out.luid->high = 0;
2786
2787         return NT_STATUS_OK;    
2788 }
2789
2790
2791 /* 
2792   lsa_LookupPrivName 
2793 */
2794 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call, 
2795                                    TALLOC_CTX *mem_ctx,
2796                                    struct lsa_LookupPrivName *r)
2797 {
2798         struct dcesrv_handle *h;
2799         struct lsa_policy_state *state;
2800         struct lsa_StringLarge *name;
2801         const char *privname;
2802
2803         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2804
2805         state = h->data;
2806
2807         if (r->in.luid->high != 0) {
2808                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2809         }
2810
2811         privname = sec_privilege_name(r->in.luid->low);
2812         if (privname == NULL) {
2813                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2814         }
2815
2816         name = talloc(mem_ctx, struct lsa_StringLarge);
2817         if (name == NULL) {
2818                 return NT_STATUS_NO_MEMORY;
2819         }
2820
2821         name->string = privname;
2822
2823         *r->out.name = name;
2824
2825         return NT_STATUS_OK;    
2826 }
2827
2828
2829 /* 
2830   lsa_LookupPrivDisplayName
2831 */
2832 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call, 
2833                                           TALLOC_CTX *mem_ctx,
2834                                           struct lsa_LookupPrivDisplayName *r)
2835 {
2836         struct dcesrv_handle *h;
2837         struct lsa_policy_state *state;
2838         struct lsa_StringLarge *disp_name = NULL;
2839         int id;
2840
2841         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2842
2843         state = h->data;
2844
2845         id = sec_privilege_id(r->in.name->string);
2846         if (id == -1) {
2847                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2848         }
2849
2850         disp_name = talloc(mem_ctx, struct lsa_StringLarge);
2851         if (disp_name == NULL) {
2852                 return NT_STATUS_NO_MEMORY;
2853         }
2854
2855         disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
2856         if (disp_name->string == NULL) {
2857                 return NT_STATUS_INTERNAL_ERROR;
2858         }
2859
2860         *r->out.disp_name = disp_name;
2861         *r->out.returned_language_id = 0;
2862
2863         return NT_STATUS_OK;
2864 }
2865
2866
2867 /* 
2868   lsa_EnumAccountsWithUserRight
2869 */
2870 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call, 
2871                                               TALLOC_CTX *mem_ctx,
2872                                               struct lsa_EnumAccountsWithUserRight *r)
2873 {
2874         struct dcesrv_handle *h;
2875         struct lsa_policy_state *state;
2876         int ret, i;
2877         struct ldb_message **res;
2878         const char * const attrs[] = { "objectSid", NULL};
2879         const char *privname;
2880
2881         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2882
2883         state = h->data;
2884
2885         if (r->in.name == NULL) {
2886                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2887         } 
2888
2889         privname = r->in.name->string;
2890         if (sec_privilege_id(privname) == -1) {
2891                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2892         }
2893
2894         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs, 
2895                            "privilege=%s", privname);
2896         if (ret == -1) {
2897                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2898         }
2899         if (ret == 0) {
2900                 return NT_STATUS_NO_MORE_ENTRIES;
2901         }
2902
2903         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
2904         if (r->out.sids->sids == NULL) {
2905                 return NT_STATUS_NO_MEMORY;
2906         }
2907         for (i=0;i<ret;i++) {
2908                 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
2909                                                                 res[i], "objectSid");
2910                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
2911         }
2912         r->out.sids->num_sids = ret;
2913
2914         return NT_STATUS_OK;
2915 }
2916
2917
2918 /* 
2919   lsa_AddAccountRights
2920 */
2921 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call, 
2922                                      TALLOC_CTX *mem_ctx,
2923                                      struct lsa_AddAccountRights *r)
2924 {
2925         struct dcesrv_handle *h;
2926         struct lsa_policy_state *state;
2927
2928         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2929
2930         state = h->data;
2931
2932         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
2933                                           LDB_FLAG_MOD_ADD,
2934                                           r->in.sid, r->in.rights);
2935 }
2936
2937
2938 /* 
2939   lsa_RemoveAccountRights
2940 */
2941 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call, 
2942                                         TALLOC_CTX *mem_ctx,
2943                                         struct lsa_RemoveAccountRights *r)
2944 {
2945         struct dcesrv_handle *h;
2946         struct lsa_policy_state *state;
2947
2948         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2949
2950         state = h->data;
2951
2952         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
2953                                           LDB_FLAG_MOD_DELETE,
2954                                           r->in.sid, r->in.rights);
2955 }
2956
2957
2958 /* 
2959   lsa_StorePrivateData
2960 */
2961 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2962                        struct lsa_StorePrivateData *r)
2963 {
2964         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2965 }
2966
2967
2968 /* 
2969   lsa_RetrievePrivateData
2970 */
2971 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2972                        struct lsa_RetrievePrivateData *r)
2973 {
2974         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2975 }
2976
2977
2978 /* 
2979   lsa_GetUserName
2980 */
2981 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2982                                 struct lsa_GetUserName *r)
2983 {
2984         NTSTATUS status = NT_STATUS_OK;
2985         const char *account_name;
2986         const char *authority_name;
2987         struct lsa_String *_account_name;
2988         struct lsa_String *_authority_name = NULL;
2989
2990         /* this is what w2k3 does */
2991         r->out.account_name = r->in.account_name;
2992         r->out.authority_name = r->in.authority_name;
2993
2994         if (r->in.account_name
2995             && *r->in.account_name
2996             /* && *(*r->in.account_name)->string */
2997             ) {
2998                 return NT_STATUS_INVALID_PARAMETER;
2999         }
3000
3001         if (r->in.authority_name
3002             && *r->in.authority_name
3003             /* && *(*r->in.authority_name)->string */
3004             ) {
3005                 return NT_STATUS_INVALID_PARAMETER;
3006         }
3007
3008         account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->account_name);
3009         authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->domain_name);
3010
3011         _account_name = talloc(mem_ctx, struct lsa_String);
3012         NT_STATUS_HAVE_NO_MEMORY(_account_name);
3013         _account_name->string = account_name;
3014
3015         if (r->in.authority_name) {
3016                 _authority_name = talloc(mem_ctx, struct lsa_String);
3017                 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3018                 _authority_name->string = authority_name;
3019         }
3020
3021         *r->out.account_name = _account_name;
3022         if (r->out.authority_name) {
3023                 *r->out.authority_name = _authority_name;
3024         }
3025
3026         return status;
3027 }
3028
3029 /*
3030   lsa_SetInfoPolicy2
3031 */
3032 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3033                                    TALLOC_CTX *mem_ctx,
3034                                    struct lsa_SetInfoPolicy2 *r)
3035 {
3036         /* need to support these */
3037         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3038 }
3039
3040 /*
3041   lsa_QueryDomainInformationPolicy
3042 */
3043 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3044                                                  TALLOC_CTX *mem_ctx,
3045                                                  struct lsa_QueryDomainInformationPolicy *r)
3046 {
3047         union lsa_DomainInformationPolicy *info;
3048
3049         info = talloc(r->out.info, union lsa_DomainInformationPolicy);
3050         if (!info) {
3051                 return NT_STATUS_NO_MEMORY;
3052         }
3053
3054         switch (r->in.level) {
3055         case LSA_DOMAIN_INFO_POLICY_EFS:
3056                 talloc_free(info);
3057                 *r->out.info = NULL;
3058                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3059         case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3060         {
3061                 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3062                 struct smb_krb5_context *smb_krb5_context;
3063                 int ret = smb_krb5_init_context(mem_ctx, 
3064                                                         dce_call->event_ctx, 
3065                                                         dce_call->conn->dce_ctx->lp_ctx,
3066                                                         &smb_krb5_context);
3067                 if (ret != 0) {
3068                         talloc_free(info);
3069                         *r->out.info = NULL;
3070                         return NT_STATUS_INTERNAL_ERROR;
3071                 }
3072                 k->enforce_restrictions = 0; /* FIXME, details missing from MS-LSAD 2.2.53 */
3073                 k->service_tkt_lifetime = 0; /* Need to find somewhere to store this, and query in KDC too */
3074                 k->user_tkt_lifetime = 0;    /* Need to find somewhere to store this, and query in KDC too */
3075                 k->user_tkt_renewaltime = 0; /* Need to find somewhere to store this, and query in KDC too */
3076                 k->clock_skew = krb5_get_max_time_skew(smb_krb5_context->krb5_context);
3077                 talloc_free(smb_krb5_context);
3078                 *r->out.info = info;
3079                 return NT_STATUS_OK;
3080         }
3081         default:
3082                 talloc_free(info);
3083                 *r->out.info = NULL;
3084                 return NT_STATUS_INVALID_INFO_CLASS;
3085         }
3086 }
3087
3088 /*
3089   lsa_SetDomInfoPolicy
3090 */
3091 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3092                                               TALLOC_CTX *mem_ctx,
3093                                               struct lsa_SetDomainInformationPolicy *r)
3094 {
3095         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3096 }
3097
3098 /*
3099   lsa_TestCall
3100 */
3101 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3102                              TALLOC_CTX *mem_ctx,
3103                              struct lsa_TestCall *r)
3104 {
3105         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3106 }
3107
3108 /* 
3109   lsa_CREDRWRITE 
3110 */
3111 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3112                        struct lsa_CREDRWRITE *r)
3113 {
3114         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3115 }
3116
3117
3118 /* 
3119   lsa_CREDRREAD 
3120 */
3121 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3122                        struct lsa_CREDRREAD *r)
3123 {