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