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