0a5fc54d684e151514d68fa50dbcdc9c8d5576a9
[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         msg = ldb_msg_new(mem_ctx);
1943         if (msg == NULL) {
1944                 return NT_STATUS_NO_MEMORY;
1945         }
1946
1947         sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
1948         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr, msg);
1949
1950         sidstr = dom_sid_string(msg, sid);
1951         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, msg);
1952
1953         dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
1954         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr, msg);
1955
1956         msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
1957         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg->dn, msg);
1958
1959         if (ldb_flag == LDB_FLAG_MOD_ADD) {
1960                 NTSTATUS status;
1961
1962                 r2.in.handle = &state->handle->wire_handle;
1963                 r2.in.sid = sid;
1964                 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
1965
1966                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
1967                 if (!NT_STATUS_IS_OK(status)) {
1968                         ZERO_STRUCTP(r2.out.rights);
1969                 }
1970         }
1971
1972         for (i=0;i<rights->count;i++) {
1973                 if (sec_privilege_id(rights->names[i].string) == -1) {
1974                         talloc_free(msg);
1975                         return NT_STATUS_NO_SUCH_PRIVILEGE;
1976                 }
1977
1978                 if (ldb_flag == LDB_FLAG_MOD_ADD) {
1979                         int j;
1980                         for (j=0;j<r2.out.rights->count;j++) {
1981                                 if (strcasecmp_m(r2.out.rights->names[j].string, 
1982                                                rights->names[i].string) == 0) {
1983                                         break;
1984                                 }
1985                         }
1986                         if (j != r2.out.rights->count) continue;
1987                 }
1988
1989                 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
1990                 if (ret != LDB_SUCCESS) {
1991                         talloc_free(msg);
1992                         return NT_STATUS_NO_MEMORY;
1993                 }
1994         }
1995
1996         el = ldb_msg_find_element(msg, "privilege");
1997         if (!el) {
1998                 talloc_free(msg);
1999                 return NT_STATUS_OK;
2000         }
2001
2002         el->flags = ldb_flag;
2003
2004         ret = ldb_modify(state->pdb, msg);
2005         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2006                 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2007                         talloc_free(msg);
2008                         return NT_STATUS_NO_MEMORY;
2009                 }
2010                 samdb_msg_add_string(state->pdb, msg, msg, "comment", "added via LSA");
2011                 ret = ldb_add(state->pdb, msg);         
2012         }
2013         if (ret != 0) {
2014                 if (ldb_flag == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2015                         talloc_free(msg);
2016                         return NT_STATUS_OK;
2017                 }
2018                 DEBUG(3, ("Could not %s attributes from %s: %s", 
2019                           ldb_flag == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2020                           ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2021                 talloc_free(msg);
2022                 return NT_STATUS_UNEXPECTED_IO_ERROR;
2023         }
2024
2025         talloc_free(msg);
2026         return NT_STATUS_OK;
2027 }
2028
2029 /* 
2030   lsa_AddPrivilegesToAccount
2031 */
2032 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2033                                            struct lsa_AddPrivilegesToAccount *r)
2034 {
2035         struct lsa_RightSet rights;
2036         struct dcesrv_handle *h;
2037         struct lsa_account_state *astate;
2038         int i;
2039
2040         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2041
2042         astate = h->data;
2043
2044         rights.count = r->in.privs->count;
2045         rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2046         if (rights.names == NULL) {
2047                 return NT_STATUS_NO_MEMORY;
2048         }
2049         for (i=0;i<rights.count;i++) {
2050                 int id = r->in.privs->set[i].luid.low;
2051                 if (r->in.privs->set[i].luid.high) {
2052                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2053                 }
2054                 rights.names[i].string = sec_privilege_name(id);
2055                 if (rights.names[i].string == NULL) {
2056                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2057                 }
2058         }
2059
2060         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
2061                                           LDB_FLAG_MOD_ADD, astate->account_sid,
2062                                           &rights);
2063 }
2064
2065
2066 /* 
2067   lsa_RemovePrivilegesFromAccount
2068 */
2069 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2070                                                 struct lsa_RemovePrivilegesFromAccount *r)
2071 {
2072         struct lsa_RightSet *rights;
2073         struct dcesrv_handle *h;
2074         struct lsa_account_state *astate;
2075         int i;
2076
2077         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2078
2079         astate = h->data;
2080
2081         rights = talloc(mem_ctx, struct lsa_RightSet);
2082
2083         if (r->in.remove_all == 1 && 
2084             r->in.privs == NULL) {
2085                 struct lsa_EnumAccountRights r2;
2086                 NTSTATUS status;
2087
2088                 r2.in.handle = &astate->policy->handle->wire_handle;
2089                 r2.in.sid = astate->account_sid;
2090                 r2.out.rights = rights;
2091
2092                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2093                 if (!NT_STATUS_IS_OK(status)) {
2094                         return status;
2095                 }
2096
2097                 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
2098                                                   LDB_FLAG_MOD_DELETE, astate->account_sid,
2099                                                   r2.out.rights);
2100         }
2101
2102         if (r->in.remove_all != 0) {
2103                 return NT_STATUS_INVALID_PARAMETER;
2104         }
2105
2106         rights->count = r->in.privs->count;
2107         rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2108         if (rights->names == NULL) {
2109                 return NT_STATUS_NO_MEMORY;
2110         }
2111         for (i=0;i<rights->count;i++) {
2112                 int id = r->in.privs->set[i].luid.low;
2113                 if (r->in.privs->set[i].luid.high) {
2114                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2115                 }
2116                 rights->names[i].string = sec_privilege_name(id);
2117                 if (rights->names[i].string == NULL) {
2118                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2119                 }
2120         }
2121
2122         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
2123                                           LDB_FLAG_MOD_DELETE, astate->account_sid,
2124                                           rights);
2125 }
2126
2127
2128 /* 
2129   lsa_GetQuotasForAccount
2130 */
2131 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2132                        struct lsa_GetQuotasForAccount *r)
2133 {
2134         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2135 }
2136
2137
2138 /* 
2139   lsa_SetQuotasForAccount
2140 */
2141 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2142                        struct lsa_SetQuotasForAccount *r)
2143 {
2144         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2145 }
2146
2147
2148 /* 
2149   lsa_GetSystemAccessAccount
2150 */
2151 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2152                        struct lsa_GetSystemAccessAccount *r)
2153 {
2154         int i;
2155         NTSTATUS status;
2156         struct lsa_EnumPrivsAccount enumPrivs;
2157         struct lsa_PrivilegeSet *privs;
2158
2159         privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2160         if (!privs) {
2161                 return NT_STATUS_NO_MEMORY;
2162         }
2163         privs->count = 0;
2164         privs->unknown = 0;
2165         privs->set = NULL;
2166
2167         enumPrivs.in.handle = r->in.handle;
2168         enumPrivs.out.privs = &privs;
2169
2170         status = dcesrv_lsa_EnumPrivsAccount(dce_call, mem_ctx, &enumPrivs);
2171         if (!NT_STATUS_IS_OK(status)) {
2172                 return status;
2173         }       
2174
2175         *(r->out.access_mask) = 0x00000000;
2176
2177         for (i = 0; i < privs->count; i++) {
2178                 int priv = privs->set[i].luid.low;
2179
2180                 switch (priv) {
2181                 case SEC_PRIV_INTERACTIVE_LOGON:
2182                         *(r->out.access_mask) |= LSA_POLICY_MODE_INTERACTIVE;
2183                         break;
2184                 case SEC_PRIV_NETWORK_LOGON:
2185                         *(r->out.access_mask) |= LSA_POLICY_MODE_NETWORK;
2186                         break;
2187                 case SEC_PRIV_REMOTE_INTERACTIVE_LOGON:
2188                         *(r->out.access_mask) |= LSA_POLICY_MODE_REMOTE_INTERACTIVE;
2189                         break;
2190                 }
2191         }
2192
2193         return NT_STATUS_OK;
2194 }
2195
2196
2197 /* 
2198   lsa_SetSystemAccessAccount
2199 */
2200 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2201                        struct lsa_SetSystemAccessAccount *r)
2202 {
2203         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2204 }
2205
2206
2207 /* 
2208   lsa_CreateSecret 
2209 */
2210 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2211                                  struct lsa_CreateSecret *r)
2212 {
2213         struct dcesrv_handle *policy_handle;
2214         struct lsa_policy_state *policy_state;
2215         struct lsa_secret_state *secret_state;
2216         struct dcesrv_handle *handle;
2217         struct ldb_message **msgs, *msg;
2218         const char *attrs[] = {
2219                 NULL
2220         };
2221
2222         const char *name;
2223
2224         int ret;
2225
2226         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2227         ZERO_STRUCTP(r->out.sec_handle);
2228         
2229         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
2230         {
2231         case SECURITY_SYSTEM:
2232         case SECURITY_ADMINISTRATOR:
2233                 break;
2234         default:
2235                 /* Users and annonymous are not allowed create secrets */
2236                 return NT_STATUS_ACCESS_DENIED;
2237         }
2238
2239         policy_state = policy_handle->data;
2240
2241         if (!r->in.name.string) {
2242                 return NT_STATUS_INVALID_PARAMETER;
2243         }
2244         
2245         secret_state = talloc(mem_ctx, struct lsa_secret_state);
2246         if (!secret_state) {
2247                 return NT_STATUS_NO_MEMORY;
2248         }
2249         secret_state->policy = policy_state;
2250
2251         msg = ldb_msg_new(mem_ctx);
2252         if (msg == NULL) {
2253                 return NT_STATUS_NO_MEMORY;
2254         }
2255
2256         if (strncmp("G$", r->in.name.string, 2) == 0) {
2257                 const char *name2;
2258                 name = &r->in.name.string[2];
2259                         /* 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) */
2260                 secret_state->sam_ldb = talloc_reference(secret_state, 
2261                                                          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))); 
2262                 secret_state->global = true;
2263
2264                 if (strlen(name) < 1) {
2265                         return NT_STATUS_INVALID_PARAMETER;
2266                 }
2267
2268                 name2 = talloc_asprintf(mem_ctx, "%s Secret", ldb_binary_encode_string(mem_ctx, name));
2269                 /* search for the secret record */
2270                 ret = gendb_search(secret_state->sam_ldb,
2271                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
2272                                    "(&(cn=%s)(objectclass=secret))", 
2273                                    name2);
2274                 if (ret > 0) {
2275                         return NT_STATUS_OBJECT_NAME_COLLISION;
2276                 }
2277                 
2278                 if (ret == -1) {
2279                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
2280                                  name2, ldb_errstring(secret_state->sam_ldb)));
2281                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2282                 }
2283
2284                 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2285                 if (!name2 || ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2286                         return NT_STATUS_NO_MEMORY;
2287                 }
2288                 
2289                 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name2);
2290         
2291         } else {
2292                 secret_state->global = false;
2293
2294                 name = r->in.name.string;
2295                 if (strlen(name) < 1) {
2296                         return NT_STATUS_INVALID_PARAMETER;
2297                 }
2298
2299                 secret_state->sam_ldb = talloc_reference(secret_state, 
2300                                                          secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
2301                 /* search for the secret record */
2302                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2303                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2304                                    &msgs, attrs,
2305                                    "(&(cn=%s)(objectclass=secret))", 
2306                                    ldb_binary_encode_string(mem_ctx, name));
2307                 if (ret > 0) {
2308                         return NT_STATUS_OBJECT_NAME_COLLISION;
2309                 }
2310                 
2311                 if (ret == -1) {
2312                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
2313                                  name, ldb_errstring(secret_state->sam_ldb)));
2314                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2315                 }
2316
2317                 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb, "cn=%s,cn=LSA Secrets", name);
2318                 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name);
2319         } 
2320
2321         samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "objectClass", "secret");
2322         
2323         secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
2324
2325         /* create the secret */
2326         ret = ldb_add(secret_state->sam_ldb, msg);
2327         if (ret != 0) {
2328                 DEBUG(0,("Failed to create secret record %s: %s\n",
2329                          ldb_dn_get_linearized(msg->dn), 
2330                          ldb_errstring(secret_state->sam_ldb)));
2331                 return NT_STATUS_ACCESS_DENIED;
2332         }
2333
2334         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2335         if (!handle) {
2336                 return NT_STATUS_NO_MEMORY;
2337         }
2338         
2339         handle->data = talloc_steal(handle, secret_state);
2340         
2341         secret_state->access_mask = r->in.access_mask;
2342         secret_state->policy = talloc_reference(secret_state, policy_state);
2343         
2344         *r->out.sec_handle = handle->wire_handle;
2345         
2346         return NT_STATUS_OK;
2347 }
2348
2349
2350 /* 
2351   lsa_OpenSecret 
2352 */
2353 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2354                                struct lsa_OpenSecret *r)
2355 {
2356         struct dcesrv_handle *policy_handle;
2357         
2358         struct lsa_policy_state *policy_state;
2359         struct lsa_secret_state *secret_state;
2360         struct dcesrv_handle *handle;
2361         struct ldb_message **msgs;
2362         const char *attrs[] = {
2363                 NULL
2364         };
2365
2366         const char *name;
2367
2368         int ret;
2369
2370         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2371         ZERO_STRUCTP(r->out.sec_handle);
2372         policy_state = policy_handle->data;
2373
2374         if (!r->in.name.string) {
2375                 return NT_STATUS_INVALID_PARAMETER;
2376         }
2377         
2378         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
2379         {
2380         case SECURITY_SYSTEM:
2381         case SECURITY_ADMINISTRATOR:
2382                 break;
2383         default:
2384                 /* Users and annonymous are not allowed to access secrets */
2385                 return NT_STATUS_ACCESS_DENIED;
2386         }
2387
2388         secret_state = talloc(mem_ctx, struct lsa_secret_state);
2389         if (!secret_state) {
2390                 return NT_STATUS_NO_MEMORY;
2391         }
2392         secret_state->policy = policy_state;
2393
2394         if (strncmp("G$", r->in.name.string, 2) == 0) {
2395                 name = &r->in.name.string[2];
2396                 /* 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) */
2397                 secret_state->sam_ldb = talloc_reference(secret_state, 
2398                                                          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))); 
2399                 secret_state->global = true;
2400
2401                 if (strlen(name) < 1) {
2402                         return NT_STATUS_INVALID_PARAMETER;
2403                 }
2404
2405                 /* search for the secret record */
2406                 ret = gendb_search(secret_state->sam_ldb,
2407                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
2408                                    "(&(cn=%s Secret)(objectclass=secret))", 
2409                                    ldb_binary_encode_string(mem_ctx, name));
2410                 if (ret == 0) {
2411                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2412                 }
2413                 
2414                 if (ret != 1) {
2415                         DEBUG(0,("Found %d records matching DN %s\n", ret,
2416                                  ldb_dn_get_linearized(policy_state->system_dn)));
2417                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2418                 }
2419         
2420         } else {
2421                 secret_state->global = false;
2422                 secret_state->sam_ldb = talloc_reference(secret_state, 
2423                                  secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
2424
2425                 name = r->in.name.string;
2426                 if (strlen(name) < 1) {
2427                         return NT_STATUS_INVALID_PARAMETER;
2428                 }
2429
2430                 /* search for the secret record */
2431                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2432                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2433                                    &msgs, attrs,
2434                                    "(&(cn=%s)(objectclass=secret))", 
2435                                    ldb_binary_encode_string(mem_ctx, name));
2436                 if (ret == 0) {
2437                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2438                 }
2439                 
2440                 if (ret != 1) {
2441                         DEBUG(0,("Found %d records matching CN=%s\n", 
2442                                  ret, ldb_binary_encode_string(mem_ctx, name)));
2443                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2444                 }
2445         } 
2446
2447         secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
2448         
2449         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2450         if (!handle) {
2451                 return NT_STATUS_NO_MEMORY;
2452         }
2453         
2454         handle->data = talloc_steal(handle, secret_state);
2455         
2456         secret_state->access_mask = r->in.access_mask;
2457         secret_state->policy = talloc_reference(secret_state, policy_state);
2458         
2459         *r->out.sec_handle = handle->wire_handle;
2460         
2461         return NT_STATUS_OK;
2462 }
2463
2464
2465 /* 
2466   lsa_SetSecret 
2467 */
2468 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2469                               struct lsa_SetSecret *r)
2470 {
2471
2472         struct dcesrv_handle *h;
2473         struct lsa_secret_state *secret_state;
2474         struct ldb_message *msg;
2475         DATA_BLOB session_key;
2476         DATA_BLOB crypt_secret, secret;
2477         struct ldb_val val;
2478         int ret;
2479         NTSTATUS status = NT_STATUS_OK;
2480
2481         struct timeval now = timeval_current();
2482         NTTIME nt_now = timeval_to_nttime(&now);
2483
2484         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
2485
2486         secret_state = h->data;
2487
2488         msg = ldb_msg_new(mem_ctx);
2489         if (msg == NULL) {
2490                 return NT_STATUS_NO_MEMORY;
2491         }
2492
2493         msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
2494         if (!msg->dn) {
2495                 return NT_STATUS_NO_MEMORY;
2496         }
2497         status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
2498         if (!NT_STATUS_IS_OK(status)) {
2499                 return status;
2500         }
2501
2502         if (r->in.old_val) {
2503                 /* Decrypt */
2504                 crypt_secret.data = r->in.old_val->data;
2505                 crypt_secret.length = r->in.old_val->size;
2506                 
2507                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
2508                 if (!NT_STATUS_IS_OK(status)) {
2509                         return status;
2510                 }
2511                 
2512                 val.data = secret.data;
2513                 val.length = secret.length;
2514                 
2515                 /* set value */
2516                 if (samdb_msg_add_value(secret_state->sam_ldb, 
2517                                         mem_ctx, msg, "priorValue", &val) != 0) {
2518                         return NT_STATUS_NO_MEMORY; 
2519                 }
2520                 
2521                 /* set old value mtime */
2522                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2523                                          mem_ctx, msg, "priorSetTime", nt_now) != 0) { 
2524                         return NT_STATUS_NO_MEMORY; 
2525                 }
2526
2527         } else {
2528                 /* If the old value is not set, then migrate the
2529                  * current value to the old value */
2530                 const struct ldb_val *old_val;
2531                 NTTIME last_set_time;
2532                 struct ldb_message **res;
2533                 const char *attrs[] = {
2534                         "currentValue",
2535                         "lastSetTime",
2536                         NULL
2537                 };
2538                 
2539                 /* search for the secret record */
2540                 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
2541                                       secret_state->secret_dn, &res, attrs);
2542                 if (ret == 0) {
2543                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2544                 }
2545                 
2546                 if (ret != 1) {
2547                         DEBUG(0,("Found %d records matching dn=%s\n", ret,
2548                                  ldb_dn_get_linearized(secret_state->secret_dn)));
2549                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2550                 }
2551                 
2552                 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
2553                 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
2554                 
2555                 if (old_val) {
2556                         /* set old value */
2557                         if (samdb_msg_add_value(secret_state->sam_ldb, 
2558                                                 mem_ctx, msg, "priorValue", 
2559                                                 old_val) != 0) {
2560                                 return NT_STATUS_NO_MEMORY; 
2561                         }
2562                 } else {
2563                         if (samdb_msg_add_delete(secret_state->sam_ldb, 
2564                                                  mem_ctx, msg, "priorValue")) {
2565                                 return NT_STATUS_NO_MEMORY;
2566                         }
2567                         
2568                 }
2569                 
2570                 /* set old value mtime */
2571                 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
2572                         if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2573                                                  mem_ctx, msg, "priorSetTime", last_set_time) != 0) { 
2574                                 return NT_STATUS_NO_MEMORY; 
2575                         }
2576                 } else {
2577                         if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2578                                                  mem_ctx, msg, "priorSetTime", nt_now) != 0) { 
2579                                 return NT_STATUS_NO_MEMORY; 
2580                         }
2581                 }
2582         }
2583
2584         if (r->in.new_val) {
2585                 /* Decrypt */
2586                 crypt_secret.data = r->in.new_val->data;
2587                 crypt_secret.length = r->in.new_val->size;
2588                 
2589                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
2590                 if (!NT_STATUS_IS_OK(status)) {
2591                         return status;
2592                 }
2593                 
2594                 val.data = secret.data;
2595                 val.length = secret.length;
2596                 
2597                 /* set value */
2598                 if (samdb_msg_add_value(secret_state->sam_ldb, 
2599                                         mem_ctx, msg, "currentValue", &val) != 0) {
2600                         return NT_STATUS_NO_MEMORY; 
2601                 }
2602                 
2603                 /* set new value mtime */
2604                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2605                                          mem_ctx, msg, "lastSetTime", nt_now) != 0) { 
2606                         return NT_STATUS_NO_MEMORY; 
2607                 }
2608                 
2609         } else {
2610                 /* NULL out the NEW value */
2611                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2612                                          mem_ctx, msg, "lastSetTime", nt_now) != 0) { 
2613                         return NT_STATUS_NO_MEMORY; 
2614                 }
2615                 if (samdb_msg_add_delete(secret_state->sam_ldb, 
2616                                          mem_ctx, msg, "currentValue")) {
2617                         return NT_STATUS_NO_MEMORY;
2618                 }
2619         }
2620
2621         /* modify the samdb record */
2622         ret = samdb_replace(secret_state->sam_ldb, mem_ctx, msg);
2623         if (ret != 0) {
2624                 /* we really need samdb.c to return NTSTATUS */
2625                 return NT_STATUS_UNSUCCESSFUL;
2626         }
2627
2628         return NT_STATUS_OK;
2629 }
2630
2631
2632 /* 
2633   lsa_QuerySecret 
2634 */
2635 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2636                                 struct lsa_QuerySecret *r)
2637 {
2638         struct dcesrv_handle *h;
2639         struct lsa_secret_state *secret_state;
2640         struct ldb_message *msg;
2641         DATA_BLOB session_key;
2642         DATA_BLOB crypt_secret, secret;
2643         int ret;
2644         struct ldb_message **res;
2645         const char *attrs[] = {
2646                 "currentValue",
2647                 "priorValue",
2648                 "lastSetTime",
2649                 "priorSetTime", 
2650                 NULL
2651         };
2652
2653         NTSTATUS nt_status;
2654
2655         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
2656
2657         /* Ensure user is permitted to read this... */
2658         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
2659         {
2660         case SECURITY_SYSTEM:
2661         case SECURITY_ADMINISTRATOR:
2662                 break;
2663         default:
2664                 /* Users and annonymous are not allowed to read secrets */
2665                 return NT_STATUS_ACCESS_DENIED;
2666         }
2667
2668         secret_state = h->data;
2669
2670         /* pull all the user attributes */
2671         ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
2672                               secret_state->secret_dn, &res, attrs);
2673         if (ret != 1) {
2674                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2675         }
2676         msg = res[0];
2677         
2678         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
2679         if (!NT_STATUS_IS_OK(nt_status)) {
2680                 return nt_status;
2681         }
2682         
2683         if (r->in.old_val) {
2684                 const struct ldb_val *prior_val;
2685                 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
2686                 if (!r->out.old_val) {
2687                         return NT_STATUS_NO_MEMORY;
2688                 }
2689                 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
2690                 
2691                 if (prior_val && prior_val->length) {
2692                         secret.data = prior_val->data;
2693                         secret.length = prior_val->length;
2694                 
2695                         /* Encrypt */
2696                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
2697                         if (!crypt_secret.length) {
2698                                 return NT_STATUS_NO_MEMORY;
2699                         }
2700                         r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
2701                         if (!r->out.old_val->buf) {
2702                                 return NT_STATUS_NO_MEMORY;
2703                         }
2704                         r->out.old_val->buf->size = crypt_secret.length;
2705                         r->out.old_val->buf->length = crypt_secret.length;
2706                         r->out.old_val->buf->data = crypt_secret.data;
2707                 }
2708         }
2709         
2710         if (r->in.old_mtime) {
2711                 r->out.old_mtime = talloc(mem_ctx, NTTIME);
2712                 if (!r->out.old_mtime) {
2713                         return NT_STATUS_NO_MEMORY;
2714                 }
2715                 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
2716         }
2717         
2718         if (r->in.new_val) {
2719                 const struct ldb_val *new_val;
2720                 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
2721                 if (!r->out.new_val) {
2722                         return NT_STATUS_NO_MEMORY;
2723                 }
2724
2725                 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
2726                 
2727                 if (new_val && new_val->length) {
2728                         secret.data = new_val->data;
2729                         secret.length = new_val->length;
2730                 
2731                         /* Encrypt */
2732                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
2733                         if (!crypt_secret.length) {
2734                                 return NT_STATUS_NO_MEMORY;
2735                         }
2736                         r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
2737                         if (!r->out.new_val->buf) {
2738                                 return NT_STATUS_NO_MEMORY;
2739                         }
2740                         r->out.new_val->buf->length = crypt_secret.length;
2741                         r->out.new_val->buf->size = crypt_secret.length;
2742                         r->out.new_val->buf->data = crypt_secret.data;
2743                 }
2744         }
2745         
2746         if (r->in.new_mtime) {
2747                 r->out.new_mtime = talloc(mem_ctx, NTTIME);
2748                 if (!r->out.new_mtime) {
2749                         return NT_STATUS_NO_MEMORY;
2750                 }
2751                 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
2752         }
2753         
2754         return NT_STATUS_OK;
2755 }
2756
2757
2758 /* 
2759   lsa_LookupPrivValue
2760 */
2761 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call, 
2762                                     TALLOC_CTX *mem_ctx,
2763                                     struct lsa_LookupPrivValue *r)
2764 {
2765         struct dcesrv_handle *h;
2766         struct lsa_policy_state *state;
2767         int id;
2768
2769         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2770
2771         state = h->data;
2772
2773         id = sec_privilege_id(r->in.name->string);
2774         if (id == -1) {
2775                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2776         }
2777
2778         r->out.luid->low = id;
2779         r->out.luid->high = 0;
2780
2781         return NT_STATUS_OK;    
2782 }
2783
2784
2785 /* 
2786   lsa_LookupPrivName 
2787 */
2788 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call, 
2789                                    TALLOC_CTX *mem_ctx,
2790                                    struct lsa_LookupPrivName *r)
2791 {
2792         struct dcesrv_handle *h;
2793         struct lsa_policy_state *state;
2794         struct lsa_StringLarge *name;
2795         const char *privname;
2796
2797         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2798
2799         state = h->data;
2800
2801         if (r->in.luid->high != 0) {
2802                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2803         }
2804
2805         privname = sec_privilege_name(r->in.luid->low);
2806         if (privname == NULL) {
2807                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2808         }
2809
2810         name = talloc(mem_ctx, struct lsa_StringLarge);
2811         if (name == NULL) {
2812                 return NT_STATUS_NO_MEMORY;
2813         }
2814
2815         name->string = privname;
2816
2817         *r->out.name = name;
2818
2819         return NT_STATUS_OK;    
2820 }
2821
2822
2823 /* 
2824   lsa_LookupPrivDisplayName
2825 */
2826 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call, 
2827                                           TALLOC_CTX *mem_ctx,
2828                                           struct lsa_LookupPrivDisplayName *r)
2829 {
2830         struct dcesrv_handle *h;
2831         struct lsa_policy_state *state;
2832         struct lsa_StringLarge *disp_name = NULL;
2833         int id;
2834
2835         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2836
2837         state = h->data;
2838
2839         id = sec_privilege_id(r->in.name->string);
2840         if (id == -1) {
2841                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2842         }
2843
2844         disp_name = talloc(mem_ctx, struct lsa_StringLarge);
2845         if (disp_name == NULL) {
2846                 return NT_STATUS_NO_MEMORY;
2847         }
2848
2849         disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
2850         if (disp_name->string == NULL) {
2851                 return NT_STATUS_INTERNAL_ERROR;
2852         }
2853
2854         *r->out.disp_name = disp_name;
2855         *r->out.returned_language_id = 0;
2856
2857         return NT_STATUS_OK;
2858 }
2859
2860
2861 /* 
2862   lsa_EnumAccountsWithUserRight
2863 */
2864 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call, 
2865                                               TALLOC_CTX *mem_ctx,
2866                                               struct lsa_EnumAccountsWithUserRight *r)
2867 {
2868         struct dcesrv_handle *h;
2869         struct lsa_policy_state *state;
2870         int ret, i;
2871         struct ldb_message **res;
2872         const char * const attrs[] = { "objectSid", NULL};
2873         const char *privname;
2874
2875         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2876
2877         state = h->data;
2878
2879         if (r->in.name == NULL) {
2880                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2881         } 
2882
2883         privname = r->in.name->string;
2884         if (sec_privilege_id(privname) == -1) {
2885                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2886         }
2887
2888         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs, 
2889                            "privilege=%s", privname);
2890         if (ret == -1) {
2891                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2892         }
2893         if (ret == 0) {
2894                 return NT_STATUS_NO_MORE_ENTRIES;
2895         }
2896
2897         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
2898         if (r->out.sids->sids == NULL) {
2899                 return NT_STATUS_NO_MEMORY;
2900         }
2901         for (i=0;i<ret;i++) {
2902                 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
2903                                                                 res[i], "objectSid");
2904                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
2905         }
2906         r->out.sids->num_sids = ret;
2907
2908         return NT_STATUS_OK;
2909 }
2910
2911
2912 /* 
2913   lsa_AddAccountRights
2914 */
2915 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call, 
2916                                      TALLOC_CTX *mem_ctx,
2917                                      struct lsa_AddAccountRights *r)
2918 {
2919         struct dcesrv_handle *h;
2920         struct lsa_policy_state *state;
2921
2922         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2923
2924         state = h->data;
2925
2926         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
2927                                           LDB_FLAG_MOD_ADD,
2928                                           r->in.sid, r->in.rights);
2929 }
2930
2931
2932 /* 
2933   lsa_RemoveAccountRights
2934 */
2935 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call, 
2936                                         TALLOC_CTX *mem_ctx,
2937                                         struct lsa_RemoveAccountRights *r)
2938 {
2939         struct dcesrv_handle *h;
2940         struct lsa_policy_state *state;
2941
2942         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2943
2944         state = h->data;
2945
2946         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
2947                                           LDB_FLAG_MOD_DELETE,
2948                                           r->in.sid, r->in.rights);
2949 }
2950
2951
2952 /* 
2953   lsa_StorePrivateData
2954 */
2955 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2956                        struct lsa_StorePrivateData *r)
2957 {
2958         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2959 }
2960
2961
2962 /* 
2963   lsa_RetrievePrivateData
2964 */
2965 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2966                        struct lsa_RetrievePrivateData *r)
2967 {
2968         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2969 }
2970
2971
2972 /* 
2973   lsa_GetUserName
2974 */
2975 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2976                                 struct lsa_GetUserName *r)
2977 {
2978         NTSTATUS status = NT_STATUS_OK;
2979         const char *account_name;
2980         const char *authority_name;
2981         struct lsa_String *_account_name;
2982         struct lsa_String *_authority_name = NULL;
2983
2984         /* this is what w2k3 does */
2985         r->out.account_name = r->in.account_name;
2986         r->out.authority_name = r->in.authority_name;
2987
2988         if (r->in.account_name
2989             && *r->in.account_name
2990             /* && *(*r->in.account_name)->string */
2991             ) {
2992                 return NT_STATUS_INVALID_PARAMETER;
2993         }
2994
2995         if (r->in.authority_name
2996             && *r->in.authority_name
2997             /* && *(*r->in.authority_name)->string */
2998             ) {
2999                 return NT_STATUS_INVALID_PARAMETER;
3000         }
3001
3002         account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->account_name);
3003         authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->domain_name);
3004
3005         _account_name = talloc(mem_ctx, struct lsa_String);
3006         NT_STATUS_HAVE_NO_MEMORY(_account_name);
3007         _account_name->string = account_name;
3008
3009         if (r->in.authority_name) {
3010                 _authority_name = talloc(mem_ctx, struct lsa_String);
3011                 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3012                 _authority_name->string = authority_name;
3013         }
3014
3015         *r->out.account_name = _account_name;
3016         if (r->out.authority_name) {
3017                 *r->out.authority_name = _authority_name;
3018         }
3019
3020         return status;
3021 }
3022
3023 /*
3024   lsa_SetInfoPolicy2
3025 */
3026 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3027                                    TALLOC_CTX *mem_ctx,
3028                                    struct lsa_SetInfoPolicy2 *r)
3029 {
3030         /* need to support these */
3031         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3032 }
3033
3034 /*
3035   lsa_QueryDomainInformationPolicy
3036 */
3037 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3038                                                  TALLOC_CTX *mem_ctx,
3039                                                  struct lsa_QueryDomainInformationPolicy *r)
3040 {
3041         union lsa_DomainInformationPolicy *info;
3042
3043         info = talloc(r->out.info, union lsa_DomainInformationPolicy);
3044         if (!info) {
3045                 return NT_STATUS_NO_MEMORY;
3046         }
3047
3048         switch (r->in.level) {
3049         case LSA_DOMAIN_INFO_POLICY_EFS:
3050                 talloc_free(info);
3051                 *r->out.info = NULL;
3052                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3053         case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3054         {
3055                 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3056                 struct smb_krb5_context *smb_krb5_context;
3057                 int ret = smb_krb5_init_context(mem_ctx, 
3058                                                         dce_call->event_ctx, 
3059                                                         dce_call->conn->dce_ctx->lp_ctx,
3060                                                         &smb_krb5_context);
3061                 if (ret != 0) {
3062                         talloc_free(info);
3063                         *r->out.info = NULL;
3064                         return NT_STATUS_INTERNAL_ERROR;
3065                 }
3066                 k->enforce_restrictions = 0; /* FIXME, details missing from MS-LSAD 2.2.53 */
3067                 k->service_tkt_lifetime = 0; /* Need to find somewhere to store this, and query in KDC too */
3068                 k->user_tkt_lifetime = 0;    /* Need to find somewhere to store this, and query in KDC too */
3069                 k->user_tkt_renewaltime = 0; /* Need to find somewhere to store this, and query in KDC too */
3070                 k->clock_skew = krb5_get_max_time_skew(smb_krb5_context->krb5_context);
3071                 talloc_free(smb_krb5_context);
3072                 *r->out.info = info;
3073                 return NT_STATUS_OK;
3074         }
3075         default:
3076                 talloc_free(info);
3077                 *r->out.info = NULL;
3078                 return NT_STATUS_INVALID_INFO_CLASS;
3079         }
3080 }
3081
3082 /*
3083   lsa_SetDomInfoPolicy
3084 */
3085 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3086                                               TALLOC_CTX *mem_ctx,
3087                                               struct lsa_SetDomainInformationPolicy *r)
3088 {
3089         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3090 }
3091
3092 /*
3093   lsa_TestCall
3094 */
3095 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3096                              TALLOC_CTX *mem_ctx,
3097                              struct lsa_TestCall *r)
3098 {
3099         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3100 }
3101
3102 /* 
3103   lsa_CREDRWRITE 
3104 */
3105 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3106                        struct lsa_CREDRWRITE *r)
3107 {
3108         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3109 }
3110
3111
3112 /* 
3113   lsa_CREDRREAD 
3114 */
3115 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3116                        struct lsa_CREDRREAD *r)
3117 {
3118         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3119 }
3120
3121
3122 /* 
3123   lsa_CREDRENUMERATE 
3124 */
3125 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3126                        struct lsa_CREDRENUMERATE *r)
3127 {
3128         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);