2aa700619d6763b3eb0f5f6b3f53171bfdd7897d
[kai/samba-autobuild/.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 #include "dsdb/common/util.h"
33 #include "libcli/security/session.h"
34 #include "libcli/lsarpc/util_lsarpc.h"
35 #include "lib/messaging/irpc.h"
36 #include "libds/common/roles.h"
37
38 #define DCESRV_INTERFACE_LSARPC_BIND(call, iface) \
39        dcesrv_interface_lsarpc_bind(call, iface)
40 static NTSTATUS dcesrv_interface_lsarpc_bind(struct dcesrv_call_state *dce_call,
41                                              const struct dcesrv_interface *iface)
42 {
43         return dcesrv_interface_bind_reject_connect(dce_call, iface);
44 }
45
46 static NTSTATUS lsarpc__op_init_server(struct dcesrv_context *dce_ctx,
47                                        const struct dcesrv_endpoint_server *ep_server);
48 static const struct dcesrv_interface dcesrv_lsarpc_interface;
49
50 #define DCESRV_INTERFACE_LSARPC_INIT_SERVER     \
51        dcesrv_interface_lsarpc_init_server
52 static NTSTATUS dcesrv_interface_lsarpc_init_server(struct dcesrv_context *dce_ctx,
53                                                     const struct dcesrv_endpoint_server *ep_server)
54 {
55         if (lpcfg_lsa_over_netlogon(dce_ctx->lp_ctx)) {
56                 NTSTATUS ret = dcesrv_interface_register(dce_ctx,
57                                                 "ncacn_np:[\\pipe\\netlogon]",
58                                                 &dcesrv_lsarpc_interface, NULL);
59                 if (!NT_STATUS_IS_OK(ret)) {
60                         DEBUG(1,("lsarpc_op_init_server: failed to register endpoint '\\pipe\\netlogon'\n"));
61                         return ret;
62                 }
63         }
64         return lsarpc__op_init_server(dce_ctx, ep_server);
65 }
66
67 /*
68   this type allows us to distinguish handle types
69 */
70
71 /*
72   state associated with a lsa_OpenAccount() operation
73 */
74 struct lsa_account_state {
75         struct lsa_policy_state *policy;
76         uint32_t access_mask;
77         struct dom_sid *account_sid;
78 };
79
80
81 /*
82   state associated with a lsa_OpenSecret() operation
83 */
84 struct lsa_secret_state {
85         struct lsa_policy_state *policy;
86         uint32_t access_mask;
87         struct ldb_dn *secret_dn;
88         struct ldb_context *sam_ldb;
89         bool global;
90 };
91
92 /*
93   state associated with a lsa_OpenTrustedDomain() operation
94 */
95 struct lsa_trusted_domain_state {
96         struct lsa_policy_state *policy;
97         uint32_t access_mask;
98         struct ldb_dn *trusted_domain_dn;
99         struct ldb_dn *trusted_domain_user_dn;
100 };
101
102 /*
103   this is based on the samba3 function make_lsa_object_sd()
104   It uses the same logic, but with samba4 helper functions
105  */
106 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
107                                     struct security_descriptor **sd,
108                                     struct dom_sid *sid,
109                                     uint32_t sid_access)
110 {
111         NTSTATUS status;
112         uint32_t rid;
113         struct dom_sid *domain_sid, *domain_admins_sid;
114         const char *domain_admins_sid_str, *sidstr;
115         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
116
117         status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
118         if (!NT_STATUS_IS_OK(status)) {
119                 TALLOC_FREE(tmp_ctx);
120                 return status;
121         }
122
123         domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
124         if (domain_admins_sid == NULL) {
125                 TALLOC_FREE(tmp_ctx);
126                 return NT_STATUS_NO_MEMORY;
127         }
128
129         domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
130         if (domain_admins_sid_str == NULL) {
131                 TALLOC_FREE(tmp_ctx);
132                 return NT_STATUS_NO_MEMORY;
133         }
134
135         sidstr = dom_sid_string(tmp_ctx, sid);
136         if (sidstr == NULL) {
137                 TALLOC_FREE(tmp_ctx);
138                 return NT_STATUS_NO_MEMORY;
139         }
140
141         *sd = security_descriptor_dacl_create(mem_ctx,
142                                               0, sidstr, NULL,
143
144                                               SID_WORLD,
145                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
146                                               SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
147
148                                               SID_BUILTIN_ADMINISTRATORS,
149                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
150                                               SEC_GENERIC_ALL, 0,
151
152                                               SID_BUILTIN_ACCOUNT_OPERATORS,
153                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
154                                               SEC_GENERIC_ALL, 0,
155
156                                               domain_admins_sid_str,
157                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
158                                               SEC_GENERIC_ALL, 0,
159
160                                               sidstr,
161                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
162                                               sid_access, 0,
163
164                                               NULL);
165         talloc_free(tmp_ctx);
166
167         NT_STATUS_HAVE_NO_MEMORY(*sd);
168
169         return NT_STATUS_OK;
170 }
171
172
173 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
174                                       TALLOC_CTX *mem_ctx,
175                                       struct lsa_EnumAccountRights *r);
176
177 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
178                                            TALLOC_CTX *mem_ctx,
179                                            struct lsa_policy_state *state,
180                                            int ldb_flag,
181                                            struct dom_sid *sid,
182                                            const struct lsa_RightSet *rights);
183
184 /*
185   lsa_Close
186 */
187 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
188                           struct lsa_Close *r)
189 {
190         enum dcerpc_transport_t transport =
191                 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
192         struct dcesrv_handle *h;
193
194         if (transport != NCACN_NP && transport != NCALRPC) {
195                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
196         }
197
198         *r->out.handle = *r->in.handle;
199
200         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
201
202         talloc_free(h);
203
204         ZERO_STRUCTP(r->out.handle);
205
206         return NT_STATUS_OK;
207 }
208
209
210 /*
211   lsa_Delete
212 */
213 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
214                            struct lsa_Delete *r)
215 {
216         return NT_STATUS_NOT_SUPPORTED;
217 }
218
219
220 /*
221   lsa_DeleteObject
222 */
223 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
224                        struct lsa_DeleteObject *r)
225 {
226         struct dcesrv_handle *h;
227         int ret;
228
229         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
230
231         if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
232                 struct lsa_secret_state *secret_state = h->data;
233
234                 /* Ensure user is permitted to delete this... */
235                 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
236                 {
237                 case SECURITY_SYSTEM:
238                 case SECURITY_ADMINISTRATOR:
239                         break;
240                 default:
241                         /* Users and anonymous are not allowed to delete things */
242                         return NT_STATUS_ACCESS_DENIED;
243                 }
244
245                 ret = ldb_delete(secret_state->sam_ldb,
246                                  secret_state->secret_dn);
247                 if (ret != LDB_SUCCESS) {
248                         return NT_STATUS_INVALID_HANDLE;
249                 }
250
251                 ZERO_STRUCTP(r->out.handle);
252
253                 return NT_STATUS_OK;
254
255         } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
256                 struct lsa_trusted_domain_state *trusted_domain_state =
257                         talloc_get_type(h->data, struct lsa_trusted_domain_state);
258                 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
259                 if (ret != LDB_SUCCESS) {
260                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
261                 }
262
263                 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
264                                  trusted_domain_state->trusted_domain_dn);
265                 if (ret != LDB_SUCCESS) {
266                         ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
267                         return NT_STATUS_INVALID_HANDLE;
268                 }
269
270                 if (trusted_domain_state->trusted_domain_user_dn) {
271                         ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
272                                          trusted_domain_state->trusted_domain_user_dn);
273                         if (ret != LDB_SUCCESS) {
274                                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
275                                 return NT_STATUS_INVALID_HANDLE;
276                         }
277                 }
278
279                 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
280                 if (ret != LDB_SUCCESS) {
281                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
282                 }
283
284                 ZERO_STRUCTP(r->out.handle);
285
286                 return NT_STATUS_OK;
287
288         } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
289                 struct lsa_RightSet *rights;
290                 struct lsa_account_state *astate;
291                 struct lsa_EnumAccountRights r2;
292                 NTSTATUS status;
293
294                 rights = talloc(mem_ctx, struct lsa_RightSet);
295
296                 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
297
298                 astate = h->data;
299
300                 r2.in.handle = &astate->policy->handle->wire_handle;
301                 r2.in.sid = astate->account_sid;
302                 r2.out.rights = rights;
303
304                 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
305                    but we have a LSA_HANDLE_ACCOUNT here, so this call
306                    will always fail */
307                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
308                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
309                         return NT_STATUS_OK;
310                 }
311
312                 if (!NT_STATUS_IS_OK(status)) {
313                         return status;
314                 }
315
316                 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
317                                                     LDB_FLAG_MOD_DELETE, astate->account_sid,
318                                                     r2.out.rights);
319                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
320                         return NT_STATUS_OK;
321                 }
322
323                 if (!NT_STATUS_IS_OK(status)) {
324                         return status;
325                 }
326
327                 ZERO_STRUCTP(r->out.handle);
328
329                 return NT_STATUS_OK;
330         }
331
332         return NT_STATUS_INVALID_HANDLE;
333 }
334
335
336 /*
337   lsa_EnumPrivs
338 */
339 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
340                               struct lsa_EnumPrivs *r)
341 {
342         struct dcesrv_handle *h;
343         uint32_t i;
344         enum sec_privilege priv;
345         const char *privname;
346
347         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
348
349         i = *r->in.resume_handle;
350
351         while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
352                r->out.privs->count < r->in.max_count) {
353                 struct lsa_PrivEntry *e;
354                 privname = sec_privilege_name(priv);
355                 r->out.privs->privs = talloc_realloc(r->out.privs,
356                                                        r->out.privs->privs,
357                                                        struct lsa_PrivEntry,
358                                                        r->out.privs->count+1);
359                 if (r->out.privs->privs == NULL) {
360                         return NT_STATUS_NO_MEMORY;
361                 }
362                 e = &r->out.privs->privs[r->out.privs->count];
363                 e->luid.low = priv;
364                 e->luid.high = 0;
365                 e->name.string = privname;
366                 r->out.privs->count++;
367                 i++;
368         }
369
370         *r->out.resume_handle = i;
371
372         return NT_STATUS_OK;
373 }
374
375
376 /*
377   lsa_QuerySecObj
378 */
379 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
380                                          struct lsa_QuerySecurity *r)
381 {
382         struct dcesrv_handle *h;
383         const struct security_descriptor *sd = NULL;
384         uint32_t access_granted = 0;
385         struct sec_desc_buf *sdbuf = NULL;
386         NTSTATUS status;
387         struct dom_sid *sid;
388
389         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
390
391         sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
392
393         if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
394                 struct lsa_policy_state *pstate = h->data;
395
396                 sd = pstate->sd;
397                 access_granted = pstate->access_mask;
398
399         } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
400                 struct lsa_account_state *astate = h->data;
401                 struct security_descriptor *_sd = NULL;
402
403                 status = dcesrv_build_lsa_sd(mem_ctx, &_sd, sid,
404                                              LSA_ACCOUNT_ALL_ACCESS);
405                 if (!NT_STATUS_IS_OK(status)) {
406                         return status;
407                 }
408                 sd = _sd;
409                 access_granted = astate->access_mask;
410         } else {
411                 return NT_STATUS_INVALID_HANDLE;
412         }
413
414         sdbuf = talloc_zero(mem_ctx, struct sec_desc_buf);
415         if (sdbuf == NULL) {
416                 return NT_STATUS_NO_MEMORY;
417         }
418
419         status = security_descriptor_for_client(sdbuf, sd, r->in.sec_info,
420                                                 access_granted, &sdbuf->sd);
421         if (!NT_STATUS_IS_OK(status)) {
422                 return status;
423         }
424
425         *r->out.sdbuf = sdbuf;
426
427         return NT_STATUS_OK;
428 }
429
430
431 /*
432   lsa_SetSecObj
433 */
434 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
435                               struct lsa_SetSecObj *r)
436 {
437         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
438 }
439
440
441 /*
442   lsa_ChangePassword
443 */
444 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
445                                    struct lsa_ChangePassword *r)
446 {
447         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
448 }
449
450 /*
451   dssetup_DsRoleGetPrimaryDomainInformation
452
453   This is not an LSA call, but is the only call left on the DSSETUP
454   pipe (after the pipe was truncated), and needs lsa_get_policy_state
455 */
456 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
457                                                  TALLOC_CTX *mem_ctx,
458                                                  struct dssetup_DsRoleGetPrimaryDomainInformation *r)
459 {
460         union dssetup_DsRoleInfo *info;
461
462         info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
463         W_ERROR_HAVE_NO_MEMORY(info);
464
465         switch (r->in.level) {
466         case DS_ROLE_BASIC_INFORMATION:
467         {
468                 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
469                 uint32_t flags = 0;
470                 const char *domain = NULL;
471                 const char *dns_domain = NULL;
472                 const char *forest = NULL;
473                 struct GUID domain_guid;
474                 struct lsa_policy_state *state;
475
476                 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
477                                                               0, /* we skip access checks */
478                                                               &state);
479                 if (!NT_STATUS_IS_OK(status)) {
480                         return ntstatus_to_werror(status);
481                 }
482
483                 ZERO_STRUCT(domain_guid);
484
485                 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
486                 case ROLE_STANDALONE:
487                         role            = DS_ROLE_STANDALONE_SERVER;
488                         break;
489                 case ROLE_DOMAIN_MEMBER:
490                         role            = DS_ROLE_MEMBER_SERVER;
491                         break;
492                 case ROLE_ACTIVE_DIRECTORY_DC:
493                         if (samdb_is_pdc(state->sam_ldb)) {
494                                 role    = DS_ROLE_PRIMARY_DC;
495                         } else {
496                                 role    = DS_ROLE_BACKUP_DC;
497                         }
498                         break;
499                 }
500
501                 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
502                 case ROLE_STANDALONE:
503                         domain          = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
504                         W_ERROR_HAVE_NO_MEMORY(domain);
505                         break;
506                 case ROLE_DOMAIN_MEMBER:
507                         domain          = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
508                         W_ERROR_HAVE_NO_MEMORY(domain);
509                         /* TODO: what is with dns_domain and forest and guid? */
510                         break;
511                 case ROLE_ACTIVE_DIRECTORY_DC:
512                         flags           = DS_ROLE_PRIMARY_DS_RUNNING;
513
514                         if (state->mixed_domain == 1) {
515                                 flags   |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
516                         }
517
518                         domain          = state->domain_name;
519                         dns_domain      = state->domain_dns;
520                         forest          = state->forest_dns;
521
522                         domain_guid     = state->domain_guid;
523                         flags   |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
524                         break;
525                 }
526
527                 info->basic.role        = role;
528                 info->basic.flags       = flags;
529                 info->basic.domain      = domain;
530                 info->basic.dns_domain  = dns_domain;
531                 info->basic.forest      = forest;
532                 info->basic.domain_guid = domain_guid;
533
534                 r->out.info = info;
535                 return WERR_OK;
536         }
537         case DS_ROLE_UPGRADE_STATUS:
538         {
539                 info->upgrade.upgrading     = DS_ROLE_NOT_UPGRADING;
540                 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
541
542                 r->out.info = info;
543                 return WERR_OK;
544         }
545         case DS_ROLE_OP_STATUS:
546         {
547                 info->opstatus.status = DS_ROLE_OP_IDLE;
548
549                 r->out.info = info;
550                 return WERR_OK;
551         }
552         default:
553                 return WERR_INVALID_PARAMETER;
554         }
555 }
556
557 /*
558   fill in the AccountDomain info
559 */
560 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
561                                        struct lsa_DomainInfo *info)
562 {
563         info->name.string = state->domain_name;
564         info->sid         = state->domain_sid;
565
566         return NT_STATUS_OK;
567 }
568
569 /*
570   fill in the DNS domain info
571 */
572 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
573                              struct lsa_DnsDomainInfo *info)
574 {
575         info->name.string = state->domain_name;
576         info->sid         = state->domain_sid;
577         info->dns_domain.string = state->domain_dns;
578         info->dns_forest.string = state->forest_dns;
579         info->domain_guid       = state->domain_guid;
580
581         return NT_STATUS_OK;
582 }
583
584 /*
585   lsa_QueryInfoPolicy2
586 */
587 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
588                                      struct lsa_QueryInfoPolicy2 *r)
589 {
590         struct lsa_policy_state *state;
591         struct dcesrv_handle *h;
592         union lsa_PolicyInformation *info;
593
594         *r->out.info = NULL;
595
596         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
597
598         state = h->data;
599
600         info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
601         if (!info) {
602                 return NT_STATUS_NO_MEMORY;
603         }
604         *r->out.info = info;
605
606         switch (r->in.level) {
607         case LSA_POLICY_INFO_AUDIT_LOG:
608                 /* we don't need to fill in any of this */
609                 ZERO_STRUCT(info->audit_log);
610                 return NT_STATUS_OK;
611         case LSA_POLICY_INFO_AUDIT_EVENTS:
612                 /* we don't need to fill in any of this */
613                 ZERO_STRUCT(info->audit_events);
614                 return NT_STATUS_OK;
615         case LSA_POLICY_INFO_PD:
616                 /* we don't need to fill in any of this */
617                 ZERO_STRUCT(info->pd);
618                 return NT_STATUS_OK;
619
620         case LSA_POLICY_INFO_DOMAIN:
621                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
622         case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
623                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
624         case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
625                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
626
627         case LSA_POLICY_INFO_ROLE:
628                 info->role.role = LSA_ROLE_PRIMARY;
629                 return NT_STATUS_OK;
630
631         case LSA_POLICY_INFO_DNS:
632         case LSA_POLICY_INFO_DNS_INT:
633                 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
634
635         case LSA_POLICY_INFO_REPLICA:
636                 ZERO_STRUCT(info->replica);
637                 return NT_STATUS_OK;
638
639         case LSA_POLICY_INFO_QUOTA:
640                 ZERO_STRUCT(info->quota);
641                 return NT_STATUS_OK;
642
643         case LSA_POLICY_INFO_MOD:
644         case LSA_POLICY_INFO_AUDIT_FULL_SET:
645         case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
646                 /* windows gives INVALID_PARAMETER */
647                 *r->out.info = NULL;
648                 return NT_STATUS_INVALID_PARAMETER;
649         }
650
651         *r->out.info = NULL;
652         return NT_STATUS_INVALID_INFO_CLASS;
653 }
654
655 /*
656   lsa_QueryInfoPolicy
657 */
658 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
659                                     struct lsa_QueryInfoPolicy *r)
660 {
661         struct lsa_QueryInfoPolicy2 r2;
662         NTSTATUS status;
663
664         ZERO_STRUCT(r2);
665
666         r2.in.handle = r->in.handle;
667         r2.in.level = r->in.level;
668         r2.out.info = r->out.info;
669
670         status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
671
672         return status;
673 }
674
675 /*
676   lsa_SetInfoPolicy
677 */
678 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
679                                   struct lsa_SetInfoPolicy *r)
680 {
681         /* need to support this */
682         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
683 }
684
685
686 /*
687   lsa_ClearAuditLog
688 */
689 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
690                                   struct lsa_ClearAuditLog *r)
691 {
692         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
693 }
694
695
696 static const struct generic_mapping dcesrv_lsa_account_mapping = {
697         LSA_ACCOUNT_READ,
698         LSA_ACCOUNT_WRITE,
699         LSA_ACCOUNT_EXECUTE,
700         LSA_ACCOUNT_ALL_ACCESS
701 };
702
703 /*
704   lsa_CreateAccount
705
706   This call does not seem to have any long-term effects, hence no database operations
707
708   we need to talk to the MS product group to find out what this account database means!
709
710   answer is that the lsa database is totally separate from the SAM and
711   ldap databases. We are going to need a separate ldb to store these
712   accounts. The SIDs on this account bear no relation to the SIDs in
713   AD
714 */
715 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
716                                   struct lsa_CreateAccount *r)
717 {
718         struct lsa_account_state *astate;
719
720         struct lsa_policy_state *state;
721         struct dcesrv_handle *h, *ah;
722
723         ZERO_STRUCTP(r->out.acct_handle);
724
725         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
726
727         state = h->data;
728
729         astate = talloc(dce_call->conn, struct lsa_account_state);
730         if (astate == NULL) {
731                 return NT_STATUS_NO_MEMORY;
732         }
733
734         astate->account_sid = dom_sid_dup(astate, r->in.sid);
735         if (astate->account_sid == NULL) {
736                 talloc_free(astate);
737                 return NT_STATUS_NO_MEMORY;
738         }
739
740         astate->policy = talloc_reference(astate, state);
741         astate->access_mask = r->in.access_mask;
742
743         /*
744          * For now we grant all requested access.
745          *
746          * We will fail at the ldb layer later.
747          */
748         if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
749                 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
750                 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
751         }
752         se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
753
754         DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X].\n",
755                   __func__, dom_sid_string(mem_ctx, astate->account_sid),
756                  (unsigned)r->in.access_mask,
757                  (unsigned)astate->access_mask));
758
759         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
760         if (!ah) {
761                 talloc_free(astate);
762                 return NT_STATUS_NO_MEMORY;
763         }
764
765         ah->data = talloc_steal(ah, astate);
766
767         *r->out.acct_handle = ah->wire_handle;
768
769         return NT_STATUS_OK;
770 }
771
772
773 /*
774   lsa_EnumAccounts
775 */
776 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
777                                  struct lsa_EnumAccounts *r)
778 {
779         struct dcesrv_handle *h;
780         struct lsa_policy_state *state;
781         int ret;
782         struct ldb_message **res;
783         const char * const attrs[] = { "objectSid", NULL};
784         uint32_t count, i;
785
786         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
787
788         state = h->data;
789
790         /* NOTE: This call must only return accounts that have at least
791            one privilege set
792         */
793         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
794                            "(&(objectSid=*)(privilege=*))");
795         if (ret < 0) {
796                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
797         }
798
799         if (*r->in.resume_handle >= ret) {
800                 return NT_STATUS_NO_MORE_ENTRIES;
801         }
802
803         count = ret - *r->in.resume_handle;
804         if (count > r->in.num_entries) {
805                 count = r->in.num_entries;
806         }
807
808         if (count == 0) {
809                 return NT_STATUS_NO_MORE_ENTRIES;
810         }
811
812         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
813         if (r->out.sids->sids == NULL) {
814                 return NT_STATUS_NO_MEMORY;
815         }
816
817         for (i=0;i<count;i++) {
818                 r->out.sids->sids[i].sid =
819                         samdb_result_dom_sid(r->out.sids->sids,
820                                              res[i + *r->in.resume_handle],
821                                              "objectSid");
822                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
823         }
824
825         r->out.sids->num_sids = count;
826         *r->out.resume_handle = count + *r->in.resume_handle;
827
828         return NT_STATUS_OK;
829 }
830
831 /* This decrypts and returns Trusted Domain Auth Information Internal data */
832 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
833                                        TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
834                                        struct trustDomainPasswords *auth_struct)
835 {
836         DATA_BLOB session_key = data_blob(NULL, 0);
837         enum ndr_err_code ndr_err;
838         NTSTATUS nt_status;
839
840         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
841         if (!NT_STATUS_IS_OK(nt_status)) {
842                 return nt_status;
843         }
844
845         arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
846         ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
847                                        auth_struct,
848                                        (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
849         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
850                 return NT_STATUS_INVALID_PARAMETER;
851         }
852
853         return NT_STATUS_OK;
854 }
855
856 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
857                                          TALLOC_CTX *mem_ctx,
858                                          struct trustAuthInOutBlob *iopw,
859                                          DATA_BLOB *trustauth_blob)
860 {
861         enum ndr_err_code ndr_err;
862
863         if (iopw->current.count != iopw->count) {
864                 return NT_STATUS_INVALID_PARAMETER;
865         }
866
867         if (iopw->previous.count > iopw->current.count) {
868                 return NT_STATUS_INVALID_PARAMETER;
869         }
870
871         if (iopw->previous.count == 0) {
872                 /*
873                  * If the previous credentials are not present
874                  * we need to make a copy.
875                  */
876                 iopw->previous = iopw->current;
877         }
878
879         if (iopw->previous.count < iopw->current.count) {
880                 struct AuthenticationInformationArray *c = &iopw->current;
881                 struct AuthenticationInformationArray *p = &iopw->previous;
882
883                 /*
884                  * The previous array needs to have the same size
885                  * as the current one.
886                  *
887                  * We may have to fill with TRUST_AUTH_TYPE_NONE
888                  * elements.
889                  */
890                 p->array = talloc_realloc(mem_ctx, p->array,
891                                    struct AuthenticationInformation,
892                                    c->count);
893                 if (p->array == NULL) {
894                         return NT_STATUS_NO_MEMORY;
895                 }
896
897                 while (p->count < c->count) {
898                         struct AuthenticationInformation *a =
899                                 &p->array[p->count++];
900
901                         *a = (struct AuthenticationInformation) {
902                                 .LastUpdateTime = p->array[0].LastUpdateTime,
903                                 .AuthType = TRUST_AUTH_TYPE_NONE,
904                         };
905                 }
906         }
907
908         ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
909                                        iopw,
910                                        (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
911         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
912                 return NT_STATUS_INVALID_PARAMETER;
913         }
914
915         return NT_STATUS_OK;
916 }
917
918 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
919                                struct ldb_context *sam_ldb,
920                                struct ldb_dn *base_dn,
921                                const char *netbios_name,
922                                struct trustAuthInOutBlob *in,
923                                struct ldb_dn **user_dn)
924 {
925         struct ldb_request *req;
926         struct ldb_message *msg;
927         struct ldb_dn *dn;
928         uint32_t i;
929         int ret;
930
931         dn = ldb_dn_copy(mem_ctx, base_dn);
932         if (!dn) {
933                 return NT_STATUS_NO_MEMORY;
934         }
935         if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
936                 return NT_STATUS_NO_MEMORY;
937         }
938
939         msg = ldb_msg_new(mem_ctx);
940         if (!msg) {
941                 return NT_STATUS_NO_MEMORY;
942         }
943         msg->dn = dn;
944
945         ret = ldb_msg_add_string(msg, "objectClass", "user");
946         if (ret != LDB_SUCCESS) {
947                 return NT_STATUS_NO_MEMORY;
948         }
949
950         ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
951         if (ret != LDB_SUCCESS) {
952                 return NT_STATUS_NO_MEMORY;
953         }
954
955         ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
956                                  UF_INTERDOMAIN_TRUST_ACCOUNT);
957         if (ret != LDB_SUCCESS) {
958                 return NT_STATUS_NO_MEMORY;
959         }
960
961         for (i = 0; i < in->count; i++) {
962                 const char *attribute;
963                 struct ldb_val v;
964                 switch (in->current.array[i].AuthType) {
965                 case TRUST_AUTH_TYPE_NT4OWF:
966                         attribute = "unicodePwd";
967                         v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
968                         v.length = 16;
969                         break;
970                 case TRUST_AUTH_TYPE_CLEAR:
971                         attribute = "clearTextPassword";
972                         v.data = in->current.array[i].AuthInfo.clear.password;
973                         v.length = in->current.array[i].AuthInfo.clear.size;
974                         break;
975                 default:
976                         continue;
977                 }
978
979                 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
980                 if (ret != LDB_SUCCESS) {
981                         return NT_STATUS_NO_MEMORY;
982                 }
983         }
984
985         /* create the trusted_domain user account */
986         ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL,
987                                 ldb_op_default_callback, NULL);
988         if (ret != LDB_SUCCESS) {
989                 return NT_STATUS_NO_MEMORY;
990         }
991
992         ret = ldb_request_add_control(req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
993                                       false, NULL);
994         if (ret != LDB_SUCCESS) {
995                 return NT_STATUS_NO_MEMORY;
996         }
997
998         ret = dsdb_autotransaction_request(sam_ldb, req);
999         if (ret != LDB_SUCCESS) {
1000                 DEBUG(0,("Failed to create user record %s: %s\n",
1001                          ldb_dn_get_linearized(msg->dn),
1002                          ldb_errstring(sam_ldb)));
1003
1004                 switch (ret) {
1005                 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1006                         return NT_STATUS_DOMAIN_EXISTS;
1007                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1008                         return NT_STATUS_ACCESS_DENIED;
1009                 default:
1010                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1011                 }
1012         }
1013
1014         if (user_dn) {
1015                 *user_dn = dn;
1016         }
1017         return NT_STATUS_OK;
1018 }
1019
1020 /*
1021   lsa_CreateTrustedDomainEx2
1022 */
1023 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
1024                                                     TALLOC_CTX *mem_ctx,
1025                                                     struct lsa_CreateTrustedDomainEx2 *r,
1026                                                     int op,
1027                                                     struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
1028 {
1029         struct dcesrv_handle *policy_handle;
1030         struct lsa_policy_state *policy_state;
1031         struct lsa_trusted_domain_state *trusted_domain_state;
1032         struct dcesrv_handle *handle;
1033         struct ldb_message **msgs, *msg;
1034         const char *attrs[] = {
1035                 NULL
1036         };
1037         const char *netbios_name;
1038         const char *dns_name;
1039         DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1040         struct trustDomainPasswords auth_struct;
1041         int ret;
1042         NTSTATUS nt_status;
1043         struct ldb_context *sam_ldb;
1044         struct server_id *server_ids = NULL;
1045         uint32_t num_server_ids = 0;
1046         NTSTATUS status;
1047         struct dom_sid *tmp_sid1;
1048         struct dom_sid *tmp_sid2;
1049         uint32_t tmp_rid;
1050         bool ok;
1051         char *dns_encoded = NULL;
1052         char *netbios_encoded = NULL;
1053         char *sid_encoded = NULL;
1054
1055         DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
1056         ZERO_STRUCTP(r->out.trustdom_handle);
1057
1058         policy_state = policy_handle->data;
1059         sam_ldb = policy_state->sam_ldb;
1060
1061         netbios_name = r->in.info->netbios_name.string;
1062         if (!netbios_name) {
1063                 return NT_STATUS_INVALID_PARAMETER;
1064         }
1065
1066         dns_name = r->in.info->domain_name.string;
1067         if (dns_name == NULL) {
1068                 return NT_STATUS_INVALID_PARAMETER;
1069         }
1070
1071         if (r->in.info->sid == NULL) {
1072                 return NT_STATUS_INVALID_SID;
1073         }
1074
1075         /*
1076          * We expect S-1-5-21-A-B-C, but we don't
1077          * allow S-1-5-21-0-0-0 as this is used
1078          * for claims and compound identities.
1079          *
1080          * So we call dom_sid_split_rid() 3 times
1081          * and compare the result to S-1-5-21
1082          */
1083         status = dom_sid_split_rid(mem_ctx, r->in.info->sid, &tmp_sid1, &tmp_rid);
1084         if (!NT_STATUS_IS_OK(status)) {
1085                 return status;
1086         }
1087         status = dom_sid_split_rid(mem_ctx, tmp_sid1, &tmp_sid2, &tmp_rid);
1088         if (!NT_STATUS_IS_OK(status)) {
1089                 return status;
1090         }
1091         status = dom_sid_split_rid(mem_ctx, tmp_sid2, &tmp_sid1, &tmp_rid);
1092         if (!NT_STATUS_IS_OK(status)) {
1093                 return status;
1094         }
1095         ok = dom_sid_parse("S-1-5-21", tmp_sid2);
1096         if (!ok) {
1097                 return NT_STATUS_INTERNAL_ERROR;
1098         }
1099         ok = dom_sid_equal(tmp_sid1, tmp_sid2);
1100         if (!ok) {
1101                 return NT_STATUS_INVALID_PARAMETER;
1102         }
1103         ok = dom_sid_parse("S-1-5-21-0-0-0", tmp_sid2);
1104         if (!ok) {
1105                 return NT_STATUS_INTERNAL_ERROR;
1106         }
1107         ok = !dom_sid_equal(r->in.info->sid, tmp_sid2);
1108         if (!ok) {
1109                 return NT_STATUS_INVALID_PARAMETER;
1110         }
1111
1112         dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
1113         if (dns_encoded == NULL) {
1114                 return NT_STATUS_NO_MEMORY;
1115         }
1116         netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1117         if (netbios_encoded == NULL) {
1118                 return NT_STATUS_NO_MEMORY;
1119         }
1120         sid_encoded = ldap_encode_ndr_dom_sid(mem_ctx, r->in.info->sid);
1121         if (sid_encoded == NULL) {
1122                 return NT_STATUS_NO_MEMORY;
1123         }
1124
1125         trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1126         if (!trusted_domain_state) {
1127                 return NT_STATUS_NO_MEMORY;
1128         }
1129         trusted_domain_state->policy = policy_state;
1130
1131         if (strcasecmp(netbios_name, "BUILTIN") == 0
1132             || (strcasecmp(dns_name, "BUILTIN") == 0)
1133             || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
1134                 return NT_STATUS_INVALID_PARAMETER;
1135         }
1136
1137         if (strcasecmp(netbios_name, policy_state->domain_name) == 0
1138             || strcasecmp(netbios_name, policy_state->domain_dns) == 0
1139             || strcasecmp(dns_name, policy_state->domain_dns) == 0
1140             || strcasecmp(dns_name, policy_state->domain_name) == 0
1141             || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
1142                 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
1143         }
1144
1145         /* While this is a REF pointer, some of the functions that wrap this don't provide this */
1146         if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
1147                 /* No secrets are created at this time, for this function */
1148                 auth_struct.outgoing.count = 0;
1149                 auth_struct.incoming.count = 0;
1150         } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
1151                 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
1152                                             r->in.auth_info_internal->auth_blob.size);
1153                 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1154                                                    &auth_blob, &auth_struct);
1155                 if (!NT_STATUS_IS_OK(nt_status)) {
1156                         return nt_status;
1157                 }
1158         } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
1159
1160                 if (unencrypted_auth_info->incoming_count > 1) {
1161                         return NT_STATUS_INVALID_PARAMETER;
1162                 }
1163
1164                 /* more investigation required here, do not create secrets for
1165                  * now */
1166                 auth_struct.outgoing.count = 0;
1167                 auth_struct.incoming.count = 0;
1168         } else {
1169                 return NT_STATUS_INVALID_PARAMETER;
1170         }
1171
1172         if (auth_struct.incoming.count) {
1173                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1174                                                      &auth_struct.incoming,
1175                                                      &trustAuthIncoming);
1176                 if (!NT_STATUS_IS_OK(nt_status)) {
1177                         return nt_status;
1178                 }
1179         } else {
1180                 trustAuthIncoming = data_blob(NULL, 0);
1181         }
1182
1183         if (auth_struct.outgoing.count) {
1184                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1185                                                      &auth_struct.outgoing,
1186                                                      &trustAuthOutgoing);
1187                 if (!NT_STATUS_IS_OK(nt_status)) {
1188                         return nt_status;
1189                 }
1190         } else {
1191                 trustAuthOutgoing = data_blob(NULL, 0);
1192         }
1193
1194         ret = ldb_transaction_start(sam_ldb);
1195         if (ret != LDB_SUCCESS) {
1196                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1197         }
1198
1199         /* search for the trusted_domain record */
1200         ret = gendb_search(sam_ldb,
1201                            mem_ctx, policy_state->system_dn, &msgs, attrs,
1202                            "(&(objectClass=trustedDomain)(|"
1203                              "(flatname=%s)(trustPartner=%s)"
1204                              "(flatname=%s)(trustPartner=%s)"
1205                              "(securityIdentifier=%s)))",
1206                            dns_encoded, dns_encoded,
1207                            netbios_encoded, netbios_encoded,
1208                            sid_encoded);
1209         if (ret > 0) {
1210                 ldb_transaction_cancel(sam_ldb);
1211                 return NT_STATUS_OBJECT_NAME_COLLISION;
1212         }
1213         if (ret < 0) {
1214                 ldb_transaction_cancel(sam_ldb);
1215                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1216         }
1217
1218         msg = ldb_msg_new(mem_ctx);
1219         if (msg == NULL) {
1220                 return NT_STATUS_NO_MEMORY;
1221         }
1222
1223         msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1224         if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", dns_name)) {
1225                         ldb_transaction_cancel(sam_ldb);
1226                 return NT_STATUS_NO_MEMORY;
1227         }
1228
1229         ret = ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1230         if (ret != LDB_SUCCESS) {
1231                 ldb_transaction_cancel(sam_ldb);
1232                 return NT_STATUS_NO_MEMORY;;
1233         }
1234
1235         ret = ldb_msg_add_string(msg, "flatname", netbios_name);
1236         if (ret != LDB_SUCCESS) {
1237                 ldb_transaction_cancel(sam_ldb);
1238                 return NT_STATUS_NO_MEMORY;
1239         }
1240
1241         ret = ldb_msg_add_string(msg, "trustPartner", dns_name);
1242         if (ret != LDB_SUCCESS) {
1243                 ldb_transaction_cancel(sam_ldb);
1244                 return NT_STATUS_NO_MEMORY;;
1245         }
1246
1247         ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier",
1248                                     r->in.info->sid);
1249         if (ret != LDB_SUCCESS) {
1250                 ldb_transaction_cancel(sam_ldb);
1251                 return NT_STATUS_NO_MEMORY;;
1252         }
1253
1254         ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1255         if (ret != LDB_SUCCESS) {
1256                 ldb_transaction_cancel(sam_ldb);
1257                 return NT_STATUS_NO_MEMORY;;
1258         }
1259
1260         ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1261         if (ret != LDB_SUCCESS) {
1262                 ldb_transaction_cancel(sam_ldb);
1263                 return NT_STATUS_NO_MEMORY;;
1264         }
1265
1266         ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1267         if (ret != LDB_SUCCESS) {
1268                 ldb_transaction_cancel(sam_ldb);
1269                 return NT_STATUS_NO_MEMORY;;
1270         }
1271
1272         if (trustAuthIncoming.data) {
1273                 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1274                 if (ret != LDB_SUCCESS) {
1275                         ldb_transaction_cancel(sam_ldb);
1276                         return NT_STATUS_NO_MEMORY;
1277                 }
1278         }
1279         if (trustAuthOutgoing.data) {
1280                 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1281                 if (ret != LDB_SUCCESS) {
1282                         ldb_transaction_cancel(sam_ldb);
1283                         return NT_STATUS_NO_MEMORY;
1284                 }
1285         }
1286
1287         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1288
1289         /* create the trusted_domain */
1290         ret = ldb_add(sam_ldb, msg);
1291         switch (ret) {
1292         case  LDB_SUCCESS:
1293                 break;
1294         case  LDB_ERR_ENTRY_ALREADY_EXISTS:
1295                 ldb_transaction_cancel(sam_ldb);
1296                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1297                          ldb_dn_get_linearized(msg->dn),
1298                          ldb_errstring(sam_ldb)));
1299                 return NT_STATUS_DOMAIN_EXISTS;
1300         case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1301                 ldb_transaction_cancel(sam_ldb);
1302                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1303                          ldb_dn_get_linearized(msg->dn),
1304                          ldb_errstring(sam_ldb)));
1305                 return NT_STATUS_ACCESS_DENIED;
1306         default:
1307                 ldb_transaction_cancel(sam_ldb);
1308                 DEBUG(0,("Failed to create user record %s: %s\n",
1309                          ldb_dn_get_linearized(msg->dn),
1310                          ldb_errstring(sam_ldb)));
1311                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1312         }
1313
1314         if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1315                 struct ldb_dn *user_dn;
1316                 /* Inbound trusts must also create a cn=users object to match */
1317                 nt_status = add_trust_user(mem_ctx, sam_ldb,
1318                                            policy_state->domain_dn,
1319                                            netbios_name,
1320                                            &auth_struct.incoming,
1321                                            &user_dn);
1322                 if (!NT_STATUS_IS_OK(nt_status)) {
1323                         ldb_transaction_cancel(sam_ldb);
1324                         return nt_status;
1325                 }
1326
1327                 /* save the trust user dn */
1328                 trusted_domain_state->trusted_domain_user_dn
1329                         = talloc_steal(trusted_domain_state, user_dn);
1330         }
1331
1332         ret = ldb_transaction_commit(sam_ldb);
1333         if (ret != LDB_SUCCESS) {
1334                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1335         }
1336
1337         /*
1338          * Notify winbindd that we have a new trust
1339          */
1340         status = irpc_servers_byname(dce_call->msg_ctx,
1341                                      mem_ctx,
1342                                      "winbind_server",
1343                                      &num_server_ids, &server_ids);
1344         if (NT_STATUS_IS_OK(status) && num_server_ids >= 1) {
1345                 enum ndr_err_code ndr_err;
1346                 DATA_BLOB b = {};
1347
1348                 ndr_err = ndr_push_struct_blob(&b, mem_ctx, r->in.info,
1349                         (ndr_push_flags_fn_t)ndr_push_lsa_TrustDomainInfoInfoEx);
1350                 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1351                         imessaging_send(dce_call->msg_ctx, server_ids[0],
1352                                 MSG_WINBIND_NEW_TRUSTED_DOMAIN, &b);
1353                 }
1354         }
1355         TALLOC_FREE(server_ids);
1356
1357         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1358         if (!handle) {
1359                 return NT_STATUS_NO_MEMORY;
1360         }
1361
1362         handle->data = talloc_steal(handle, trusted_domain_state);
1363
1364         trusted_domain_state->access_mask = r->in.access_mask;
1365         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1366
1367         *r->out.trustdom_handle = handle->wire_handle;
1368
1369         return NT_STATUS_OK;
1370 }
1371
1372 /*
1373   lsa_CreateTrustedDomainEx2
1374 */
1375 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1376                                            TALLOC_CTX *mem_ctx,
1377                                            struct lsa_CreateTrustedDomainEx2 *r)
1378 {
1379         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1380 }
1381 /*
1382   lsa_CreateTrustedDomainEx
1383 */
1384 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1385                                           TALLOC_CTX *mem_ctx,
1386                                           struct lsa_CreateTrustedDomainEx *r)
1387 {
1388         struct lsa_CreateTrustedDomainEx2 r2;
1389
1390         r2.in.policy_handle = r->in.policy_handle;
1391         r2.in.info = r->in.info;
1392         r2.out.trustdom_handle = r->out.trustdom_handle;
1393         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1394 }
1395
1396 /*
1397   lsa_CreateTrustedDomain
1398 */
1399 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1400                                         struct lsa_CreateTrustedDomain *r)
1401 {
1402         struct lsa_CreateTrustedDomainEx2 r2;
1403
1404         r2.in.policy_handle = r->in.policy_handle;
1405         r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1406         if (!r2.in.info) {
1407                 return NT_STATUS_NO_MEMORY;
1408         }
1409
1410         r2.in.info->domain_name = r->in.info->name;
1411         r2.in.info->netbios_name = r->in.info->name;
1412         r2.in.info->sid = r->in.info->sid;
1413         r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1414         r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1415         r2.in.info->trust_attributes = 0;
1416
1417         r2.in.access_mask = r->in.access_mask;
1418         r2.out.trustdom_handle = r->out.trustdom_handle;
1419
1420         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1421 }
1422
1423 static NTSTATUS dcesrv_lsa_OpenTrustedDomain_common(
1424                                         struct dcesrv_call_state *dce_call,
1425                                         TALLOC_CTX *tmp_mem,
1426                                         struct lsa_policy_state *policy_state,
1427                                         const char *filter,
1428                                         uint32_t access_mask,
1429                                         struct dcesrv_handle **_handle)
1430 {
1431         struct lsa_trusted_domain_state *trusted_domain_state;
1432         struct dcesrv_handle *handle;
1433         struct ldb_message **msgs;
1434         const char *attrs[] = {
1435                 "trustDirection",
1436                 "flatname",
1437                 NULL
1438         };
1439         uint32_t direction;
1440         int ret;
1441
1442         /* TODO: perform access checks */
1443
1444         /* search for the trusted_domain record */
1445         ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1446                            policy_state->system_dn,
1447                            &msgs, attrs, "%s", filter);
1448         if (ret == 0) {
1449                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1450         }
1451
1452         if (ret != 1) {
1453                 DEBUG(0,("Found %d records matching %s under %s\n", ret,
1454                          filter,
1455                          ldb_dn_get_linearized(policy_state->system_dn)));
1456                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1457         }
1458
1459         trusted_domain_state = talloc_zero(tmp_mem,
1460                                            struct lsa_trusted_domain_state);
1461         if (!trusted_domain_state) {
1462                 return NT_STATUS_NO_MEMORY;
1463         }
1464         trusted_domain_state->policy = policy_state;
1465
1466         trusted_domain_state->trusted_domain_dn =
1467                 talloc_steal(trusted_domain_state, msgs[0]->dn);
1468
1469         direction = ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0);
1470         if (direction & LSA_TRUST_DIRECTION_INBOUND) {
1471                 const char *flatname = ldb_msg_find_attr_as_string(msgs[0],
1472                                                         "flatname", NULL);
1473
1474                 /* search for the trusted_domain account */
1475                 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1476                                    policy_state->domain_dn,
1477                                    &msgs, attrs,
1478                                    "(&(samaccountname=%s$)(objectclass=user)"
1479                                    "(userAccountControl:%s:=%u))",
1480                                    flatname,
1481                                    LDB_OID_COMPARATOR_AND,
1482                                    UF_INTERDOMAIN_TRUST_ACCOUNT);
1483                 if (ret == 1) {
1484                         trusted_domain_state->trusted_domain_user_dn =
1485                                 talloc_steal(trusted_domain_state, msgs[0]->dn);
1486                 }
1487         }
1488
1489         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1490         if (!handle) {
1491                 return NT_STATUS_NO_MEMORY;
1492         }
1493
1494         handle->data = talloc_steal(handle, trusted_domain_state);
1495
1496         trusted_domain_state->access_mask = access_mask;
1497         trusted_domain_state->policy = talloc_reference(trusted_domain_state,
1498                                                         policy_state);
1499
1500         *_handle = handle;
1501
1502         return NT_STATUS_OK;
1503 }
1504
1505 /*
1506   lsa_OpenTrustedDomain
1507 */
1508 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1509                                       struct lsa_OpenTrustedDomain *r)
1510 {
1511         struct dcesrv_handle *policy_handle;
1512         struct lsa_policy_state *policy_state;
1513         struct dcesrv_handle *handle;
1514         const char *sid_string;
1515         char *filter;
1516         NTSTATUS status;
1517
1518         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1519         ZERO_STRUCTP(r->out.trustdom_handle);
1520         policy_state = policy_handle->data;
1521
1522         sid_string = dom_sid_string(mem_ctx, r->in.sid);
1523         if (!sid_string) {
1524                 return NT_STATUS_NO_MEMORY;
1525         }
1526
1527         filter = talloc_asprintf(mem_ctx,
1528                                  "(&(securityIdentifier=%s)"
1529                                  "(objectclass=trustedDomain))",
1530                                  sid_string);
1531         if (filter == NULL) {
1532                 return NT_STATUS_NO_MEMORY;
1533         }
1534
1535         status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1536                                                      policy_state,
1537                                                      filter,
1538                                                      r->in.access_mask,
1539                                                      &handle);
1540         if (!NT_STATUS_IS_OK(status)) {
1541                 return status;
1542         }
1543
1544         *r->out.trustdom_handle = handle->wire_handle;
1545
1546         return NT_STATUS_OK;
1547 }
1548
1549
1550 /*
1551   lsa_OpenTrustedDomainByName
1552 */
1553 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1554                                             TALLOC_CTX *mem_ctx,
1555                                             struct lsa_OpenTrustedDomainByName *r)
1556 {
1557         struct dcesrv_handle *policy_handle;
1558         struct lsa_policy_state *policy_state;
1559         struct dcesrv_handle *handle;
1560         char *td_name;
1561         char *filter;
1562         NTSTATUS status;
1563
1564         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1565         ZERO_STRUCTP(r->out.trustdom_handle);
1566         policy_state = policy_handle->data;
1567
1568         if (!r->in.name.string) {
1569                 return NT_STATUS_INVALID_PARAMETER;
1570         }
1571
1572         /* search for the trusted_domain record */
1573         td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1574         if (td_name == NULL) {
1575                 return NT_STATUS_NO_MEMORY;
1576         }
1577
1578         filter = talloc_asprintf(mem_ctx,
1579                            "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1580                              "(objectclass=trustedDomain))",
1581                            td_name, td_name, td_name);
1582         if (filter == NULL) {
1583                 return NT_STATUS_NO_MEMORY;
1584         }
1585
1586         status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1587                                                      policy_state,
1588                                                      filter,
1589                                                      r->in.access_mask,
1590                                                      &handle);
1591         if (!NT_STATUS_IS_OK(status)) {
1592                 return status;
1593         }
1594
1595         *r->out.trustdom_handle = handle->wire_handle;
1596
1597         return NT_STATUS_OK;
1598 }
1599
1600
1601
1602 /*
1603   lsa_SetTrustedDomainInfo
1604 */
1605 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1606                                          struct lsa_SetTrustedDomainInfo *r)
1607 {
1608         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1609 }
1610
1611
1612
1613 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1614  * otherwise at least one must be provided */
1615 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1616                         struct ldb_dn *basedn, const char *dns_domain,
1617                         const char *netbios, struct dom_sid2 *sid,
1618                         struct ldb_message ***msgs)
1619 {
1620         const char *attrs[] = { "flatname", "trustPartner",
1621                                 "securityIdentifier", "trustDirection",
1622                                 "trustType", "trustAttributes",
1623                                 "trustPosixOffset",
1624                                 "msDs-supportedEncryptionTypes",
1625                                 "msDS-TrustForestTrustInfo",
1626                                 NULL
1627         };
1628         char *dns = NULL;
1629         char *nbn = NULL;
1630         char *sidstr = NULL;
1631         char *filter;
1632         int ret;
1633
1634
1635         if (dns_domain || netbios || sid) {
1636                 filter = talloc_strdup(mem_ctx,
1637                                    "(&(objectclass=trustedDomain)(|");
1638         } else {
1639                 filter = talloc_strdup(mem_ctx,
1640                                        "(objectclass=trustedDomain)");
1641         }
1642         if (!filter) {
1643                 return NT_STATUS_NO_MEMORY;
1644         }
1645
1646         if (dns_domain) {
1647                 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1648                 if (!dns) {
1649                         return NT_STATUS_NO_MEMORY;
1650                 }
1651                 filter = talloc_asprintf_append(filter,
1652                                                 "(trustPartner=%s)", dns);
1653                 if (!filter) {
1654                         return NT_STATUS_NO_MEMORY;
1655                 }
1656         }
1657         if (netbios) {
1658                 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1659                 if (!nbn) {
1660                         return NT_STATUS_NO_MEMORY;
1661                 }
1662                 filter = talloc_asprintf_append(filter,
1663                                                 "(flatname=%s)", nbn);
1664                 if (!filter) {
1665                         return NT_STATUS_NO_MEMORY;
1666                 }
1667         }
1668         if (sid) {
1669                 sidstr = dom_sid_string(mem_ctx, sid);
1670                 if (!sidstr) {
1671                         return NT_STATUS_INVALID_PARAMETER;
1672                 }
1673                 filter = talloc_asprintf_append(filter,
1674                                                 "(securityIdentifier=%s)",
1675                                                 sidstr);
1676                 if (!filter) {
1677                         return NT_STATUS_NO_MEMORY;
1678                 }
1679         }
1680         if (dns_domain || netbios || sid) {
1681                 filter = talloc_asprintf_append(filter, "))");
1682                 if (!filter) {
1683                         return NT_STATUS_NO_MEMORY;
1684                 }
1685         }
1686
1687         ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1688         if (ret == 0) {
1689                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1690         }
1691
1692         if (ret != 1) {
1693                 return NT_STATUS_OBJECT_NAME_COLLISION;
1694         }
1695
1696         return NT_STATUS_OK;
1697 }
1698
1699 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1700                                       struct ldb_context *sam_ldb,
1701                                       struct ldb_message *orig,
1702                                       struct ldb_message *dest,
1703                                       const char *attribute,
1704                                       uint32_t value,
1705                                       uint32_t *orig_value)
1706 {
1707         const struct ldb_val *orig_val;
1708         uint32_t orig_uint = 0;
1709         unsigned int flags = 0;
1710         int ret;
1711
1712         orig_val = ldb_msg_find_ldb_val(orig, attribute);
1713         if (!orig_val || !orig_val->data) {
1714                 /* add new attribute */
1715                 flags = LDB_FLAG_MOD_ADD;
1716
1717         } else {
1718                 errno = 0;
1719                 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1720                 if (errno != 0 || orig_uint != value) {
1721                         /* replace also if can't get value */
1722                         flags = LDB_FLAG_MOD_REPLACE;
1723                 }
1724         }
1725
1726         if (flags == 0) {
1727                 /* stored value is identical, nothing to change */
1728                 goto done;
1729         }
1730
1731         ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1732         if (ret != LDB_SUCCESS) {
1733                 return NT_STATUS_NO_MEMORY;
1734         }
1735
1736         ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1737         if (ret != LDB_SUCCESS) {
1738                 return NT_STATUS_NO_MEMORY;
1739         }
1740
1741 done:
1742         if (orig_value) {
1743                 *orig_value = orig_uint;
1744         }
1745         return NT_STATUS_OK;
1746 }
1747
1748 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1749                                   struct ldb_context *sam_ldb,
1750                                   struct ldb_dn *base_dn,
1751                                   bool delete_user,
1752                                   const char *netbios_name,
1753                                   struct trustAuthInOutBlob *in)
1754 {
1755         const char *attrs[] = { "userAccountControl", NULL };
1756         struct ldb_message **msgs;
1757         struct ldb_message *msg;
1758         uint32_t uac;
1759         uint32_t i;
1760         int ret;
1761
1762         ret = gendb_search(sam_ldb, mem_ctx,
1763                            base_dn, &msgs, attrs,
1764                            "samAccountName=%s$", netbios_name);
1765         if (ret > 1) {
1766                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1767         }
1768
1769         if (ret == 0) {
1770                 if (delete_user) {
1771                         return NT_STATUS_OK;
1772                 }
1773
1774                 /* ok no existing user, add it from scratch */
1775                 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1776                                       netbios_name, in, NULL);
1777         }
1778
1779         /* check user is what we are looking for */
1780         uac = ldb_msg_find_attr_as_uint(msgs[0],
1781                                         "userAccountControl", 0);
1782         if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1783                 return NT_STATUS_OBJECT_NAME_COLLISION;
1784         }
1785
1786         if (delete_user) {
1787                 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1788                 switch (ret) {
1789                 case LDB_SUCCESS:
1790                         return NT_STATUS_OK;
1791                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1792                         return NT_STATUS_ACCESS_DENIED;
1793                 default:
1794                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1795                 }
1796         }
1797
1798         /* entry exists, just modify secret if any */
1799         if (in == NULL || in->count == 0) {
1800                 return NT_STATUS_OK;
1801         }
1802
1803         msg = ldb_msg_new(mem_ctx);
1804         if (!msg) {
1805                 return NT_STATUS_NO_MEMORY;
1806         }
1807         msg->dn = msgs[0]->dn;
1808
1809         for (i = 0; i < in->count; i++) {
1810                 const char *attribute;
1811                 struct ldb_val v;
1812                 switch (in->current.array[i].AuthType) {
1813                 case TRUST_AUTH_TYPE_NT4OWF:
1814                         attribute = "unicodePwd";
1815                         v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1816                         v.length = 16;
1817                         break;
1818                 case TRUST_AUTH_TYPE_CLEAR:
1819                         attribute = "clearTextPassword";
1820                         v.data = in->current.array[i].AuthInfo.clear.password;
1821                         v.length = in->current.array[i].AuthInfo.clear.size;
1822                         break;
1823                 default:
1824                         continue;
1825                 }
1826
1827                 ret = ldb_msg_add_empty(msg, attribute,
1828                                         LDB_FLAG_MOD_REPLACE, NULL);
1829                 if (ret != LDB_SUCCESS) {
1830                         return NT_STATUS_NO_MEMORY;
1831                 }
1832
1833                 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1834                 if (ret != LDB_SUCCESS) {
1835                         return NT_STATUS_NO_MEMORY;
1836                 }
1837         }
1838
1839         /* create the trusted_domain user account */
1840         ret = ldb_modify(sam_ldb, msg);
1841         if (ret != LDB_SUCCESS) {
1842                 DEBUG(0,("Failed to create user record %s: %s\n",
1843                          ldb_dn_get_linearized(msg->dn),
1844                          ldb_errstring(sam_ldb)));
1845
1846                 switch (ret) {
1847                 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1848                         return NT_STATUS_DOMAIN_EXISTS;
1849                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1850                         return NT_STATUS_ACCESS_DENIED;
1851                 default:
1852                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1853                 }
1854         }
1855
1856         return NT_STATUS_OK;
1857 }
1858
1859
1860 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1861                                           struct lsa_policy_state *p_state,
1862                                           TALLOC_CTX *mem_ctx,
1863                                           struct ldb_message *dom_msg,
1864                                           enum lsa_TrustDomInfoEnum level,
1865                                           union lsa_TrustedDomainInfo *info)
1866 {
1867         uint32_t *posix_offset = NULL;
1868         struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1869         struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1870         struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1871         uint32_t *enc_types = NULL;
1872         DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1873         struct trustDomainPasswords auth_struct;
1874         struct trustAuthInOutBlob *current_passwords = NULL;
1875         NTSTATUS nt_status;
1876         struct ldb_message **msgs;
1877         struct ldb_message *msg;
1878         bool add_outgoing = false;
1879         bool add_incoming = false;
1880         bool del_outgoing = false;
1881         bool del_incoming = false;
1882         bool del_forest_info = false;
1883         bool in_transaction = false;
1884         int ret;
1885         bool am_rodc;
1886
1887         switch (level) {
1888         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1889                 posix_offset = &info->posix_offset.posix_offset;
1890                 break;
1891         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1892                 info_ex = &info->info_ex;
1893                 break;
1894         case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1895                 auth_info = &info->auth_info;
1896                 break;
1897         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1898                 posix_offset = &info->full_info.posix_offset.posix_offset;
1899                 info_ex = &info->full_info.info_ex;
1900                 auth_info = &info->full_info.auth_info;
1901                 break;
1902         case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1903                 auth_info_int = &info->auth_info_internal;
1904                 break;
1905         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1906                 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1907                 info_ex = &info->full_info_internal.info_ex;
1908                 auth_info_int = &info->full_info_internal.auth_info;
1909                 break;
1910         case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1911                 enc_types = &info->enc_types.enc_types;
1912                 break;
1913         default:
1914                 return NT_STATUS_INVALID_PARAMETER;
1915         }
1916
1917         if (auth_info) {
1918                 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1919                                                   &trustAuthIncoming,
1920                                                   &trustAuthOutgoing);
1921                 if (!NT_STATUS_IS_OK(nt_status)) {
1922                         return nt_status;
1923                 }
1924                 if (trustAuthIncoming.data) {
1925                         /* This does the decode of some of this twice, but it is easier that way */
1926                         nt_status = auth_info_2_trustauth_inout(mem_ctx,
1927                                                                 auth_info->incoming_count,
1928                                                                 auth_info->incoming_current_auth_info,
1929                                                                 NULL,
1930                                                                 &current_passwords);
1931                         if (!NT_STATUS_IS_OK(nt_status)) {
1932                                 return nt_status;
1933                         }
1934                 }
1935         }
1936
1937         /* decode auth_info_int if set */
1938         if (auth_info_int) {
1939
1940                 /* now decrypt blob */
1941                 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1942                                             auth_info_int->auth_blob.size);
1943
1944                 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1945                                                    &auth_blob, &auth_struct);
1946                 if (!NT_STATUS_IS_OK(nt_status)) {
1947                         return nt_status;
1948                 }
1949         }
1950
1951         if (info_ex) {
1952                 /* verify data matches */
1953                 if (info_ex->trust_attributes &
1954                     LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1955                         /* TODO: check what behavior level we have */
1956                        if (strcasecmp_m(p_state->domain_dns,
1957                                         p_state->forest_dns) != 0) {
1958                                 return NT_STATUS_INVALID_DOMAIN_STATE;
1959                         }
1960                 }
1961
1962                 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1963                 if (ret == LDB_SUCCESS && am_rodc) {
1964                         return NT_STATUS_NO_SUCH_DOMAIN;
1965                 }
1966
1967                 /* verify only one object matches the dns/netbios/sid
1968                  * triplet and that this is the one we already have */
1969                 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1970                                     p_state->system_dn,
1971                                     info_ex->domain_name.string,
1972                                     info_ex->netbios_name.string,
1973                                     info_ex->sid, &msgs);
1974                 if (!NT_STATUS_IS_OK(nt_status)) {
1975                         return nt_status;
1976                 }
1977                 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1978                         return NT_STATUS_OBJECT_NAME_COLLISION;
1979                 }
1980                 talloc_free(msgs);
1981         }
1982
1983         /* TODO: should we fetch previous values from the existing entry
1984          * and append them ? */
1985         if (auth_info_int && auth_struct.incoming.count) {
1986                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1987                                                      &auth_struct.incoming,
1988                                                      &trustAuthIncoming);
1989                 if (!NT_STATUS_IS_OK(nt_status)) {
1990                         return nt_status;
1991                 }
1992
1993                 current_passwords = &auth_struct.incoming;
1994
1995         } else {
1996                 trustAuthIncoming = data_blob(NULL, 0);
1997         }
1998
1999         if (auth_info_int && auth_struct.outgoing.count) {
2000                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
2001                                                      &auth_struct.outgoing,
2002                                                      &trustAuthOutgoing);
2003                 if (!NT_STATUS_IS_OK(nt_status)) {
2004                         return nt_status;
2005                 }
2006         } else {
2007                 trustAuthOutgoing = data_blob(NULL, 0);
2008         }
2009
2010         msg = ldb_msg_new(mem_ctx);
2011         if (msg == NULL) {
2012                 return NT_STATUS_NO_MEMORY;
2013         }
2014         msg->dn = dom_msg->dn;
2015
2016         if (posix_offset) {
2017                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2018                                                   dom_msg, msg,
2019                                                   "trustPosixOffset",
2020                                                   *posix_offset, NULL);
2021                 if (!NT_STATUS_IS_OK(nt_status)) {
2022                         return nt_status;
2023                 }
2024         }
2025
2026         if (info_ex) {
2027                 uint32_t origattrs;
2028                 uint32_t changed_attrs;
2029                 uint32_t origdir;
2030                 int origtype;
2031
2032                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2033                                                   dom_msg, msg,
2034                                                   "trustDirection",
2035                                                   info_ex->trust_direction,
2036                                                   &origdir);
2037                 if (!NT_STATUS_IS_OK(nt_status)) {
2038                         return nt_status;
2039                 }
2040
2041                 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2042                         if (auth_info != NULL && trustAuthIncoming.length > 0) {
2043                                 add_incoming = true;
2044                         }
2045                 }
2046                 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2047                         if (auth_info != NULL && trustAuthOutgoing.length > 0) {
2048                                 add_outgoing = true;
2049                         }
2050                 }
2051
2052                 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
2053                     !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
2054                         del_incoming = true;
2055                 }
2056                 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
2057                     !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
2058                         del_outgoing = true;
2059                 }
2060
2061                 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
2062                 if (origtype == -1 || origtype != info_ex->trust_type) {
2063                         DEBUG(1, ("Attempted to change trust type! "
2064                                   "Operation not handled\n"));
2065                         return NT_STATUS_INVALID_PARAMETER;
2066                 }
2067
2068                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2069                                                   dom_msg, msg,
2070                                                   "trustAttributes",
2071                                                   info_ex->trust_attributes,
2072                                                   &origattrs);
2073                 if (!NT_STATUS_IS_OK(nt_status)) {
2074                         return nt_status;
2075                 }
2076                 /* TODO: check forestFunctionality from ldb opaque */
2077                 /* TODO: check what is set makes sense */
2078
2079                 changed_attrs = origattrs ^ info_ex->trust_attributes;
2080                 if (changed_attrs & ~LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
2081                         /*
2082                          * For now we only allow
2083                          * LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE to be changed.
2084                          *
2085                          * TODO: we may need to support more attribute changes
2086                          */
2087                         DEBUG(1, ("Attempted to change trust attributes "
2088                                   "(0x%08x != 0x%08x)! "
2089                                   "Operation not handled yet...\n",
2090                                   (unsigned)origattrs,
2091                                   (unsigned)info_ex->trust_attributes));
2092                         return NT_STATUS_INVALID_PARAMETER;
2093                 }
2094
2095                 if (!(info_ex->trust_attributes &
2096                       LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE))
2097                 {
2098                         struct ldb_message_element *orig_forest_el = NULL;
2099
2100                         orig_forest_el = ldb_msg_find_element(dom_msg,
2101                                                 "msDS-TrustForestTrustInfo");
2102                         if (orig_forest_el != NULL) {
2103                                 del_forest_info = true;
2104                         }
2105                 }
2106         }
2107
2108         if (enc_types) {
2109                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2110                                                   dom_msg, msg,
2111                                                   "msDS-SupportedEncryptionTypes",
2112                                                   *enc_types, NULL);
2113                 if (!NT_STATUS_IS_OK(nt_status)) {
2114                         return nt_status;
2115                 }
2116         }
2117
2118         if (add_incoming || del_incoming) {
2119                 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
2120                                         LDB_FLAG_MOD_REPLACE, NULL);
2121                 if (ret != LDB_SUCCESS) {
2122                         return NT_STATUS_NO_MEMORY;
2123                 }
2124                 if (add_incoming) {
2125                         ret = ldb_msg_add_value(msg, "trustAuthIncoming",
2126                                                 &trustAuthIncoming, NULL);
2127                         if (ret != LDB_SUCCESS) {
2128                                 return NT_STATUS_NO_MEMORY;
2129                         }
2130                 }
2131         }
2132         if (add_outgoing || del_outgoing) {
2133                 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
2134                                         LDB_FLAG_MOD_REPLACE, NULL);
2135                 if (ret != LDB_SUCCESS) {
2136                         return NT_STATUS_NO_MEMORY;
2137                 }
2138                 if (add_outgoing) {
2139                         ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
2140                                                 &trustAuthOutgoing, NULL);
2141                         if (ret != LDB_SUCCESS) {
2142                                 return NT_STATUS_NO_MEMORY;
2143                         }
2144                 }
2145         }
2146         if (del_forest_info) {
2147                 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
2148                                         LDB_FLAG_MOD_REPLACE, NULL);
2149                 if (ret != LDB_SUCCESS) {
2150                         return NT_STATUS_NO_MEMORY;
2151                 }
2152         }
2153
2154         /* start transaction */
2155         ret = ldb_transaction_start(p_state->sam_ldb);
2156         if (ret != LDB_SUCCESS) {
2157                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2158         }
2159         in_transaction = true;
2160
2161         if (msg->num_elements) {
2162                 ret = ldb_modify(p_state->sam_ldb, msg);
2163                 if (ret != LDB_SUCCESS) {
2164                         DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
2165                                  ldb_dn_get_linearized(msg->dn),
2166                                  ldb_errstring(p_state->sam_ldb)));
2167                         nt_status = dsdb_ldb_err_to_ntstatus(ret);
2168                         goto done;
2169                 }
2170         }
2171
2172         if (add_incoming || del_incoming) {
2173                 const char *netbios_name;
2174
2175                 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
2176                                                            "flatname", NULL);
2177                 if (!netbios_name) {
2178                         nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
2179                         goto done;
2180                 }
2181
2182                 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
2183                 nt_status = update_trust_user(mem_ctx,
2184                                               p_state->sam_ldb,
2185                                               p_state->domain_dn,
2186                                               del_incoming,
2187                                               netbios_name,
2188                                               current_passwords);
2189                 if (!NT_STATUS_IS_OK(nt_status)) {
2190                         goto done;
2191                 }
2192         }
2193
2194         /* ok, all fine, commit transaction and return */
2195         ret = ldb_transaction_commit(p_state->sam_ldb);
2196         if (ret != LDB_SUCCESS) {
2197                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2198         }
2199         in_transaction = false;
2200
2201         nt_status = NT_STATUS_OK;
2202
2203 done:
2204         if (in_transaction) {
2205                 ldb_transaction_cancel(p_state->sam_ldb);
2206         }
2207         return nt_status;
2208 }
2209
2210 /*
2211   lsa_SetInfomrationTrustedDomain
2212 */
2213 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
2214                                 struct dcesrv_call_state *dce_call,
2215                                 TALLOC_CTX *mem_ctx,
2216                                 struct lsa_SetInformationTrustedDomain *r)
2217 {
2218         struct dcesrv_handle *h;
2219         struct lsa_trusted_domain_state *td_state;
2220         struct ldb_message **msgs;
2221         NTSTATUS nt_status;
2222
2223         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
2224                            LSA_HANDLE_TRUSTED_DOMAIN);
2225
2226         td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2227
2228         /* get the trusted domain object */
2229         nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
2230                             td_state->trusted_domain_dn,
2231                             NULL, NULL, NULL, &msgs);
2232         if (!NT_STATUS_IS_OK(nt_status)) {
2233                 if (NT_STATUS_EQUAL(nt_status,
2234                                     NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2235                         return nt_status;
2236                 }
2237                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2238         }
2239
2240         return setInfoTrustedDomain_base(dce_call, td_state->policy, mem_ctx,
2241                                          msgs[0], r->in.level, r->in.info);
2242 }
2243
2244
2245 /*
2246   lsa_DeleteTrustedDomain
2247 */
2248 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2249                                       struct lsa_DeleteTrustedDomain *r)
2250 {
2251         NTSTATUS status;
2252         struct lsa_OpenTrustedDomain opn = {{0},{0}};
2253         struct lsa_DeleteObject del;
2254         struct dcesrv_handle *h;
2255
2256         opn.in.handle = r->in.handle;
2257         opn.in.sid = r->in.dom_sid;
2258         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2259         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2260         if (!opn.out.trustdom_handle) {
2261                 return NT_STATUS_NO_MEMORY;
2262         }
2263         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2264         if (!NT_STATUS_IS_OK(status)) {
2265                 return status;
2266         }
2267
2268         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2269         talloc_steal(mem_ctx, h);
2270
2271         del.in.handle = opn.out.trustdom_handle;
2272         del.out.handle = opn.out.trustdom_handle;
2273         status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
2274         if (!NT_STATUS_IS_OK(status)) {
2275                 return status;
2276         }
2277         return NT_STATUS_OK;
2278 }
2279
2280 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
2281                                      struct ldb_message *msg,
2282                                      struct lsa_TrustDomainInfoInfoEx *info_ex)
2283 {
2284         info_ex->domain_name.string
2285                 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2286         info_ex->netbios_name.string
2287                 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2288         info_ex->sid
2289                 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2290         info_ex->trust_direction
2291                 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2292         info_ex->trust_type
2293                 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2294         info_ex->trust_attributes
2295                 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2296         return NT_STATUS_OK;
2297 }
2298
2299 /*
2300   lsa_QueryTrustedDomainInfo
2301 */
2302 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2303                                            struct lsa_QueryTrustedDomainInfo *r)
2304 {
2305         union lsa_TrustedDomainInfo *info = NULL;
2306         struct dcesrv_handle *h;
2307         struct lsa_trusted_domain_state *trusted_domain_state;
2308         struct ldb_message *msg;
2309         int ret;
2310         struct ldb_message **res;
2311         const char *attrs[] = {
2312                 "flatname",
2313                 "trustPartner",
2314                 "securityIdentifier",
2315                 "trustDirection",
2316                 "trustType",
2317                 "trustAttributes",
2318                 "msDs-supportedEncryptionTypes",
2319                 NULL
2320         };
2321
2322         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2323
2324         trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2325
2326         /* pull all the user attributes */
2327         ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2328                               trusted_domain_state->trusted_domain_dn, &res, attrs);
2329         if (ret != 1) {
2330                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2331         }
2332         msg = res[0];
2333
2334         info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2335         if (!info) {
2336                 return NT_STATUS_NO_MEMORY;
2337         }
2338         *r->out.info = info;
2339
2340         switch (r->in.level) {
2341         case LSA_TRUSTED_DOMAIN_INFO_NAME:
2342                 info->name.netbios_name.string
2343                         = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2344                 break;
2345         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2346                 info->posix_offset.posix_offset
2347                         = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2348                 break;
2349 #if 0  /* Win2k3 doesn't implement this */
2350         case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2351                 r->out.info->info_basic.netbios_name.string
2352                         = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2353                 r->out.info->info_basic.sid
2354                         = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2355                 break;
2356 #endif
2357         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2358                 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2359
2360         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2361                 ZERO_STRUCT(info->full_info);
2362                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2363         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2364                 ZERO_STRUCT(info->full_info2_internal);
2365                 info->full_info2_internal.posix_offset.posix_offset
2366                         = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2367                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2368
2369         case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2370                 info->enc_types.enc_types
2371                         = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2372                 break;
2373
2374         case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2375         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2376                 /* oops, we don't want to return the info after all */
2377                 talloc_free(info);
2378                 *r->out.info = NULL;
2379                 return NT_STATUS_INVALID_PARAMETER;
2380         default:
2381                 /* oops, we don't want to return the info after all */
2382                 talloc_free(info);
2383                 *r->out.info = NULL;
2384                 return NT_STATUS_INVALID_INFO_CLASS;
2385         }
2386
2387         return NT_STATUS_OK;
2388 }
2389
2390
2391 /*
2392   lsa_QueryTrustedDomainInfoBySid
2393 */
2394 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2395                                                 struct lsa_QueryTrustedDomainInfoBySid *r)
2396 {
2397         NTSTATUS status;
2398         struct lsa_OpenTrustedDomain opn = {{0},{0}};
2399         struct lsa_QueryTrustedDomainInfo query;
2400         struct dcesrv_handle *h;
2401
2402         opn.in.handle = r->in.handle;
2403         opn.in.sid = r->in.dom_sid;
2404         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2405         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2406         if (!opn.out.trustdom_handle) {
2407                 return NT_STATUS_NO_MEMORY;
2408         }
2409         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2410         if (!NT_STATUS_IS_OK(status)) {
2411                 return status;
2412         }
2413
2414         /* Ensure this handle goes away at the end of this call */
2415         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2416         talloc_steal(mem_ctx, h);
2417
2418         query.in.trustdom_handle = opn.out.trustdom_handle;
2419         query.in.level = r->in.level;
2420         query.out.info = r->out.info;
2421         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2422         if (!NT_STATUS_IS_OK(status)) {
2423                 return status;
2424         }
2425
2426         return NT_STATUS_OK;
2427 }
2428
2429 /*
2430   lsa_SetTrustedDomainInfoByName
2431 */
2432 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2433                                                TALLOC_CTX *mem_ctx,
2434                                                struct lsa_SetTrustedDomainInfoByName *r)
2435 {
2436         struct dcesrv_handle *policy_handle;
2437         struct lsa_policy_state *policy_state;
2438         struct ldb_message **msgs;
2439         NTSTATUS nt_status;
2440
2441         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2442         policy_state = policy_handle->data;
2443
2444         /* get the trusted domain object */
2445         nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2446                             policy_state->domain_dn,
2447                             r->in.trusted_domain->string,
2448                             r->in.trusted_domain->string,
2449                             NULL, &msgs);
2450         if (!NT_STATUS_IS_OK(nt_status)) {
2451                 if (NT_STATUS_EQUAL(nt_status,
2452                                     NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2453                         return nt_status;
2454                 }
2455                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2456         }
2457
2458         return setInfoTrustedDomain_base(dce_call, policy_state, mem_ctx,
2459                                          msgs[0], r->in.level, r->in.info);
2460 }
2461
2462 /*
2463    lsa_QueryTrustedDomainInfoByName
2464 */
2465 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2466                                                  TALLOC_CTX *mem_ctx,
2467                                                  struct lsa_QueryTrustedDomainInfoByName *r)
2468 {
2469         NTSTATUS status;
2470         struct lsa_OpenTrustedDomainByName opn = {{0},{0}};
2471         struct lsa_QueryTrustedDomainInfo query;
2472         struct dcesrv_handle *h;
2473
2474         opn.in.handle = r->in.handle;
2475         opn.in.name = *r->in.trusted_domain;
2476         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2477         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2478         if (!opn.out.trustdom_handle) {
2479                 return NT_STATUS_NO_MEMORY;
2480         }
2481         status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2482         if (!NT_STATUS_IS_OK(status)) {
2483                 return status;
2484         }
2485
2486         /* Ensure this handle goes away at the end of this call */
2487         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2488         talloc_steal(mem_ctx, h);
2489
2490         query.in.trustdom_handle = opn.out.trustdom_handle;
2491         query.in.level = r->in.level;
2492         query.out.info = r->out.info;
2493         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2494         if (!NT_STATUS_IS_OK(status)) {
2495                 return status;
2496         }
2497
2498         return NT_STATUS_OK;
2499 }
2500
2501 /*
2502   lsa_CloseTrustedDomainEx
2503 */
2504 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2505                                          TALLOC_CTX *mem_ctx,
2506                                          struct lsa_CloseTrustedDomainEx *r)
2507 {
2508         /* The result of a bad hair day from an IDL programmer?  Not
2509          * implmented in Win2k3.  You should always just lsa_Close
2510          * anyway. */
2511         return NT_STATUS_NOT_IMPLEMENTED;
2512 }
2513
2514
2515 /*
2516   comparison function for sorting lsa_DomainInformation array
2517 */
2518 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2519 {
2520         return strcasecmp_m(e1->name.string, e2->name.string);
2521 }
2522
2523 /*
2524   lsa_EnumTrustDom
2525 */
2526 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2527                                  struct lsa_EnumTrustDom *r)
2528 {
2529         struct dcesrv_handle *policy_handle;
2530         struct lsa_DomainInfo *entries;
2531         struct lsa_policy_state *policy_state;
2532         struct ldb_message **domains;
2533         const char *attrs[] = {
2534                 "flatname",
2535                 "securityIdentifier",
2536                 NULL
2537         };
2538
2539
2540         int count, i;
2541
2542         *r->out.resume_handle = 0;
2543
2544         r->out.domains->domains = NULL;
2545         r->out.domains->count = 0;
2546
2547         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2548
2549         policy_state = policy_handle->data;
2550
2551         /* search for all users in this domain. This could possibly be cached and
2552            resumed based on resume_key */
2553         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2554                              "objectclass=trustedDomain");
2555         if (count < 0) {
2556                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2557         }
2558
2559         /* convert to lsa_TrustInformation format */
2560         entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2561         if (!entries) {
2562                 return NT_STATUS_NO_MEMORY;
2563         }
2564         for (i=0;i<count;i++) {
2565                 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2566                 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2567         }
2568
2569         /* sort the results by name */
2570         TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2571
2572         if (*r->in.resume_handle >= count) {
2573                 *r->out.resume_handle = -1;
2574
2575                 return NT_STATUS_NO_MORE_ENTRIES;
2576         }
2577
2578         /* return the rest, limit by max_size. Note that we
2579            use the w2k3 element size value of 60 */
2580         r->out.domains->count = count - *r->in.resume_handle;
2581         r->out.domains->count = MIN(r->out.domains->count,
2582                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2583
2584         r->out.domains->domains = entries + *r->in.resume_handle;
2585         r->out.domains->count = r->out.domains->count;
2586
2587         if (r->out.domains->count < count - *r->in.resume_handle) {
2588                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2589                 return STATUS_MORE_ENTRIES;
2590         }
2591
2592         /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2593          * always be larger than the previous input resume handle, in
2594          * particular when hitting the last query it is vital to set the
2595          * resume handle correctly to avoid infinite client loops, as
2596          * seen e.g. with Windows XP SP3 when resume handle is 0 and
2597          * status is NT_STATUS_OK - gd */
2598
2599         *r->out.resume_handle = (uint32_t)-1;
2600
2601         return NT_STATUS_OK;
2602 }
2603
2604 /*
2605   comparison function for sorting lsa_DomainInformation array
2606 */
2607 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2608 {
2609         return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2610 }
2611
2612 /*
2613   lsa_EnumTrustedDomainsEx
2614 */
2615 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2616                                         struct lsa_EnumTrustedDomainsEx *r)
2617 {
2618         struct dcesrv_handle *policy_handle;
2619         struct lsa_TrustDomainInfoInfoEx *entries;
2620         struct lsa_policy_state *policy_state;
2621         struct ldb_message **domains;
2622         const char *attrs[] = {
2623                 "flatname",
2624                 "trustPartner",
2625                 "securityIdentifier",
2626                 "trustDirection",
2627                 "trustType",
2628                 "trustAttributes",
2629                 NULL
2630         };
2631         NTSTATUS nt_status;
2632
2633         int count, i;
2634
2635         *r->out.resume_handle = 0;
2636
2637         r->out.domains->domains = NULL;
2638         r->out.domains->count = 0;
2639
2640         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2641
2642         policy_state = policy_handle->data;
2643
2644         /* search for all users in this domain. This could possibly be cached and
2645            resumed based on resume_key */
2646         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2647                              "objectclass=trustedDomain");
2648         if (count < 0) {
2649                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2650         }
2651
2652         /* convert to lsa_DomainInformation format */
2653         entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2654         if (!entries) {
2655                 return NT_STATUS_NO_MEMORY;
2656         }
2657         for (i=0;i<count;i++) {
2658                 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2659                 if (!NT_STATUS_IS_OK(nt_status)) {
2660                         return nt_status;
2661                 }
2662         }
2663
2664         /* sort the results by name */
2665         TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2666
2667         if (*r->in.resume_handle >= count) {
2668                 *r->out.resume_handle = -1;
2669
2670                 return NT_STATUS_NO_MORE_ENTRIES;
2671         }
2672
2673         /* return the rest, limit by max_size. Note that we
2674            use the w2k3 element size value of 60 */
2675         r->out.domains->count = count - *r->in.resume_handle;
2676         r->out.domains->count = MIN(r->out.domains->count,
2677                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2678
2679         r->out.domains->domains = entries + *r->in.resume_handle;
2680         r->out.domains->count = r->out.domains->count;
2681
2682         if (r->out.domains->count < count - *r->in.resume_handle) {
2683                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2684                 return STATUS_MORE_ENTRIES;
2685         }
2686
2687         *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2688
2689         return NT_STATUS_OK;
2690 }
2691
2692
2693 /*
2694   lsa_OpenAccount
2695 */
2696 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2697                                 struct lsa_OpenAccount *r)
2698 {
2699         struct dcesrv_handle *h, *ah;
2700         struct lsa_policy_state *state;
2701         struct lsa_account_state *astate;
2702
2703         ZERO_STRUCTP(r->out.acct_handle);
2704
2705         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2706
2707         state = h->data;
2708
2709         astate = talloc(dce_call->conn, struct lsa_account_state);
2710         if (astate == NULL) {
2711                 return NT_STATUS_NO_MEMORY;
2712         }
2713
2714         astate->account_sid = dom_sid_dup(astate, r->in.sid);
2715         if (astate->account_sid == NULL) {
2716                 talloc_free(astate);
2717                 return NT_STATUS_NO_MEMORY;
2718         }
2719
2720         astate->policy = talloc_reference(astate, state);
2721         astate->access_mask = r->in.access_mask;
2722
2723         /*
2724          * For now we grant all requested access.
2725          *
2726          * We will fail at the ldb layer later.
2727          */
2728         if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
2729                 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
2730                 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
2731         }
2732         se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
2733
2734         DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X] - success.\n",
2735                   __func__, dom_sid_string(mem_ctx, astate->account_sid),
2736                  (unsigned)r->in.access_mask,
2737                  (unsigned)astate->access_mask));
2738
2739         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2740         if (!ah) {
2741                 talloc_free(astate);
2742                 return NT_STATUS_NO_MEMORY;
2743         }
2744
2745         ah->data = talloc_steal(ah, astate);
2746
2747         *r->out.acct_handle = ah->wire_handle;
2748
2749         return NT_STATUS_OK;
2750 }
2751
2752
2753 /*
2754   lsa_EnumPrivsAccount
2755 */
2756 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2757                                      TALLOC_CTX *mem_ctx,
2758                                      struct lsa_EnumPrivsAccount *r)
2759 {
2760         struct dcesrv_handle *h;
2761         struct lsa_account_state *astate;
2762         int ret;
2763         unsigned int i, j;
2764         struct ldb_message **res;
2765         const char * const attrs[] = { "privilege", NULL};
2766         struct ldb_message_element *el;
2767         const char *sidstr;
2768         struct lsa_PrivilegeSet *privs;
2769
2770         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2771
2772         astate = h->data;
2773
2774         privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2775         if (privs == NULL) {
2776                 return NT_STATUS_NO_MEMORY;
2777         }
2778         privs->count = 0;
2779         privs->unknown = 0;
2780         privs->set = NULL;
2781
2782         *r->out.privs = privs;
2783
2784         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2785         if (sidstr == NULL) {
2786                 return NT_STATUS_NO_MEMORY;
2787         }
2788
2789         ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2790                            "objectSid=%s", sidstr);
2791         if (ret < 0) {
2792                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2793         }
2794         if (ret != 1) {
2795                 return NT_STATUS_OK;
2796         }
2797
2798         el = ldb_msg_find_element(res[0], "privilege");
2799         if (el == NULL || el->num_values == 0) {
2800                 return NT_STATUS_OK;
2801         }
2802
2803         privs->set = talloc_array(privs,
2804                                   struct lsa_LUIDAttribute, el->num_values);
2805         if (privs->set == NULL) {
2806                 return NT_STATUS_NO_MEMORY;
2807         }
2808
2809         j = 0;
2810         for (i=0;i<el->num_values;i++) {
2811                 int id = sec_privilege_id((const char *)el->values[i].data);
2812                 if (id == SEC_PRIV_INVALID) {
2813                         /* Perhaps an account right, not a privilege */
2814                         continue;
2815                 }
2816                 privs->set[j].attribute = 0;
2817                 privs->set[j].luid.low = id;
2818                 privs->set[j].luid.high = 0;
2819                 j++;
2820         }
2821
2822         privs->count = j;
2823
2824         return NT_STATUS_OK;
2825 }
2826
2827 /*
2828   lsa_EnumAccountRights
2829 */
2830 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2831                                       TALLOC_CTX *mem_ctx,
2832                                       struct lsa_EnumAccountRights *r)
2833 {
2834         struct dcesrv_handle *h;
2835         struct lsa_policy_state *state;
2836         int ret;
2837         unsigned int i;
2838         struct ldb_message **res;
2839         const char * const attrs[] = { "privilege", NULL};
2840         const char *sidstr;
2841         struct ldb_message_element *el;
2842
2843         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2844
2845         state = h->data;
2846
2847         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2848         if (sidstr == NULL) {
2849                 return NT_STATUS_NO_MEMORY;
2850         }
2851
2852         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2853                            "(&(objectSid=%s)(privilege=*))", sidstr);
2854         if (ret == 0) {
2855                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2856         }
2857         if (ret != 1) {
2858                 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2859                           dom_sid_string(mem_ctx, r->in.sid),
2860                           ldb_errstring(state->pdb)));
2861                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2862         }
2863
2864         el = ldb_msg_find_element(res[0], "privilege");
2865         if (el == NULL || el->num_values == 0) {
2866                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2867         }
2868
2869         r->out.rights->count = el->num_values;
2870         r->out.rights->names = talloc_array(r->out.rights,
2871                                             struct lsa_StringLarge, r->out.rights->count);
2872         if (r->out.rights->names == NULL) {
2873                 return NT_STATUS_NO_MEMORY;
2874         }
2875
2876         for (i=0;i<el->num_values;i++) {
2877                 r->out.rights->names[i].string = (const char *)el->values[i].data;
2878         }
2879
2880         return NT_STATUS_OK;
2881 }
2882
2883
2884
2885 /*
2886   helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2887 */
2888 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2889                                            TALLOC_CTX *mem_ctx,
2890                                            struct lsa_policy_state *state,
2891                                            int ldb_flag,
2892                                            struct dom_sid *sid,
2893                                            const struct lsa_RightSet *rights)
2894 {
2895         const char *sidstr, *sidndrstr;
2896         struct ldb_message *msg;
2897         struct ldb_message_element *el;
2898         int ret;
2899         uint32_t i;
2900         struct lsa_EnumAccountRights r2;
2901         char *dnstr;
2902
2903         if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2904             SECURITY_ADMINISTRATOR) {
2905                 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2906                 return NT_STATUS_ACCESS_DENIED;
2907         }
2908
2909         msg = ldb_msg_new(mem_ctx);
2910         if (msg == NULL) {
2911                 return NT_STATUS_NO_MEMORY;
2912         }
2913
2914         sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2915         if (sidndrstr == NULL) {
2916                 TALLOC_FREE(msg);
2917                 return NT_STATUS_NO_MEMORY;
2918         }
2919
2920         sidstr = dom_sid_string(msg, sid);
2921         if (sidstr == NULL) {
2922                 TALLOC_FREE(msg);
2923                 return NT_STATUS_NO_MEMORY;
2924         }
2925
2926         dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2927         if (dnstr == NULL) {
2928                 TALLOC_FREE(msg);
2929                 return NT_STATUS_NO_MEMORY;
2930         }
2931
2932         msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2933         if (msg->dn == NULL) {
2934                 TALLOC_FREE(msg);
2935                 return NT_STATUS_NO_MEMORY;
2936         }
2937
2938         if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2939                 NTSTATUS status;
2940
2941                 r2.in.handle = &state->handle->wire_handle;
2942                 r2.in.sid = sid;
2943                 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2944
2945                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2946                 if (!NT_STATUS_IS_OK(status)) {
2947                         ZERO_STRUCTP(r2.out.rights);
2948                 }
2949         }
2950
2951         for (i=0;i<rights->count;i++) {
2952                 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2953                         if (sec_right_bit(rights->names[i].string) == 0) {
2954                                 talloc_free(msg);
2955                                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2956                         }
2957
2958                         talloc_free(msg);
2959                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2960                 }
2961
2962                 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2963                         uint32_t j;
2964                         for (j=0;j<r2.out.rights->count;j++) {
2965                                 if (strcasecmp_m(r2.out.rights->names[j].string,
2966                                                rights->names[i].string) == 0) {
2967                                         break;
2968                                 }
2969                         }
2970                         if (j != r2.out.rights->count) continue;
2971                 }
2972
2973                 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2974                 if (ret != LDB_SUCCESS) {
2975                         talloc_free(msg);
2976                         return NT_STATUS_NO_MEMORY;
2977                 }
2978         }
2979
2980         el = ldb_msg_find_element(msg, "privilege");
2981         if (!el) {
2982                 talloc_free(msg);
2983                 return NT_STATUS_OK;
2984         }
2985
2986         el->flags = ldb_flag;
2987
2988         ret = ldb_modify(state->pdb, msg);
2989         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2990                 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2991                         talloc_free(msg);
2992                         return NT_STATUS_NO_MEMORY;
2993                 }
2994                 ldb_msg_add_string(msg, "comment", "added via LSA");
2995                 ret = ldb_add(state->pdb, msg);
2996         }
2997         if (ret != LDB_SUCCESS) {
2998                 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2999                         talloc_free(msg);
3000                         return NT_STATUS_OK;
3001                 }
3002                 DEBUG(3, ("Could not %s attributes from %s: %s",
3003                           LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
3004                           ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
3005                 talloc_free(msg);
3006                 return NT_STATUS_UNEXPECTED_IO_ERROR;
3007         }
3008
3009         talloc_free(msg);
3010         return NT_STATUS_OK;
3011 }
3012
3013 /*
3014   lsa_AddPrivilegesToAccount
3015 */
3016 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3017                                            struct lsa_AddPrivilegesToAccount *r)
3018 {
3019         struct lsa_RightSet rights;
3020         struct dcesrv_handle *h;
3021         struct lsa_account_state *astate;
3022         uint32_t i;
3023
3024         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3025
3026         astate = h->data;
3027
3028         rights.count = r->in.privs->count;
3029         rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
3030         if (rights.names == NULL) {
3031                 return NT_STATUS_NO_MEMORY;
3032         }
3033         for (i=0;i<rights.count;i++) {
3034                 int id = r->in.privs->set[i].luid.low;
3035                 if (r->in.privs->set[i].luid.high) {
3036                         return NT_STATUS_NO_SUCH_PRIVILEGE;
3037                 }
3038                 rights.names[i].string = sec_privilege_name(id);
3039                 if (rights.names[i].string == NULL) {
3040                         return NT_STATUS_NO_SUCH_PRIVILEGE;
3041                 }
3042         }
3043
3044         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3045                                           LDB_FLAG_MOD_ADD, astate->account_sid,
3046                                           &rights);
3047 }
3048
3049
3050 /*
3051   lsa_RemovePrivilegesFromAccount
3052 */
3053 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3054                                                 struct lsa_RemovePrivilegesFromAccount *r)
3055 {
3056         struct lsa_RightSet *rights;
3057         struct dcesrv_handle *h;
3058         struct lsa_account_state *astate;
3059         uint32_t i;
3060
3061         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3062
3063         astate = h->data;
3064
3065         rights = talloc(mem_ctx, struct lsa_RightSet);
3066
3067         if (r->in.remove_all == 1 &&
3068             r->in.privs == NULL) {
3069                 struct lsa_EnumAccountRights r2;
3070                 NTSTATUS status;
3071
3072                 r2.in.handle = &astate->policy->handle->wire_handle;
3073                 r2.in.sid = astate->account_sid;
3074                 r2.out.rights = rights;
3075
3076                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
3077                 if (!NT_STATUS_IS_OK(status)) {
3078                         return status;
3079                 }
3080
3081                 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3082                                                   LDB_FLAG_MOD_DELETE, astate->account_sid,
3083                                                   r2.out.rights);
3084         }
3085
3086         if (r->in.remove_all != 0) {
3087                 return NT_STATUS_INVALID_PARAMETER;
3088         }
3089
3090         rights->count = r->in.privs->count;
3091         rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
3092         if (rights->names == NULL) {
3093                 return NT_STATUS_NO_MEMORY;
3094         }
3095         for (i=0;i<rights->count;i++) {
3096                 int id = r->in.privs->set[i].luid.low;
3097                 if (r->in.privs->set[i].luid.high) {
3098                         return NT_STATUS_NO_SUCH_PRIVILEGE;
3099                 }
3100                 rights->names[i].string = sec_privilege_name(id);
3101                 if (rights->names[i].string == NULL) {
3102                         return NT_STATUS_NO_SUCH_PRIVILEGE;
3103                 }
3104         }
3105
3106         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3107                                           LDB_FLAG_MOD_DELETE, astate->account_sid,
3108                                           rights);
3109 }
3110
3111
3112 /*
3113   lsa_GetQuotasForAccount
3114 */
3115 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3116                        struct lsa_GetQuotasForAccount *r)
3117 {
3118         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3119 }
3120
3121
3122 /*
3123   lsa_SetQuotasForAccount
3124 */
3125 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3126                        struct lsa_SetQuotasForAccount *r)
3127 {
3128         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3129 }
3130
3131
3132 /*
3133   lsa_GetSystemAccessAccount
3134 */
3135 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3136                        struct lsa_GetSystemAccessAccount *r)
3137 {
3138         struct dcesrv_handle *h;
3139         struct lsa_account_state *astate;
3140         int ret;
3141         unsigned int i;
3142         struct ldb_message **res;
3143         const char * const attrs[] = { "privilege", NULL};
3144         struct ldb_message_element *el;
3145         const char *sidstr;
3146
3147         *(r->out.access_mask) = 0x00000000;
3148
3149         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3150
3151         astate = h->data;
3152
3153         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
3154         if (sidstr == NULL) {
3155                 return NT_STATUS_NO_MEMORY;
3156         }
3157
3158         ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
3159                            "objectSid=%s", sidstr);
3160         if (ret < 0) {
3161                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3162         }
3163         if (ret != 1) {
3164                 return NT_STATUS_OK;
3165         }
3166
3167         el = ldb_msg_find_element(res[0], "privilege");
3168         if (el == NULL || el->num_values == 0) {
3169                 return NT_STATUS_OK;
3170         }
3171
3172         for (i=0;i<el->num_values;i++) {
3173                 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
3174                 if (right_bit == 0) {
3175                         /* Perhaps an privilege, not a right */
3176                         continue;
3177                 }
3178                 *(r->out.access_mask) |= right_bit;
3179         }
3180
3181         return NT_STATUS_OK;
3182 }
3183
3184
3185 /*
3186   lsa_SetSystemAccessAccount
3187 */
3188 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3189                        struct lsa_SetSystemAccessAccount *r)
3190 {
3191         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3192 }
3193
3194
3195 /*
3196   lsa_CreateSecret
3197 */
3198 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3199                                  struct lsa_CreateSecret *r)
3200 {
3201         struct dcesrv_handle *policy_handle;
3202         struct lsa_policy_state *policy_state;
3203         struct lsa_secret_state *secret_state;
3204         struct dcesrv_handle *handle;
3205         struct ldb_message **msgs, *msg;
3206         const char *attrs[] = {
3207                 NULL
3208         };
3209
3210         const char *name;
3211
3212         int ret;
3213
3214         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3215         ZERO_STRUCTP(r->out.sec_handle);
3216
3217         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3218         {
3219         case SECURITY_SYSTEM:
3220         case SECURITY_ADMINISTRATOR:
3221                 break;
3222         default:
3223                 /* Users and annonymous are not allowed create secrets */
3224                 return NT_STATUS_ACCESS_DENIED;
3225         }
3226
3227         policy_state = policy_handle->data;
3228
3229         if (!r->in.name.string) {
3230                 return NT_STATUS_INVALID_PARAMETER;
3231         }
3232
3233         secret_state = talloc(mem_ctx, struct lsa_secret_state);
3234         NT_STATUS_HAVE_NO_MEMORY(secret_state);
3235         secret_state->policy = policy_state;
3236
3237         msg = ldb_msg_new(mem_ctx);
3238         if (msg == NULL) {
3239                 return NT_STATUS_NO_MEMORY;
3240         }
3241
3242         if (strncmp("G$", r->in.name.string, 2) == 0) {
3243                 const char *name2;
3244
3245                 secret_state->global = true;
3246
3247                 name = &r->in.name.string[2];
3248                 if (strlen(name) == 0) {
3249                         return NT_STATUS_INVALID_PARAMETER;
3250                 }
3251
3252                 name2 = talloc_asprintf(mem_ctx, "%s Secret",
3253                                         ldb_binary_encode_string(mem_ctx, name));
3254                 NT_STATUS_HAVE_NO_MEMORY(name2);
3255
3256                 /* We need to connect to the database as system, as this is one
3257                  * of the rare RPC calls that must read the secrets (and this
3258                  * is denied otherwise) */
3259                 secret_state->sam_ldb = talloc_reference(secret_state,
3260                                                          samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0));
3261                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3262
3263                 /* search for the secret record */
3264                 ret = gendb_search(secret_state->sam_ldb,
3265                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
3266                                    "(&(cn=%s)(objectclass=secret))",
3267                                    name2);
3268                 if (ret > 0) {
3269                         return NT_STATUS_OBJECT_NAME_COLLISION;
3270                 }
3271
3272                 if (ret < 0) {
3273                         DEBUG(0,("Failure searching for CN=%s: %s\n",
3274                                  name2, ldb_errstring(secret_state->sam_ldb)));
3275                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3276                 }
3277
3278                 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
3279                 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3280                 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
3281                         return NT_STATUS_NO_MEMORY;
3282                 }
3283
3284                 ret = ldb_msg_add_string(msg, "cn", name2);
3285                 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3286         } else {
3287                 secret_state->global = false;
3288
3289                 name = r->in.name.string;
3290                 if (strlen(name) == 0) {
3291                         return NT_STATUS_INVALID_PARAMETER;
3292                 }
3293
3294                 secret_state->sam_ldb = talloc_reference(secret_state,
3295                                                          secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3296                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3297
3298                 /* search for the secret record */
3299                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3300                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3301                                    &msgs, attrs,
3302                                    "(&(cn=%s)(objectclass=secret))",
3303                                    ldb_binary_encode_string(mem_ctx, name));
3304                 if (ret > 0) {
3305                         return NT_STATUS_OBJECT_NAME_COLLISION;
3306                 }
3307
3308                 if (ret < 0) {
3309                         DEBUG(0,("Failure searching for CN=%s: %s\n",
3310                                  name, ldb_errstring(secret_state->sam_ldb)));
3311                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3312                 }
3313
3314                 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3315                                          "cn=%s,cn=LSA Secrets", name);
3316                 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3317                 ret = ldb_msg_add_string(msg, "cn", name);
3318                 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3319         }
3320
3321         ret = ldb_msg_add_string(msg, "objectClass", "secret");
3322         if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3323
3324         secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3325         NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3326
3327         /* create the secret */
3328         ret = ldb_add(secret_state->sam_ldb, msg);
3329         if (ret != LDB_SUCCESS) {
3330                 DEBUG(0,("Failed to create secret record %s: %s\n",
3331                          ldb_dn_get_linearized(msg->dn),
3332                          ldb_errstring(secret_state->sam_ldb)));
3333                 return NT_STATUS_ACCESS_DENIED;
3334         }
3335
3336         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3337         NT_STATUS_HAVE_NO_MEMORY(handle);
3338
3339         handle->data = talloc_steal(handle, secret_state);
3340
3341         secret_state->access_mask = r->in.access_mask;
3342         secret_state->policy = talloc_reference(secret_state, policy_state);
3343         NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3344
3345         *r->out.sec_handle = handle->wire_handle;
3346
3347         return NT_STATUS_OK;
3348 }
3349
3350
3351 /*
3352   lsa_OpenSecret
3353 */
3354 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3355                                struct lsa_OpenSecret *r)
3356 {
3357         struct dcesrv_handle *policy_handle;
3358
3359         struct lsa_policy_state *policy_state;
3360         struct lsa_secret_state *secret_state;
3361         struct dcesrv_handle *handle;
3362         struct ldb_message **msgs;
3363         const char *attrs[] = {
3364                 NULL
3365         };
3366
3367         const char *name;
3368
3369         int ret;
3370
3371         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3372         ZERO_STRUCTP(r->out.sec_handle);
3373         policy_state = policy_handle->data;
3374
3375         if (!r->in.name.string) {
3376                 return NT_STATUS_INVALID_PARAMETER;
3377         }
3378
3379         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3380         {
3381         case SECURITY_SYSTEM:
3382         case SECURITY_ADMINISTRATOR:
3383                 break;
3384         default:
3385                 /* Users and annonymous are not allowed to access secrets */
3386                 return NT_STATUS_ACCESS_DENIED;
3387         }
3388
3389         secret_state = talloc(mem_ctx, struct lsa_secret_state);
3390         if (!secret_state) {
3391                 return NT_STATUS_NO_MEMORY;
3392         }
3393         secret_state->policy = policy_state;
3394
3395         if (strncmp("G$", r->in.name.string, 2) == 0) {
3396                 name = &r->in.name.string[2];
3397                 /* 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) */
3398                 secret_state->sam_ldb = talloc_reference(secret_state,
3399                                                          samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0));
3400                 secret_state->global = true;
3401
3402                 if (strlen(name) < 1) {
3403                         return NT_STATUS_INVALID_PARAMETER;
3404                 }
3405
3406                 /* search for the secret record */
3407                 ret = gendb_search(secret_state->sam_ldb,
3408                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
3409                                    "(&(cn=%s Secret)(objectclass=secret))",
3410                                    ldb_binary_encode_string(mem_ctx, name));
3411                 if (ret == 0) {
3412                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3413                 }
3414
3415                 if (ret != 1) {
3416                         DEBUG(0,("Found %d records matching DN %s\n", ret,
3417                                  ldb_dn_get_linearized(policy_state->system_dn)));
3418                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3419                 }
3420         } else {
3421                 secret_state->global = false;
3422                 secret_state->sam_ldb = talloc_reference(secret_state,
3423                                                          secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3424
3425                 name = r->in.name.string;
3426                 if (strlen(name) < 1) {
3427                         return NT_STATUS_INVALID_PARAMETER;
3428                 }
3429
3430                 /* search for the secret record */
3431                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3432                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3433                                    &msgs, attrs,
3434                                    "(&(cn=%s)(objectclass=secret))",
3435                                    ldb_binary_encode_string(mem_ctx, name));
3436                 if (ret == 0) {
3437                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3438                 }
3439
3440                 if (ret != 1) {
3441                         DEBUG(0,("Found %d records matching CN=%s\n",
3442                                  ret, ldb_binary_encode_string(mem_ctx, name)));
3443                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3444                 }
3445         }
3446
3447         secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3448
3449         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3450         if (!handle) {
3451                 return NT_STATUS_NO_MEMORY;
3452         }
3453
3454         handle->data = talloc_steal(handle, secret_state);
3455
3456         secret_state->access_mask = r->in.access_mask;
3457         secret_state->policy = talloc_reference(secret_state, policy_state);
3458
3459         *r->out.sec_handle = handle->wire_handle;
3460
3461         return NT_STATUS_OK;
3462 }
3463
3464
3465 /*
3466   lsa_SetSecret
3467 */
3468 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3469                               struct lsa_SetSecret *r)
3470 {
3471
3472         struct dcesrv_handle *h;
3473         struct lsa_secret_state *secret_state;
3474         struct ldb_message *msg;
3475         DATA_BLOB session_key;
3476         DATA_BLOB crypt_secret, secret;
3477         struct ldb_val val;
3478         int ret;
3479         NTSTATUS status = NT_STATUS_OK;
3480
3481         struct timeval now = timeval_current();
3482         NTTIME nt_now = timeval_to_nttime(&now);
3483
3484         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3485
3486         secret_state = h->data;
3487
3488         msg = ldb_msg_new(mem_ctx);
3489         if (msg == NULL) {
3490                 return NT_STATUS_NO_MEMORY;
3491         }
3492
3493         msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3494         if (!msg->dn) {
3495                 return NT_STATUS_NO_MEMORY;
3496         }
3497         status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3498         if (!NT_STATUS_IS_OK(status)) {
3499                 return status;
3500         }
3501
3502         if (r->in.old_val) {
3503                 /* Decrypt */
3504                 crypt_secret.data = r->in.old_val->data;
3505                 crypt_secret.length = r->in.old_val->size;
3506
3507                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3508                 if (!NT_STATUS_IS_OK(status)) {
3509                         return status;
3510                 }
3511
3512                 val.data = secret.data;
3513                 val.length = secret.length;
3514
3515                 /* set value */
3516                 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3517                         return NT_STATUS_NO_MEMORY;
3518                 }
3519
3520                 /* set old value mtime */
3521                 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3522                                          mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3523                         return NT_STATUS_NO_MEMORY;
3524                 }
3525
3526         } else {
3527                 /* If the old value is not set, then migrate the
3528                  * current value to the old value */
3529                 const struct ldb_val *old_val;
3530                 NTTIME last_set_time;
3531                 struct ldb_message **res;
3532                 const char *attrs[] = {
3533                         "currentValue",
3534                         "lastSetTime",
3535                         NULL
3536                 };
3537
3538                 /* search for the secret record */
3539                 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3540                                       secret_state->secret_dn, &res, attrs);
3541                 if (ret == 0) {
3542                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3543                 }
3544
3545                 if (ret != 1) {
3546                         DEBUG(0,("Found %d records matching dn=%s\n", ret,
3547                                  ldb_dn_get_linearized(secret_state->secret_dn)));
3548                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3549                 }
3550
3551                 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3552                 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3553
3554                 if (old_val) {
3555                         /* set old value */
3556                         if (ldb_msg_add_value(msg, "priorValue",
3557                                               old_val, NULL) != LDB_SUCCESS) {
3558                                 return NT_STATUS_NO_MEMORY;
3559                         }
3560                 } else {
3561                         if (samdb_msg_add_delete(secret_state->sam_ldb,
3562                                                  mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3563                                 return NT_STATUS_NO_MEMORY;
3564                         }
3565                 }
3566
3567                 /* set old value mtime */
3568                 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3569                         if (samdb_msg_add_uint64(secret_state->sam_ldb,
3570                                                  mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3571                                 return NT_STATUS_NO_MEMORY;
3572                         }
3573                 } else {
3574                         if (samdb_msg_add_uint64(secret_state->sam_ldb,
3575                                                  mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3576                                 return NT_STATUS_NO_MEMORY;
3577                         }
3578                 }
3579         }
3580
3581         if (r->in.new_val) {
3582                 /* Decrypt */
3583                 crypt_secret.data = r->in.new_val->data;
3584                 crypt_secret.length = r->in.new_val->size;
3585
3586                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3587                 if (!NT_STATUS_IS_OK(status)) {
3588                         return status;
3589                 }
3590
3591                 val.data = secret.data;
3592                 val.length = secret.length;
3593
3594                 /* set value */
3595                 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3596                         return NT_STATUS_NO_MEMORY;
3597                 }
3598
3599                 /* set new value mtime */
3600                 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3601                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3602                         return NT_STATUS_NO_MEMORY;
3603                 }
3604         } else {
3605                 /* NULL out the NEW value */
3606                 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3607                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3608                         return NT_STATUS_NO_MEMORY;
3609                 }
3610                 if (samdb_msg_add_delete(secret_state->sam_ldb,
3611                                          mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3612                         return NT_STATUS_NO_MEMORY;
3613                 }
3614         }
3615
3616         /* modify the samdb record */
3617         ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3618         if (ret != LDB_SUCCESS) {
3619                 return dsdb_ldb_err_to_ntstatus(ret);
3620         }
3621
3622         return NT_STATUS_OK;
3623 }
3624
3625
3626 /*
3627   lsa_QuerySecret
3628 */
3629 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3630                                 struct lsa_QuerySecret *r)
3631 {
3632         struct dcesrv_handle *h;
3633         struct lsa_secret_state *secret_state;
3634         struct ldb_message *msg;
3635         DATA_BLOB session_key;
3636         DATA_BLOB crypt_secret, secret;
3637         int ret;
3638         struct ldb_message **res;
3639         const char *attrs[] = {
3640                 "currentValue",
3641                 "priorValue",
3642                 "lastSetTime",
3643                 "priorSetTime",
3644                 NULL
3645         };
3646
3647         NTSTATUS nt_status;
3648
3649         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3650
3651         /* Ensure user is permitted to read this... */
3652         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3653         {
3654         case SECURITY_SYSTEM:
3655         case SECURITY_ADMINISTRATOR:
3656                 break;
3657         default:
3658                 /* Users and annonymous are not allowed to read secrets */
3659                 return NT_STATUS_ACCESS_DENIED;
3660         }
3661
3662         secret_state = h->data;
3663
3664         /* pull all the user attributes */
3665         ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3666                               secret_state->secret_dn, &res, attrs);
3667         if (ret != 1) {
3668                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3669         }
3670         msg = res[0];
3671
3672         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3673         if (!NT_STATUS_IS_OK(nt_status)) {
3674                 return nt_status;
3675         }
3676
3677         if (r->in.old_val) {
3678                 const struct ldb_val *prior_val;
3679                 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3680                 if (!r->out.old_val) {
3681                         return NT_STATUS_NO_MEMORY;
3682                 }
3683                 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3684
3685                 if (prior_val && prior_val->length) {
3686                         secret.data = prior_val->data;
3687                         secret.length = prior_val->length;
3688
3689                         /* Encrypt */
3690                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3691                         if (!crypt_secret.length) {
3692                                 return NT_STATUS_NO_MEMORY;
3693                         }
3694                         r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3695                         if (!r->out.old_val->buf) {
3696                                 return NT_STATUS_NO_MEMORY;
3697                         }
3698                         r->out.old_val->buf->size = crypt_secret.length;
3699                         r->out.old_val->buf->length = crypt_secret.length;
3700                         r->out.old_val->buf->data = crypt_secret.data;
3701                 }
3702         }
3703
3704         if (r->in.old_mtime) {
3705                 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3706                 if (!r->out.old_mtime) {
3707                         return NT_STATUS_NO_MEMORY;
3708                 }
3709                 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3710         }
3711
3712         if (r->in.new_val) {
3713                 const struct ldb_val *new_val;
3714                 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3715                 if (!r->out.new_val) {
3716                         return NT_STATUS_NO_MEMORY;
3717                 }
3718
3719                 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3720
3721                 if (new_val && new_val->length) {
3722                         secret.data = new_val->data;
3723                         secret.length = new_val->length;
3724
3725                         /* Encrypt */
3726                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3727                         if (!crypt_secret.length) {
3728                                 return NT_STATUS_NO_MEMORY;
3729                         }
3730                         r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3731                         if (!r->out.new_val->buf) {
3732                                 return NT_STATUS_NO_MEMORY;
3733                         }
3734                         r->out.new_val->buf->length = crypt_secret.length;
3735                         r->out.new_val->buf->size = crypt_secret.length;
3736                         r->out.new_val->buf->data = crypt_secret.data;
3737                 }
3738         }
3739
3740         if (r->in.new_mtime) {
3741                 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3742                 if (!r->out.new_mtime) {
3743                         return NT_STATUS_NO_MEMORY;
3744                 }
3745                 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3746         }
3747
3748         return NT_STATUS_OK;
3749 }
3750
3751
3752 /*
3753   lsa_LookupPrivValue
3754 */
3755 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3756                                     TALLOC_CTX *mem_ctx,
3757                                     struct lsa_LookupPrivValue *r)
3758 {
3759         struct dcesrv_handle *h;
3760         int id;
3761
3762         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3763
3764         id = sec_privilege_id(r->in.name->string);
3765         if (id == SEC_PRIV_INVALID) {
3766                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3767         }
3768
3769         r->out.luid->low = id;
3770         r->out.luid->high = 0;
3771
3772         return NT_STATUS_OK;
3773 }
3774
3775
3776 /*
3777   lsa_LookupPrivName
3778 */
3779 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3780                                    TALLOC_CTX *mem_ctx,
3781                                    struct lsa_LookupPrivName *r)
3782 {
3783         struct dcesrv_handle *h;
3784         struct lsa_StringLarge *name;
3785         const char *privname;
3786
3787         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3788
3789         if (r->in.luid->high != 0) {
3790                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3791         }
3792
3793         privname = sec_privilege_name(r->in.luid->low);
3794         if (privname == NULL) {
3795                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3796         }
3797
3798         name = talloc(mem_ctx, struct lsa_StringLarge);
3799         if (name == NULL) {
3800                 return NT_STATUS_NO_MEMORY;
3801         }
3802
3803         name->string = privname;
3804
3805         *r->out.name = name;
3806
3807         return NT_STATUS_OK;
3808 }
3809
3810
3811 /*
3812   lsa_LookupPrivDisplayName
3813 */
3814 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3815                                           TALLOC_CTX *mem_ctx,
3816                                           struct lsa_LookupPrivDisplayName *r)
3817 {
3818         struct dcesrv_handle *h;
3819         struct lsa_StringLarge *disp_name = NULL;
3820         enum sec_privilege id;
3821
3822         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3823
3824         id = sec_privilege_id(r->in.name->string);
3825         if (id == SEC_PRIV_INVALID) {
3826                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3827         }
3828
3829         disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3830         if (disp_name == NULL) {
3831                 return NT_STATUS_NO_MEMORY;
3832         }
3833
3834         disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3835         if (disp_name->string == NULL) {
3836                 return NT_STATUS_INTERNAL_ERROR;
3837         }
3838
3839         *r->out.disp_name = disp_name;
3840         *r->out.returned_language_id = 0;
3841
3842         return NT_STATUS_OK;
3843 }
3844
3845
3846 /*
3847   lsa_EnumAccountsWithUserRight
3848 */
3849 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3850                                               TALLOC_CTX *mem_ctx,
3851                                               struct lsa_EnumAccountsWithUserRight *r)
3852 {
3853         struct dcesrv_handle *h;
3854         struct lsa_policy_state *state;
3855         int ret, i;
3856         struct ldb_message **res;
3857         const char * const attrs[] = { "objectSid", NULL};
3858         const char *privname;
3859
3860         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3861
3862         state = h->data;
3863
3864         if (r->in.name == NULL) {
3865                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3866         }
3867
3868         privname = r->in.name->string;
3869         if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3870                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3871         }
3872
3873         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3874                            "privilege=%s", privname);
3875         if (ret < 0) {
3876                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3877         }
3878         if (ret == 0) {
3879                 return NT_STATUS_NO_MORE_ENTRIES;
3880         }
3881
3882         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3883         if (r->out.sids->sids == NULL) {
3884                 return NT_STATUS_NO_MEMORY;
3885         }
3886         for (i=0;i<ret;i++) {
3887                 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3888                                                                 res[i], "objectSid");
3889                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3890         }
3891         r->out.sids->num_sids = ret;
3892
3893         return NT_STATUS_OK;
3894 }
3895
3896
3897 /*
3898   lsa_AddAccountRights
3899 */
3900 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3901                                      TALLOC_CTX *mem_ctx,
3902                                      struct lsa_AddAccountRights *r)
3903 {
3904         struct dcesrv_handle *h;
3905         struct lsa_policy_state *state;
3906
3907         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3908
3909         state = h->data;
3910
3911         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3912                                           LDB_FLAG_MOD_ADD,
3913                                           r->in.sid, r->in.rights);
3914 }
3915
3916
3917 /*
3918   lsa_RemoveAccountRights
3919 */
3920 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3921                                         TALLOC_CTX *mem_ctx,
3922                                         struct lsa_RemoveAccountRights *r)
3923 {
3924         struct dcesrv_handle *h;
3925         struct lsa_policy_state *state;
3926
3927         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3928
3929         state = h->data;
3930
3931         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3932                                           LDB_FLAG_MOD_DELETE,
3933                                           r->in.sid, r->in.rights);
3934 }
3935
3936
3937 /*
3938   lsa_StorePrivateData
3939 */
3940 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3941                        struct lsa_StorePrivateData *r)
3942 {
3943         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3944 }
3945
3946
3947 /*
3948   lsa_RetrievePrivateData
3949 */
3950 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3951                        struct lsa_RetrievePrivateData *r)
3952 {
3953         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3954 }
3955
3956
3957 /*
3958   lsa_GetUserName
3959 */
3960 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3961                                 struct lsa_GetUserName *r)
3962 {
3963         enum dcerpc_transport_t transport =
3964                 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
3965         NTSTATUS status = NT_STATUS_OK;
3966         const char *account_name;
3967         const char *authority_name;
3968         struct lsa_String *_account_name;
3969         struct lsa_String *_authority_name = NULL;
3970
3971         if (transport != NCACN_NP && transport != NCALRPC) {
3972                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3973         }
3974
3975         /* this is what w2k3 does */
3976         r->out.account_name = r->in.account_name;
3977         r->out.authority_name = r->in.authority_name;
3978
3979         if (r->in.account_name
3980             && *r->in.account_name
3981             /* && *(*r->in.account_name)->string */
3982             ) {
3983                 return NT_STATUS_INVALID_PARAMETER;
3984         }
3985
3986         if (r->in.authority_name
3987             && *r->in.authority_name
3988             /* && *(*r->in.authority_name)->string */
3989             ) {
3990                 return NT_STATUS_INVALID_PARAMETER;
3991         }
3992
3993         account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3994         authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3995
3996         _account_name = talloc(mem_ctx, struct lsa_String);
3997         NT_STATUS_HAVE_NO_MEMORY(_account_name);
3998         _account_name->string = account_name;
3999
4000         if (r->in.authority_name) {
4001                 _authority_name = talloc(mem_ctx, struct lsa_String);
4002                 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
4003                 _authority_name->string = authority_name;
4004         }
4005
4006         *r->out.account_name = _account_name;
4007         if (r->out.authority_name) {
4008                 *r->out.authority_name = _authority_name;
4009         }
4010
4011         return status;
4012 }
4013
4014 /*
4015   lsa_SetInfoPolicy2
4016 */
4017 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
4018                                    TALLOC_CTX *mem_ctx,
4019                                    struct lsa_SetInfoPolicy2 *r)
4020 {
4021         /* need to support these */
4022         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4023 }
4024
4025 static void kdc_get_policy(struct loadparm_context *lp_ctx,
4026                            struct smb_krb5_context *smb_krb5_context,
4027                            struct lsa_DomainInfoKerberos *k)
4028 {
4029         time_t svc_tkt_lifetime;
4030         time_t usr_tkt_lifetime;
4031         time_t renewal_lifetime;
4032
4033         /* These should be set and stored via Group Policy, but until then, some defaults are in order */
4034
4035         /* Our KDC always re-validates the client */
4036         k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
4037
4038         lpcfg_default_kdc_policy(lp_ctx, &svc_tkt_lifetime,
4039                                  &usr_tkt_lifetime, &renewal_lifetime);
4040
4041         unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
4042         unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
4043         unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
4044 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
4045         However in the parent function we basically just did a full
4046         krb5_context init with the only purpose of getting a global
4047         config option (the max skew), it would probably make more sense
4048         to have a lp_ or ldb global option as the samba default */
4049         if (smb_krb5_context) {
4050                 unix_to_nt_time(&k->clock_skew,
4051                                 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
4052         }
4053 #endif
4054         k->reserved = 0;
4055 }
4056 /*
4057   lsa_QueryDomainInformationPolicy
4058 */
4059 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4060                                                  TALLOC_CTX *mem_ctx,
4061                                                  struct lsa_QueryDomainInformationPolicy *r)
4062 {
4063         union lsa_DomainInformationPolicy *info;
4064
4065         info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
4066         if (!info) {
4067                 return NT_STATUS_NO_MEMORY;
4068         }
4069
4070         switch (r->in.level) {
4071         case LSA_DOMAIN_INFO_POLICY_EFS:
4072                 talloc_free(info);
4073                 *r->out.info = NULL;
4074                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4075         case LSA_DOMAIN_INFO_POLICY_KERBEROS:
4076         {
4077                 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
4078                 struct smb_krb5_context *smb_krb5_context;
4079                 int ret = smb_krb5_init_context(mem_ctx,
4080                                                         dce_call->conn->dce_ctx->lp_ctx,
4081                                                         &smb_krb5_context);
4082                 if (ret != 0) {
4083                         talloc_free(info);
4084                         *r->out.info = NULL;
4085                         return NT_STATUS_INTERNAL_ERROR;
4086                 }
4087                 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
4088                                smb_krb5_context,
4089                                k);
4090                 talloc_free(smb_krb5_context);
4091                 *r->out.info = info;
4092                 return NT_STATUS_OK;
4093         }
4094         default:
4095                 talloc_free(info);
4096                 *r->out.info = NULL;
4097                 return NT_STATUS_INVALID_INFO_CLASS;
4098         }
4099 }
4100
4101 /*
4102   lsa_SetDomInfoPolicy
4103 */
4104 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4105                                               TALLOC_CTX *mem_ctx,
4106                                               struct lsa_SetDomainInformationPolicy *r)
4107 {
4108         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4109 }
4110
4111 /*
4112   lsa_TestCall
4113 */
4114 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
4115                              TALLOC_CTX *mem_ctx,
4116                              struct lsa_TestCall *r)
4117 {
4118         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4119 }
4120
4121 /*
4122   lsa_CREDRWRITE
4123 */
4124 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4125                        struct lsa_CREDRWRITE *r)
4126 {
4127         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4128 }
4129
4130
4131 /*
4132   lsa_CREDRREAD
4133 */
4134 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4135                        struct lsa_CREDRREAD *r)
4136 {
4137         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4138 }
4139
4140
4141 /*
4142   lsa_CREDRENUMERATE
4143 */
4144 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4145                        struct lsa_CREDRENUMERATE *r)
4146 {
4147         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4148 }
4149
4150
4151 /*
4152   lsa_CREDRWRITEDOMAINCREDENTIALS
4153 */
4154 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4155                        struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
4156 {
4157         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4158 }
4159
4160
4161 /*
4162   lsa_CREDRREADDOMAINCREDENTIALS
4163 */
4164 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4165                        struct lsa_CREDRREADDOMAINCREDENTIALS *r)
4166 {
4167         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4168 }
4169
4170
4171 /*
4172   lsa_CREDRDELETE
4173 */
4174 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4175                        struct lsa_CREDRDELETE *r)
4176 {
4177         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4178 }
4179
4180
4181 /*
4182   lsa_CREDRGETTARGETINFO
4183 */
4184 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4185                        struct lsa_CREDRGETTARGETINFO *r)
4186 {
4187         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4188 }
4189
4190
4191 /*
4192   lsa_CREDRPROFILELOADED
4193 */
4194 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4195                        struct lsa_CREDRPROFILELOADED *r)
4196 {
4197         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4198 }
4199
4200
4201 /*
4202   lsa_CREDRGETSESSIONTYPES
4203 */
4204 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4205                        struct lsa_CREDRGETSESSIONTYPES *r)
4206 {
4207         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4208 }
4209
4210
4211 /*
4212   lsa_LSARREGISTERAUDITEVENT
4213 */
4214 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4215                        struct lsa_LSARREGISTERAUDITEVENT *r)
4216 {
4217         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4218 }
4219
4220
4221 /*
4222   lsa_LSARGENAUDITEVENT
4223 */
4224 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4225                        struct lsa_LSARGENAUDITEVENT *r)
4226 {
4227         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4228 }
4229
4230
4231 /*
4232   lsa_LSARUNREGISTERAUDITEVENT
4233 */
4234 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4235                        struct lsa_LSARUNREGISTERAUDITEVENT *r)
4236 {
4237         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4238 }
4239
4240
4241 /*
4242   lsa_lsaRQueryForestTrustInformation
4243 */
4244 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4245                        struct lsa_lsaRQueryForestTrustInformation *r)
4246 {
4247         struct dcesrv_handle *h = NULL;
4248         struct lsa_policy_state *p_state = NULL;
4249         int forest_level = DS_DOMAIN_FUNCTION_2000;
4250         const char * const trust_attrs[] = {
4251                 "securityIdentifier",
4252                 "flatName",
4253                 "trustPartner",
4254                 "trustAttributes",
4255                 "trustDirection",
4256                 "trustType",
4257                 "msDS-TrustForestTrustInfo",
4258                 NULL
4259         };
4260         struct ldb_message *trust_tdo_msg = NULL;
4261         struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4262         struct ForestTrustInfo *trust_fti = NULL;
4263         struct lsa_ForestTrustInformation *trust_lfti = NULL;
4264         NTSTATUS status;
4265
4266         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4267
4268         p_state = h->data;
4269
4270         if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4271                 return NT_STATUS_INVALID_DOMAIN_STATE;
4272         }
4273
4274         forest_level = dsdb_forest_functional_level(p_state->sam_ldb);
4275         if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4276                 return NT_STATUS_INVALID_DOMAIN_STATE;
4277         }
4278
4279         if (r->in.trusted_domain_name->string == NULL) {
4280                 return NT_STATUS_NO_SUCH_DOMAIN;
4281         }
4282
4283         status = dsdb_trust_search_tdo(p_state->sam_ldb,
4284                                        r->in.trusted_domain_name->string,
4285                                        r->in.trusted_domain_name->string,
4286                                        trust_attrs, mem_ctx, &trust_tdo_msg);
4287         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4288                 return NT_STATUS_NO_SUCH_DOMAIN;
4289         }
4290         if (!NT_STATUS_IS_OK(status)) {
4291                 return status;
4292         }
4293
4294         status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4295         if (!NT_STATUS_IS_OK(status)) {
4296                 return status;
4297         }
4298
4299         if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4300                 return NT_STATUS_INVALID_PARAMETER;
4301         }
4302
4303         if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4304                 return NT_STATUS_INVALID_PARAMETER;
4305         }
4306
4307         status = dsdb_trust_parse_forest_info(mem_ctx,
4308                                               trust_tdo_msg,
4309                                               &trust_fti);
4310         if (!NT_STATUS_IS_OK(status)) {
4311                 return status;
4312         }
4313
4314         status = dsdb_trust_forest_info_to_lsa(mem_ctx, trust_fti,
4315                                                &trust_lfti);
4316         if (!NT_STATUS_IS_OK(status)) {
4317                 return status;
4318         }
4319
4320         *r->out.forest_trust_info = trust_lfti;
4321         return NT_STATUS_OK;
4322 }
4323
4324 /*
4325   lsa_lsaRSetForestTrustInformation
4326 */
4327 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4328                                                          TALLOC_CTX *mem_ctx,
4329                                                          struct lsa_lsaRSetForestTrustInformation *r)
4330 {
4331         struct dcesrv_handle *h;
4332         struct lsa_policy_state *p_state;
4333         const char * const trust_attrs[] = {
4334                 "securityIdentifier",
4335                 "flatName",
4336                 "trustPartner",
4337                 "trustAttributes",
4338                 "trustDirection",
4339                 "trustType",
4340                 "msDS-TrustForestTrustInfo",
4341                 NULL
4342         };
4343         struct ldb_message *trust_tdo_msg = NULL;
4344         struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4345         struct lsa_ForestTrustInformation *step1_lfti = NULL;
4346         struct lsa_ForestTrustInformation *step2_lfti = NULL;
4347         struct ForestTrustInfo *trust_fti = NULL;
4348         struct ldb_result *trusts_res = NULL;
4349         unsigned int i;
4350         struct lsa_TrustDomainInfoInfoEx *xref_tdo = NULL;
4351         struct lsa_ForestTrustInformation *xref_lfti = NULL;
4352         struct lsa_ForestTrustCollisionInfo *c_info = NULL;
4353         DATA_BLOB ft_blob = {};
4354         struct ldb_message *msg = NULL;
4355         NTSTATUS status;
4356         enum ndr_err_code ndr_err;
4357         int ret;
4358         bool in_transaction = false;
4359
4360         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4361
4362         p_state = h->data;
4363
4364         if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4365                 return NT_STATUS_INVALID_DOMAIN_STATE;
4366         }
4367
4368         if (r->in.check_only == 0) {
4369                 ret = ldb_transaction_start(p_state->sam_ldb);
4370                 if (ret != LDB_SUCCESS) {
4371                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
4372                 }
4373                 in_transaction = true;
4374         }
4375
4376         /*
4377          * abort if we are not a PDC
4378          *
4379          * In future we should use a function like IsEffectiveRoleOwner()
4380          */
4381         if (!samdb_is_pdc(p_state->sam_ldb)) {
4382                 status = NT_STATUS_INVALID_DOMAIN_ROLE;
4383                 goto done;
4384         }
4385
4386         if (r->in.trusted_domain_name->string == NULL) {
4387                 status = NT_STATUS_NO_SUCH_DOMAIN;
4388                 goto done;
4389         }
4390
4391         status = dsdb_trust_search_tdo(p_state->sam_ldb,
4392                                        r->in.trusted_domain_name->string,
4393                                        r->in.trusted_domain_name->string,
4394                                        trust_attrs, mem_ctx, &trust_tdo_msg);
4395         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4396                 status = NT_STATUS_NO_SUCH_DOMAIN;
4397                 goto done;
4398         }
4399         if (!NT_STATUS_IS_OK(status)) {
4400                 goto done;
4401         }
4402
4403         status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4404         if (!NT_STATUS_IS_OK(status)) {
4405                 goto done;
4406         }
4407
4408         if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4409                 status = NT_STATUS_INVALID_PARAMETER;
4410                 goto done;
4411         }
4412
4413         if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4414                 status = NT_STATUS_INVALID_PARAMETER;
4415                 goto done;
4416         }
4417
4418         /*
4419          * verify and normalize the given forest trust info.
4420          *
4421          * Step1: doesn't reorder yet, so step1_lfti might contain
4422          * NULL entries. This means dsdb_trust_verify_forest_info()
4423          * can generate collision entries with the callers index.
4424          */
4425         status = dsdb_trust_normalize_forest_info_step1(mem_ctx,
4426                                                         r->in.forest_trust_info,
4427                                                         &step1_lfti);
4428         if (!NT_STATUS_IS_OK(status)) {
4429                 goto done;
4430         }
4431
4432         c_info = talloc_zero(r->out.collision_info,
4433                              struct lsa_ForestTrustCollisionInfo);
4434         if (c_info == NULL) {
4435                 status = NT_STATUS_NO_MEMORY;
4436                 goto done;
4437         }
4438
4439         /*
4440          * First check our own forest, then other domains/forests
4441          */
4442
4443         status = dsdb_trust_xref_tdo_info(mem_ctx, p_state->sam_ldb,
4444                                           &xref_tdo);
4445         if (!NT_STATUS_IS_OK(status)) {
4446                 goto done;
4447         }
4448         status = dsdb_trust_xref_forest_info(mem_ctx, p_state->sam_ldb,
4449                                              &xref_lfti);
4450         if (!NT_STATUS_IS_OK(status)) {
4451                 goto done;
4452         }
4453
4454         /*
4455          * The documentation proposed to generate
4456          * LSA_FOREST_TRUST_COLLISION_XREF collisions.
4457          * But Windows always uses LSA_FOREST_TRUST_COLLISION_TDO.
4458          */
4459         status = dsdb_trust_verify_forest_info(xref_tdo, xref_lfti,
4460                                                LSA_FOREST_TRUST_COLLISION_TDO,
4461                                                c_info, step1_lfti);
4462         if (!NT_STATUS_IS_OK(status)) {
4463                 goto done;
4464         }
4465
4466         /* fetch all other trusted domain objects */
4467         status = dsdb_trust_search_tdos(p_state->sam_ldb,
4468                                         trust_tdo->domain_name.string,
4469                                         trust_attrs,
4470                                         mem_ctx, &trusts_res);
4471         if (!NT_STATUS_IS_OK(status)) {
4472                 goto done;
4473         }
4474
4475         /*
4476          * now check against the other domains.
4477          * and generate LSA_FOREST_TRUST_COLLISION_TDO collisions.
4478          */
4479         for (i = 0; i < trusts_res->count; i++) {
4480                 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
4481                 struct ForestTrustInfo *fti = NULL;
4482                 struct lsa_ForestTrustInformation *lfti = NULL;
4483
4484                 status = dsdb_trust_parse_tdo_info(mem_ctx,
4485                                                    trusts_res->msgs[i],
4486                                                    &tdo);
4487                 if (!NT_STATUS_IS_OK(status)) {
4488                         goto done;
4489                 }
4490
4491                 status = dsdb_trust_parse_forest_info(tdo,
4492                                                       trusts_res->msgs[i],
4493                                                       &fti);
4494                 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
4495                         continue;
4496                 }
4497                 if (!NT_STATUS_IS_OK(status)) {
4498                         goto done;
4499                 }
4500
4501                 status = dsdb_trust_forest_info_to_lsa(tdo, fti, &lfti);
4502                 if (!NT_STATUS_IS_OK(status)) {
4503                         goto done;
4504                 }
4505
4506                 status = dsdb_trust_verify_forest_info(tdo, lfti,
4507                                                 LSA_FOREST_TRUST_COLLISION_TDO,
4508                                                 c_info, step1_lfti);
4509                 if (!NT_STATUS_IS_OK(status)) {
4510                         goto done;
4511                 }
4512
4513                 TALLOC_FREE(tdo);
4514         }
4515
4516         if (r->in.check_only != 0) {
4517                 status = NT_STATUS_OK;
4518                 goto done;
4519         }
4520
4521         /*
4522          * not just a check, write info back
4523          */
4524
4525         /*
4526          * normalize the given forest trust info.
4527          *
4528          * Step2: adds TOP_LEVEL_NAME[_EX] in reverse order,
4529          * followed by DOMAIN_INFO in reverse order. It also removes
4530          * possible NULL entries from Step1.
4531          */
4532         status = dsdb_trust_normalize_forest_info_step2(mem_ctx, step1_lfti,
4533                                                         &step2_lfti);
4534         if (!NT_STATUS_IS_OK(status)) {
4535                 goto done;
4536         }
4537
4538         status = dsdb_trust_forest_info_from_lsa(mem_ctx, step2_lfti,
4539                                                  &trust_fti);
4540         if (!NT_STATUS_IS_OK(status)) {
4541                 goto done;
4542         }
4543
4544         ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, trust_fti,
4545                                        (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4546         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4547                 status = NT_STATUS_INVALID_PARAMETER;
4548                 goto done;
4549         }
4550
4551         msg = ldb_msg_new(mem_ctx);
4552         if (msg == NULL) {
4553                 status = NT_STATUS_NO_MEMORY;
4554                 goto done;
4555         }
4556
4557         msg->dn = ldb_dn_copy(mem_ctx, trust_tdo_msg->dn);
4558         if (!msg->dn) {
4559                 status = NT_STATUS_NO_MEMORY;
4560                 goto done;
4561         }
4562
4563         ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4564                                 LDB_FLAG_MOD_REPLACE, NULL);
4565         if (ret != LDB_SUCCESS) {
4566                 status = NT_STATUS_NO_MEMORY;
4567                 goto done;
4568         }
4569         ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4570                                 &ft_blob, NULL);
4571         if (ret != LDB_SUCCESS) {
4572                 status = NT_STATUS_NO_MEMORY;
4573                 goto done;
4574         }
4575
4576         ret = ldb_modify(p_state->sam_ldb, msg);
4577         if (ret != LDB_SUCCESS) {
4578                 status = dsdb_ldb_err_to_ntstatus(ret);
4579
4580                 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4581                           ldb_errstring(p_state->sam_ldb)));
4582
4583                 goto done;
4584         }
4585
4586         /* ok, all fine, commit transaction and return */
4587         in_transaction = false;
4588         ret = ldb_transaction_commit(p_state->sam_ldb);
4589         if (ret != LDB_SUCCESS) {
4590                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
4591                 goto done;
4592         }
4593
4594         status = NT_STATUS_OK;
4595
4596 done:
4597         if (NT_STATUS_IS_OK(status) && c_info->count != 0) {
4598                 *r->out.collision_info = c_info;
4599         }
4600
4601         if (in_transaction) {
4602                 ldb_transaction_cancel(p_state->sam_ldb);
4603         }
4604
4605         return status;
4606 }
4607
4608 /*
4609   lsa_CREDRRENAME
4610 */
4611 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4612                        struct lsa_CREDRRENAME *r)
4613 {
4614         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4615 }
4616
4617
4618
4619 /*
4620   lsa_LSAROPENPOLICYSCE
4621 */
4622 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4623                        struct lsa_LSAROPENPOLICYSCE *r)
4624 {
4625         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4626 }
4627
4628
4629 /*
4630   lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4631 */
4632 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4633                        struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4634 {
4635         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4636 }
4637
4638
4639 /*
4640   lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4641 */
4642 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4643                        struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4644 {
4645         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4646 }
4647
4648
4649 /*
4650   lsa_LSARADTREPORTSECURITYEVENT
4651 */
4652 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4653                        struct lsa_LSARADTREPORTSECURITYEVENT *r)
4654 {
4655         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4656 }
4657
4658
4659 /* include the generated boilerplate */
4660 #include "librpc/gen_ndr/ndr_lsa_s.c"
4661
4662
4663
4664 /*****************************************
4665 NOTE! The remaining calls below were
4666 removed in w2k3, so the DCESRV_FAULT()
4667 replies are the correct implementation. Do
4668 not try and fill these in with anything else
4669 ******************************************/
4670
4671 /*
4672   dssetup_DsRoleDnsNameToFlatName
4673 */
4674 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4675                                         struct dssetup_DsRoleDnsNameToFlatName *r)
4676 {
4677         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4678 }
4679
4680
4681 /*
4682   dssetup_DsRoleDcAsDc
4683 */
4684 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4685                              struct dssetup_DsRoleDcAsDc *r)
4686 {
4687         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4688 }
4689
4690
4691 /*
4692   dssetup_DsRoleDcAsReplica
4693 */
4694 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4695                                   struct dssetup_DsRoleDcAsReplica *r)
4696 {
4697         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4698 }
4699
4700
4701 /*
4702   dssetup_DsRoleDemoteDc
4703 */
4704 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4705                                struct dssetup_DsRoleDemoteDc *r)
4706 {
4707         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4708 }
4709
4710
4711 /*
4712   dssetup_DsRoleGetDcOperationProgress
4713 */
4714 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4715                                              struct dssetup_DsRoleGetDcOperationProgress *r)
4716 {
4717         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4718 }
4719
4720
4721 /* 
4722   dssetup_DsRoleGetDcOperationResults 
4723 */
4724 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4725                                             struct dssetup_DsRoleGetDcOperationResults *r)
4726 {
4727         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4728 }
4729
4730
4731 /* 
4732   dssetup_DsRoleCancel 
4733 */
4734 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4735                              struct dssetup_DsRoleCancel *r)
4736 {
4737         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4738 }
4739
4740
4741 /*
4742   dssetup_DsRoleServerSaveStateForUpgrade
4743 */
4744 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4745                                                 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4746 {
4747         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4748 }
4749
4750
4751 /*
4752   dssetup_DsRoleUpgradeDownlevelServer
4753 */
4754 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4755                                              struct dssetup_DsRoleUpgradeDownlevelServer *r)
4756 {
4757         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4758 }
4759
4760
4761 /*
4762   dssetup_DsRoleAbortDownlevelServerUpgrade
4763 */
4764 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4765                                                   struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4766 {
4767         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4768 }
4769
4770
4771 /* include the generated boilerplate */
4772 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4773
4774 NTSTATUS dcerpc_server_lsa_init(void)
4775 {
4776         NTSTATUS ret;
4777
4778         ret = dcerpc_server_dssetup_init();
4779         if (!NT_STATUS_IS_OK(ret)) {
4780                 return ret;
4781         }
4782         ret = dcerpc_server_lsarpc_init();
4783         if (!NT_STATUS_IS_OK(ret)) {
4784                 return ret;
4785         }
4786         return ret;
4787 }