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