Make the updated RPC-LSA pass against Win2008, and Samba4 to match
[kai/samba.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 "../lib/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   fill in the AccountDomain info
404 */
405 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
406                                        struct lsa_DomainInfo *info)
407 {
408         info->name.string = state->domain_name;
409         info->sid         = state->domain_sid;
410
411         return NT_STATUS_OK;
412 }
413
414 /*
415   fill in the DNS domain info
416 */
417 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
418                              struct lsa_DnsDomainInfo *info)
419 {
420         info->name.string = state->domain_name;
421         info->sid         = state->domain_sid;
422         info->dns_domain.string = state->domain_dns;
423         info->dns_forest.string = state->forest_dns;
424         info->domain_guid       = state->domain_guid;
425
426         return NT_STATUS_OK;
427 }
428
429 /* 
430   lsa_QueryInfoPolicy2
431 */
432 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
433                                      struct lsa_QueryInfoPolicy2 *r)
434 {
435         struct lsa_policy_state *state;
436         struct dcesrv_handle *h;
437
438         r->out.info = NULL;
439
440         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
441
442         state = h->data;
443
444         r->out.info = talloc(mem_ctx, union lsa_PolicyInformation);
445         if (!r->out.info) {
446                 return NT_STATUS_NO_MEMORY;
447         }
448
449         ZERO_STRUCTP(r->out.info);
450
451         switch (r->in.level) {
452         case LSA_POLICY_INFO_AUDIT_LOG:
453                 /* we don't need to fill in any of this */
454                 ZERO_STRUCT(r->out.info->audit_log);
455                 return NT_STATUS_OK;
456         case LSA_POLICY_INFO_AUDIT_EVENTS:
457                 /* we don't need to fill in any of this */
458                 ZERO_STRUCT(r->out.info->audit_events);
459                 return NT_STATUS_OK;
460         case LSA_POLICY_INFO_PD:
461                 /* we don't need to fill in any of this */
462                 ZERO_STRUCT(r->out.info->pd);
463                 return NT_STATUS_OK;
464
465         case LSA_POLICY_INFO_DOMAIN:
466                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &r->out.info->domain);
467         case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
468                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &r->out.info->account_domain);
469         case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
470                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &r->out.info->l_account_domain);
471
472
473         case LSA_POLICY_INFO_ROLE:
474                 r->out.info->role.role = LSA_ROLE_PRIMARY;
475                 return NT_STATUS_OK;
476
477         case LSA_POLICY_INFO_DNS:
478         case LSA_POLICY_INFO_DNS_INT:
479                 return dcesrv_lsa_info_DNS(state, mem_ctx, &r->out.info->dns);
480
481         case LSA_POLICY_INFO_REPLICA:
482                 ZERO_STRUCT(r->out.info->replica);
483                 return NT_STATUS_OK;
484
485         case LSA_POLICY_INFO_QUOTA:
486                 ZERO_STRUCT(r->out.info->quota);
487                 return NT_STATUS_OK;
488
489         case LSA_POLICY_INFO_MOD:
490         case LSA_POLICY_INFO_AUDIT_FULL_SET:
491         case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
492                 /* windows gives INVALID_PARAMETER */
493                 r->out.info = NULL;
494                 return NT_STATUS_INVALID_PARAMETER;
495         }
496
497         r->out.info = NULL;
498         return NT_STATUS_INVALID_INFO_CLASS;
499 }
500
501 /* 
502   lsa_QueryInfoPolicy 
503 */
504 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
505                                     struct lsa_QueryInfoPolicy *r)
506 {
507         struct lsa_QueryInfoPolicy2 r2;
508         NTSTATUS status;
509
510         ZERO_STRUCT(r2);
511
512         r2.in.handle = r->in.handle;
513         r2.in.level = r->in.level;
514         
515         status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
516
517         r->out.info = r2.out.info;
518
519         return status;
520 }
521
522 /* 
523   lsa_SetInfoPolicy 
524 */
525 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
526                                   struct lsa_SetInfoPolicy *r)
527 {
528         /* need to support this */
529         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
530 }
531
532
533 /* 
534   lsa_ClearAuditLog 
535 */
536 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
537                                   struct lsa_ClearAuditLog *r)
538 {
539         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
540 }
541
542
543 /* 
544   lsa_CreateAccount 
545
546   This call does not seem to have any long-term effects, hence no database operations
547
548   we need to talk to the MS product group to find out what this account database means!
549
550   answer is that the lsa database is totally separate from the SAM and
551   ldap databases. We are going to need a separate ldb to store these
552   accounts. The SIDs on this account bear no relation to the SIDs in
553   AD
554 */
555 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
556                                   struct lsa_CreateAccount *r)
557 {
558         struct lsa_account_state *astate;
559
560         struct lsa_policy_state *state;
561         struct dcesrv_handle *h, *ah;
562
563         ZERO_STRUCTP(r->out.acct_handle);
564
565         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
566
567         state = h->data;
568
569         astate = talloc(dce_call->conn, struct lsa_account_state);
570         if (astate == NULL) {
571                 return NT_STATUS_NO_MEMORY;
572         }
573
574         astate->account_sid = dom_sid_dup(astate, r->in.sid);
575         if (astate->account_sid == NULL) {
576                 talloc_free(astate);
577                 return NT_STATUS_NO_MEMORY;
578         }
579         
580         astate->policy = talloc_reference(astate, state);
581         astate->access_mask = r->in.access_mask;
582
583         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
584         if (!ah) {
585                 talloc_free(astate);
586                 return NT_STATUS_NO_MEMORY;
587         }
588
589         ah->data = talloc_steal(ah, astate);
590
591         *r->out.acct_handle = ah->wire_handle;
592
593         return NT_STATUS_OK;
594 }
595
596
597 /* 
598   lsa_EnumAccounts 
599 */
600 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
601                                  struct lsa_EnumAccounts *r)
602 {
603         struct dcesrv_handle *h;
604         struct lsa_policy_state *state;
605         int ret, i;
606         struct ldb_message **res;
607         const char * const attrs[] = { "objectSid", NULL};
608         uint32_t count;
609
610         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
611
612         state = h->data;
613
614         /* NOTE: This call must only return accounts that have at least
615            one privilege set 
616         */
617         ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, 
618                            "(&(objectSid=*)(privilege=*))");
619         if (ret < 0) {
620                 return NT_STATUS_NO_SUCH_USER;
621         }
622
623         if (*r->in.resume_handle >= ret) {
624                 return NT_STATUS_NO_MORE_ENTRIES;
625         }
626
627         count = ret - *r->in.resume_handle;
628         if (count > r->in.num_entries) {
629                 count = r->in.num_entries;
630         }
631
632         if (count == 0) {
633                 return NT_STATUS_NO_MORE_ENTRIES;
634         }
635
636         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
637         if (r->out.sids->sids == NULL) {
638                 return NT_STATUS_NO_MEMORY;
639         }
640
641         for (i=0;i<count;i++) {
642                 r->out.sids->sids[i].sid = 
643                         samdb_result_dom_sid(r->out.sids->sids, 
644                                              res[i + *r->in.resume_handle],
645                                              "objectSid");
646                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
647         }
648
649         r->out.sids->num_sids = count;
650         *r->out.resume_handle = count + *r->in.resume_handle;
651
652         return NT_STATUS_OK;
653         
654 }
655
656
657 /*
658   lsa_CreateTrustedDomainEx2
659 */
660 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
661                                                     TALLOC_CTX *mem_ctx,
662                                                     struct lsa_CreateTrustedDomainEx2 *r,
663                                                     int op)
664 {
665         struct dcesrv_handle *policy_handle;
666         struct lsa_policy_state *policy_state;
667         struct lsa_trusted_domain_state *trusted_domain_state;
668         struct dcesrv_handle *handle;
669         struct ldb_message **msgs, *msg, *msg_user;
670         const char *attrs[] = {
671                 NULL
672         };
673         const char *netbios_name;
674         const char *dns_name;
675         const char *name;
676         DATA_BLOB session_key = data_blob(NULL, 0);
677         DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
678         struct trustDomainPasswords auth_struct;
679         int ret;
680         NTSTATUS nt_status;
681         enum ndr_err_code ndr_err;
682         
683         DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
684         ZERO_STRUCTP(r->out.trustdom_handle);
685         
686         policy_state = policy_handle->data;
687
688         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
689         if (!NT_STATUS_IS_OK(nt_status)) {
690                 return nt_status;
691         }
692
693         netbios_name = r->in.info->netbios_name.string;
694         if (!netbios_name) {
695                 return NT_STATUS_INVALID_PARAMETER;
696         }
697         
698         dns_name = r->in.info->domain_name.string;
699         
700         trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
701         if (!trusted_domain_state) {
702                 return NT_STATUS_NO_MEMORY;
703         }
704         trusted_domain_state->policy = policy_state;
705
706         if (strcasecmp(netbios_name, "BUILTIN") == 0
707             || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0) 
708             || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
709                 return NT_STATUS_INVALID_PARAMETER;;
710         }
711
712         if (strcasecmp(netbios_name, policy_state->domain_name) == 0
713             || strcasecmp(netbios_name, policy_state->domain_dns) == 0
714             || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0) 
715             || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
716             || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
717                 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
718         }
719
720         /* While this is a REF pointer, some of the functions that wrap this don't provide this */
721         if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
722                 /* No secrets are created at this time, for this function */
723                 auth_struct.outgoing.count = 0;
724                 auth_struct.incoming.count = 0;
725         } else {
726                 auth_blob = data_blob_const(r->in.auth_info->auth_blob.data, r->in.auth_info->auth_blob.size);
727                 arcfour_crypt_blob(auth_blob.data, auth_blob.length, &session_key);
728                 ndr_err = ndr_pull_struct_blob(&auth_blob, mem_ctx, 
729                                                lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
730                                                &auth_struct,
731                                                (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
732                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
733                         return NT_STATUS_INVALID_PARAMETER;
734                 }                               
735
736                 if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
737                         if (auth_struct.incoming.count > 1) {
738                                 return NT_STATUS_INVALID_PARAMETER;
739                         }
740                 }
741         }
742
743         if (auth_struct.incoming.count) {
744                 int i;
745                 struct trustAuthInOutBlob incoming;
746                 
747                 incoming.count = auth_struct.incoming.count;
748                 incoming.current = talloc(mem_ctx, struct AuthenticationInformationArray);
749                 if (!incoming.current) {
750                         return NT_STATUS_NO_MEMORY;
751                 }
752                 
753                 incoming.current->array = *auth_struct.incoming.current;
754                 if (!incoming.current->array) {
755                         return NT_STATUS_NO_MEMORY;
756                 }
757
758                 incoming.previous = talloc(mem_ctx, struct AuthenticationInformationArray);
759                 if (!incoming.previous) {
760                         return NT_STATUS_NO_MEMORY;
761                 }
762                 incoming.previous->array = talloc_array(mem_ctx, struct AuthenticationInformation, incoming.count);
763                 if (!incoming.previous->array) {
764                         return NT_STATUS_NO_MEMORY;
765                 }
766
767                 for (i = 0; i < incoming.count; i++) {
768                         incoming.previous->array[i].LastUpdateTime = 0;
769                         incoming.previous->array[i].AuthType = 0;
770                 }
771                 ndr_err = ndr_push_struct_blob(&trustAuthIncoming, mem_ctx, 
772                                                lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
773                                                &incoming,
774                                                (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
775                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
776                         return NT_STATUS_INVALID_PARAMETER;
777                 }
778         } else {
779                 trustAuthIncoming = data_blob(NULL, 0);
780         }
781         
782         if (auth_struct.outgoing.count) {
783                 int i;
784                 struct trustAuthInOutBlob outgoing;
785                 
786                 outgoing.count = auth_struct.outgoing.count;
787                 outgoing.current = talloc(mem_ctx, struct AuthenticationInformationArray);
788                 if (!outgoing.current) {
789                         return NT_STATUS_NO_MEMORY;
790                 }
791                 
792                 outgoing.current->array = *auth_struct.outgoing.current;
793                 if (!outgoing.current->array) {
794                         return NT_STATUS_NO_MEMORY;
795                 }
796
797                 outgoing.previous = talloc(mem_ctx, struct AuthenticationInformationArray);
798                 if (!outgoing.previous) {
799                         return NT_STATUS_NO_MEMORY;
800                 }
801                 outgoing.previous->array = talloc_array(mem_ctx, struct AuthenticationInformation, outgoing.count);
802                 if (!outgoing.previous->array) {
803                         return NT_STATUS_NO_MEMORY;
804                 }
805
806                 for (i = 0; i < outgoing.count; i++) {
807                         outgoing.previous->array[i].LastUpdateTime = 0;
808                         outgoing.previous->array[i].AuthType = 0;
809                 }
810                 ndr_err = ndr_push_struct_blob(&trustAuthOutgoing, mem_ctx, 
811                                                lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
812                                                &outgoing,
813                                                (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
814                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
815                         return NT_STATUS_INVALID_PARAMETER;
816                 }
817         } else {
818                 trustAuthOutgoing = data_blob(NULL, 0);
819         }
820
821         ret = ldb_transaction_start(policy_state->sam_ldb);
822         if (ret != LDB_SUCCESS) {
823                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
824         }
825
826         if (dns_name) {
827                 char *dns_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
828                 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
829                 /* search for the trusted_domain record */
830                 ret = gendb_search(policy_state->sam_ldb,
831                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
832                                    "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))", 
833                                    dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
834                 if (ret > 0) {
835                         ldb_transaction_cancel(policy_state->sam_ldb);
836                         return NT_STATUS_OBJECT_NAME_COLLISION;
837                 }
838         } else {
839                 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
840                 /* search for the trusted_domain record */
841                 ret = gendb_search(policy_state->sam_ldb,
842                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
843                                    "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))", 
844                                    netbios_encoded, netbios_encoded, netbios_encoded);
845                 if (ret > 0) {
846                         ldb_transaction_cancel(policy_state->sam_ldb);
847                         return NT_STATUS_OBJECT_NAME_COLLISION;
848                 }
849         }
850         
851         if (ret < 0 ) {
852                 ldb_transaction_cancel(policy_state->sam_ldb);
853                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
854         }
855         
856         name = dns_name ? dns_name : netbios_name;
857
858         msg = ldb_msg_new(mem_ctx);
859         if (msg == NULL) {
860                 return NT_STATUS_NO_MEMORY;
861         }
862
863         msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
864         if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
865                         ldb_transaction_cancel(policy_state->sam_ldb);
866                 return NT_STATUS_NO_MEMORY;
867         }
868         
869         samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "flatname", netbios_name);
870
871         if (r->in.info->sid) {
872                 const char *sid_string = dom_sid_string(mem_ctx, r->in.info->sid);
873                 if (!sid_string) {
874                         ldb_transaction_cancel(policy_state->sam_ldb);
875                         return NT_STATUS_NO_MEMORY;
876                 }
877                         
878                 samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "securityIdentifier", sid_string);
879         }
880
881         samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "objectClass", "trustedDomain");
882
883         samdb_msg_add_int(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
884
885         samdb_msg_add_int(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
886
887         samdb_msg_add_int(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
888         
889         if (dns_name) {
890                 samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustPartner", dns_name);
891         }
892
893         if (trustAuthIncoming.data) {
894                 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
895                 if (ret != LDB_SUCCESS) {
896                         ldb_transaction_cancel(policy_state->sam_ldb);
897                         return NT_STATUS_NO_MEMORY;
898                 }
899         }
900         if (trustAuthOutgoing.data) {
901                 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
902                 if (ret != LDB_SUCCESS) {
903                         ldb_transaction_cancel(policy_state->sam_ldb);
904                         return NT_STATUS_NO_MEMORY;
905                 }
906         }
907
908         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
909
910         /* create the trusted_domain */
911         ret = ldb_add(trusted_domain_state->policy->sam_ldb, msg);
912         switch (ret) {
913         case  LDB_SUCCESS:
914                 break;
915         case  LDB_ERR_ENTRY_ALREADY_EXISTS:
916                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
917                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
918                          ldb_dn_get_linearized(msg->dn),
919                          ldb_errstring(trusted_domain_state->policy->sam_ldb)));
920                 return NT_STATUS_DOMAIN_EXISTS;
921         case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
922                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
923                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
924                          ldb_dn_get_linearized(msg->dn),
925                          ldb_errstring(trusted_domain_state->policy->sam_ldb)));
926                 return NT_STATUS_ACCESS_DENIED;
927         default:
928                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
929                 DEBUG(0,("Failed to create user record %s: %s\n",
930                          ldb_dn_get_linearized(msg->dn),
931                          ldb_errstring(trusted_domain_state->policy->sam_ldb)));
932                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
933         }
934
935         if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
936                 msg_user = ldb_msg_new(mem_ctx);
937                 if (msg == NULL) {
938                         ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
939                         return NT_STATUS_NO_MEMORY;
940                 }
941
942                 /* Inbound trusts must also create a cn=users object to match */
943
944                 trusted_domain_state->trusted_domain_user_dn = msg_user->dn
945                         = ldb_dn_copy(trusted_domain_state, policy_state->domain_dn);
946                 if ( ! ldb_dn_add_child_fmt(msg_user->dn, "cn=users")) {
947                         ldb_transaction_cancel(policy_state->sam_ldb);
948                         return NT_STATUS_NO_MEMORY;
949                 }
950         
951                 if ( ! ldb_dn_add_child_fmt(msg_user->dn, "cn=%s", netbios_name)) {
952                         ldb_transaction_cancel(policy_state->sam_ldb);
953                         return NT_STATUS_NO_MEMORY;
954                 }
955
956                 ldb_msg_add_string(msg_user, "objectClass", "user");
957
958                 ldb_msg_add_steal_string(msg_user, "samAccountName", 
959                                          talloc_asprintf(mem_ctx, "%s$", netbios_name));
960
961                 if (samdb_msg_add_uint(trusted_domain_state->policy->sam_ldb, mem_ctx, msg_user, 
962                                        "userAccountControl", 
963                                        UF_INTERDOMAIN_TRUST_ACCOUNT) != 0) { 
964                         ldb_transaction_cancel(policy_state->sam_ldb);
965                         return NT_STATUS_NO_MEMORY; 
966                 }
967
968                 if (auth_struct.incoming.count) {
969                         int i;
970                         for (i=0; i < auth_struct.incoming.count; i++ ) {
971                                 if (auth_struct.incoming.current[i]->AuthType == TRUST_AUTH_TYPE_NT4OWF) {
972                                         samdb_msg_add_hash(trusted_domain_state->policy->sam_ldb, 
973                                                            mem_ctx, msg_user, "unicodePwd", 
974                                                            &auth_struct.incoming.current[i]->AuthInfo.nt4owf.password);
975                                 } else if (auth_struct.incoming.current[i]->AuthType == TRUST_AUTH_TYPE_CLEAR) {
976                                         DATA_BLOB new_password = data_blob_const(auth_struct.incoming.current[i]->AuthInfo.clear.password,
977                                                                                  auth_struct.incoming.current[i]->AuthInfo.clear.size);
978                                         ret = ldb_msg_add_value(msg_user, "clearTextPassword", &new_password, NULL);
979                                         if (ret != LDB_SUCCESS) {
980                                                 ldb_transaction_cancel(policy_state->sam_ldb);
981                                                 return NT_STATUS_NO_MEMORY;
982                                         }
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         int i;
2059         NTSTATUS status;
2060         struct lsa_EnumPrivsAccount enumPrivs;
2061
2062         enumPrivs.in.handle = r->in.handle;
2063
2064         status = dcesrv_lsa_EnumPrivsAccount(dce_call, mem_ctx, &enumPrivs);
2065         if (!NT_STATUS_IS_OK(status)) {
2066                 return status;
2067         }       
2068
2069         *(r->out.access_mask) = 0x00000000;
2070
2071         for (i = 0; i < enumPrivs.out.privs->count; i++) {
2072                 int priv = enumPrivs.out.privs->set[i].luid.low;
2073
2074                 switch (priv) {
2075                 case SEC_PRIV_INTERACTIVE_LOGON:
2076                         *(r->out.access_mask) |= LSA_POLICY_MODE_INTERACTIVE;
2077                         break;
2078                 case SEC_PRIV_NETWORK_LOGON:
2079                         *(r->out.access_mask) |= LSA_POLICY_MODE_NETWORK;
2080                         break;
2081                 case SEC_PRIV_REMOTE_INTERACTIVE_LOGON:
2082                         *(r->out.access_mask) |= LSA_POLICY_MODE_REMOTE_INTERACTIVE;
2083                         break;
2084                 }
2085         }
2086
2087         return NT_STATUS_OK;
2088 }
2089
2090
2091 /* 
2092   lsa_SetSystemAccessAccount
2093 */
2094 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2095                        struct lsa_SetSystemAccessAccount *r)
2096 {
2097         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2098 }
2099
2100
2101 /* 
2102   lsa_CreateSecret 
2103 */
2104 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2105                                  struct lsa_CreateSecret *r)
2106 {
2107         struct dcesrv_handle *policy_handle;
2108         struct lsa_policy_state *policy_state;
2109         struct lsa_secret_state *secret_state;
2110         struct dcesrv_handle *handle;
2111         struct ldb_message **msgs, *msg;
2112         const char *errstr;
2113         const char *attrs[] = {
2114                 NULL
2115         };
2116
2117         const char *name;
2118
2119         int ret;
2120
2121         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2122         ZERO_STRUCTP(r->out.sec_handle);
2123         
2124         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
2125         {
2126         case SECURITY_SYSTEM:
2127         case SECURITY_ADMINISTRATOR:
2128                 break;
2129         default:
2130                 /* Users and annonymous are not allowed create secrets */
2131                 return NT_STATUS_ACCESS_DENIED;
2132         }
2133
2134         policy_state = policy_handle->data;
2135
2136         if (!r->in.name.string) {
2137                 return NT_STATUS_INVALID_PARAMETER;
2138         }
2139         
2140         secret_state = talloc(mem_ctx, struct lsa_secret_state);
2141         if (!secret_state) {
2142                 return NT_STATUS_NO_MEMORY;
2143         }
2144         secret_state->policy = policy_state;
2145
2146         msg = ldb_msg_new(mem_ctx);
2147         if (msg == NULL) {
2148                 return NT_STATUS_NO_MEMORY;
2149         }
2150
2151         if (strncmp("G$", r->in.name.string, 2) == 0) {
2152                 const char *name2;
2153                 name = &r->in.name.string[2];
2154                         /* 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) */
2155                 secret_state->sam_ldb = talloc_reference(secret_state, 
2156                                                          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))); 
2157                 secret_state->global = true;
2158
2159                 if (strlen(name) < 1) {
2160                         return NT_STATUS_INVALID_PARAMETER;
2161                 }
2162
2163                 name2 = talloc_asprintf(mem_ctx, "%s Secret", ldb_binary_encode_string(mem_ctx, name));
2164                 /* search for the secret record */
2165                 ret = gendb_search(secret_state->sam_ldb,
2166                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
2167                                    "(&(cn=%s)(objectclass=secret))", 
2168                                    name2);
2169                 if (ret > 0) {
2170                         return NT_STATUS_OBJECT_NAME_COLLISION;
2171                 }
2172                 
2173                 if (ret == -1) {
2174                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
2175                                  name2, ldb_errstring(secret_state->sam_ldb)));
2176                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2177                 }
2178
2179                 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2180                 if (!name2 || ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2181                         return NT_STATUS_NO_MEMORY;
2182                 }
2183                 
2184                 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name2);
2185         
2186         } else {
2187                 secret_state->global = false;
2188
2189                 name = r->in.name.string;
2190                 if (strlen(name) < 1) {
2191                         return NT_STATUS_INVALID_PARAMETER;
2192                 }
2193
2194                 secret_state->sam_ldb = talloc_reference(secret_state, 
2195                                                          secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
2196                 /* search for the secret record */
2197                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2198                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2199                                    &msgs, attrs,
2200                                    "(&(cn=%s)(objectclass=secret))", 
2201                                    ldb_binary_encode_string(mem_ctx, name));
2202                 if (ret > 0) {
2203                         return NT_STATUS_OBJECT_NAME_COLLISION;
2204                 }
2205                 
2206                 if (ret == -1) {
2207                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
2208                                  name, ldb_errstring(secret_state->sam_ldb)));
2209                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2210                 }
2211
2212                 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb, "cn=%s,cn=LSA Secrets", name);
2213                 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name);
2214         } 
2215
2216         /* pull in all the template attributes.  Note this is always from the global samdb */
2217         ret = samdb_copy_template(secret_state->policy->sam_ldb, msg, 
2218                                   "secret", &errstr);
2219         if (ret != 0) {
2220                 DEBUG(0,("Failed to load TemplateSecret from samdb: %s\n",
2221                          errstr));
2222                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2223         }
2224
2225         samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "objectClass", "secret");
2226         
2227         secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
2228
2229         /* create the secret */
2230         ret = ldb_add(secret_state->sam_ldb, msg);
2231         if (ret != 0) {
2232                 DEBUG(0,("Failed to create secret record %s: %s\n",
2233                          ldb_dn_get_linearized(msg->dn), 
2234                          ldb_errstring(secret_state->sam_ldb)));
2235                 return NT_STATUS_ACCESS_DENIED;
2236         }
2237
2238         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2239         if (!handle) {
2240                 return NT_STATUS_NO_MEMORY;
2241         }
2242         
2243         handle->data = talloc_steal(handle, secret_state);
2244         
2245         secret_state->access_mask = r->in.access_mask;
2246         secret_state->policy = talloc_reference(secret_state, policy_state);
2247         
2248         *r->out.sec_handle = handle->wire_handle;
2249         
2250         return NT_STATUS_OK;
2251 }
2252
2253
2254 /* 
2255   lsa_OpenSecret 
2256 */
2257 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2258                                struct lsa_OpenSecret *r)
2259 {
2260         struct dcesrv_handle *policy_handle;
2261         
2262         struct lsa_policy_state *policy_state;
2263         struct lsa_secret_state *secret_state;
2264         struct dcesrv_handle *handle;
2265         struct ldb_message **msgs;
2266         const char *attrs[] = {
2267                 NULL
2268         };
2269
2270         const char *name;
2271
2272         int ret;
2273
2274         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2275         ZERO_STRUCTP(r->out.sec_handle);
2276         policy_state = policy_handle->data;
2277
2278         if (!r->in.name.string) {
2279                 return NT_STATUS_INVALID_PARAMETER;
2280         }
2281         
2282         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
2283         {
2284         case SECURITY_SYSTEM:
2285         case SECURITY_ADMINISTRATOR:
2286                 break;
2287         default:
2288                 /* Users and annonymous are not allowed to access secrets */
2289                 return NT_STATUS_ACCESS_DENIED;
2290         }
2291
2292         secret_state = talloc(mem_ctx, struct lsa_secret_state);
2293         if (!secret_state) {
2294                 return NT_STATUS_NO_MEMORY;
2295         }
2296         secret_state->policy = policy_state;
2297
2298         if (strncmp("G$", r->in.name.string, 2) == 0) {
2299                 name = &r->in.name.string[2];
2300                 /* 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) */
2301                 secret_state->sam_ldb = talloc_reference(secret_state, 
2302                                                          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))); 
2303                 secret_state->global = true;
2304
2305                 if (strlen(name) < 1) {
2306                         return NT_STATUS_INVALID_PARAMETER;
2307                 }
2308
2309                 /* search for the secret record */
2310                 ret = gendb_search(secret_state->sam_ldb,
2311                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
2312                                    "(&(cn=%s Secret)(objectclass=secret))", 
2313                                    ldb_binary_encode_string(mem_ctx, name));
2314                 if (ret == 0) {
2315                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2316                 }
2317                 
2318                 if (ret != 1) {
2319                         DEBUG(0,("Found %d records matching DN %s\n", ret,
2320                                  ldb_dn_get_linearized(policy_state->system_dn)));
2321                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2322                 }
2323         
2324         } else {
2325                 secret_state->global = false;
2326                 secret_state->sam_ldb = talloc_reference(secret_state, 
2327                                  secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
2328
2329                 name = r->in.name.string;
2330                 if (strlen(name) < 1) {
2331                         return NT_STATUS_INVALID_PARAMETER;
2332                 }
2333
2334                 /* search for the secret record */
2335                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2336                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2337                                    &msgs, attrs,
2338                                    "(&(cn=%s)(objectclass=secret))", 
2339                                    ldb_binary_encode_string(mem_ctx, name));
2340                 if (ret == 0) {
2341                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2342                 }
2343                 
2344                 if (ret != 1) {
2345                         DEBUG(0,("Found %d records matching CN=%s\n", 
2346                                  ret, ldb_binary_encode_string(mem_ctx, name)));
2347                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2348                 }
2349         } 
2350
2351         secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
2352         
2353         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2354         if (!handle) {
2355                 return NT_STATUS_NO_MEMORY;
2356         }
2357         
2358         handle->data = talloc_steal(handle, secret_state);
2359         
2360         secret_state->access_mask = r->in.access_mask;
2361         secret_state->policy = talloc_reference(secret_state, policy_state);
2362         
2363         *r->out.sec_handle = handle->wire_handle;
2364         
2365         return NT_STATUS_OK;
2366 }
2367
2368
2369 /* 
2370   lsa_SetSecret 
2371 */
2372 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2373                               struct lsa_SetSecret *r)
2374 {
2375
2376         struct dcesrv_handle *h;
2377         struct lsa_secret_state *secret_state;
2378         struct ldb_message *msg;
2379         DATA_BLOB session_key;
2380         DATA_BLOB crypt_secret, secret;
2381         struct ldb_val val;
2382         int ret;
2383         NTSTATUS status = NT_STATUS_OK;
2384
2385         struct timeval now = timeval_current();
2386         NTTIME nt_now = timeval_to_nttime(&now);
2387
2388         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
2389
2390         secret_state = h->data;
2391
2392         msg = ldb_msg_new(mem_ctx);
2393         if (msg == NULL) {
2394                 return NT_STATUS_NO_MEMORY;
2395         }
2396
2397         msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
2398         if (!msg->dn) {
2399                 return NT_STATUS_NO_MEMORY;
2400         }
2401         status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
2402         if (!NT_STATUS_IS_OK(status)) {
2403                 return status;
2404         }
2405
2406         if (r->in.old_val) {
2407                 /* Decrypt */
2408                 crypt_secret.data = r->in.old_val->data;
2409                 crypt_secret.length = r->in.old_val->size;
2410                 
2411                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
2412                 if (!NT_STATUS_IS_OK(status)) {
2413                         return status;
2414                 }
2415                 
2416                 val.data = secret.data;
2417                 val.length = secret.length;
2418                 
2419                 /* set value */
2420                 if (samdb_msg_add_value(secret_state->sam_ldb, 
2421                                         mem_ctx, msg, "priorValue", &val) != 0) {
2422                         return NT_STATUS_NO_MEMORY; 
2423                 }
2424                 
2425                 /* set old value mtime */
2426                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2427                                          mem_ctx, msg, "priorSetTime", nt_now) != 0) { 
2428                         return NT_STATUS_NO_MEMORY; 
2429                 }
2430
2431         } else {
2432                 /* If the old value is not set, then migrate the
2433                  * current value to the old value */
2434                 const struct ldb_val *old_val;
2435                 NTTIME last_set_time;
2436                 struct ldb_message **res;
2437                 const char *attrs[] = {
2438                         "currentValue",
2439                         "lastSetTime",
2440                         NULL
2441                 };
2442                 
2443                 /* search for the secret record */
2444                 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
2445                                       secret_state->secret_dn, &res, attrs);
2446                 if (ret == 0) {
2447                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2448                 }
2449                 
2450                 if (ret != 1) {
2451                         DEBUG(0,("Found %d records matching dn=%s\n", ret,
2452                                  ldb_dn_get_linearized(secret_state->secret_dn)));
2453                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2454                 }
2455                 
2456                 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
2457                 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
2458                 
2459                 if (old_val) {
2460                         /* set old value */
2461                         if (samdb_msg_add_value(secret_state->sam_ldb, 
2462                                                 mem_ctx, msg, "priorValue", 
2463                                                 old_val) != 0) {
2464                                 return NT_STATUS_NO_MEMORY; 
2465                         }
2466                 } else {
2467                         if (samdb_msg_add_delete(secret_state->sam_ldb, 
2468                                                  mem_ctx, msg, "priorValue")) {
2469                                 return NT_STATUS_NO_MEMORY;
2470                         }
2471                         
2472                 }
2473                 
2474                 /* set old value mtime */
2475                 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
2476                         if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2477                                                  mem_ctx, msg, "priorSetTime", last_set_time) != 0) { 
2478                                 return NT_STATUS_NO_MEMORY; 
2479                         }
2480                 } else {
2481                         if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2482                                                  mem_ctx, msg, "priorSetTime", nt_now) != 0) { 
2483                                 return NT_STATUS_NO_MEMORY; 
2484                         }
2485                 }
2486         }
2487
2488         if (r->in.new_val) {
2489                 /* Decrypt */
2490                 crypt_secret.data = r->in.new_val->data;
2491                 crypt_secret.length = r->in.new_val->size;
2492                 
2493                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
2494                 if (!NT_STATUS_IS_OK(status)) {
2495                         return status;
2496                 }
2497                 
2498                 val.data = secret.data;
2499                 val.length = secret.length;
2500                 
2501                 /* set value */
2502                 if (samdb_msg_add_value(secret_state->sam_ldb, 
2503                                         mem_ctx, msg, "currentValue", &val) != 0) {
2504                         return NT_STATUS_NO_MEMORY; 
2505                 }
2506                 
2507                 /* set new value mtime */
2508                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2509                                          mem_ctx, msg, "lastSetTime", nt_now) != 0) { 
2510                         return NT_STATUS_NO_MEMORY; 
2511                 }
2512                 
2513         } else {
2514                 /* NULL out the NEW value */
2515                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2516                                          mem_ctx, msg, "lastSetTime", nt_now) != 0) { 
2517                         return NT_STATUS_NO_MEMORY; 
2518                 }
2519                 if (samdb_msg_add_delete(secret_state->sam_ldb, 
2520                                          mem_ctx, msg, "currentValue")) {
2521                         return NT_STATUS_NO_MEMORY;
2522                 }
2523         }
2524
2525         /* modify the samdb record */
2526         ret = samdb_replace(secret_state->sam_ldb, mem_ctx, msg);
2527         if (ret != 0) {
2528                 /* we really need samdb.c to return NTSTATUS */
2529                 return NT_STATUS_UNSUCCESSFUL;
2530         }
2531
2532         return NT_STATUS_OK;
2533 }
2534
2535
2536 /* 
2537   lsa_QuerySecret 
2538 */
2539 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2540                                 struct lsa_QuerySecret *r)
2541 {
2542         struct dcesrv_handle *h;
2543         struct lsa_secret_state *secret_state;
2544         struct ldb_message *msg;
2545         DATA_BLOB session_key;
2546         DATA_BLOB crypt_secret, secret;
2547         int ret;
2548         struct ldb_message **res;
2549         const char *attrs[] = {
2550                 "currentValue",
2551                 "priorValue",
2552                 "lastSetTime",
2553                 "priorSetTime", 
2554                 NULL
2555         };
2556
2557         NTSTATUS nt_status;
2558
2559         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
2560
2561         /* Ensure user is permitted to read this... */
2562         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
2563         {
2564         case SECURITY_SYSTEM:
2565         case SECURITY_ADMINISTRATOR:
2566                 break;
2567         default:
2568                 /* Users and annonymous are not allowed to read secrets */
2569                 return NT_STATUS_ACCESS_DENIED;
2570         }
2571
2572         secret_state = h->data;
2573
2574         /* pull all the user attributes */
2575         ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
2576                               secret_state->secret_dn, &res, attrs);
2577         if (ret != 1) {
2578                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2579         }
2580         msg = res[0];
2581         
2582         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
2583         if (!NT_STATUS_IS_OK(nt_status)) {
2584                 return nt_status;
2585         }
2586         
2587         if (r->in.old_val) {
2588                 const struct ldb_val *prior_val;
2589                 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
2590                 if (!r->out.old_val) {
2591                         return NT_STATUS_NO_MEMORY;
2592                 }
2593                 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
2594                 
2595                 if (prior_val && prior_val->length) {
2596                         secret.data = prior_val->data;
2597                         secret.length = prior_val->length;
2598                 
2599                         /* Encrypt */
2600                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
2601                         if (!crypt_secret.length) {
2602                                 return NT_STATUS_NO_MEMORY;
2603                         }
2604                         r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
2605                         if (!r->out.old_val->buf) {
2606                                 return NT_STATUS_NO_MEMORY;
2607                         }
2608                         r->out.old_val->buf->size = crypt_secret.length;
2609                         r->out.old_val->buf->length = crypt_secret.length;
2610                         r->out.old_val->buf->data = crypt_secret.data;
2611                 }
2612         }
2613         
2614         if (r->in.old_mtime) {
2615                 r->out.old_mtime = talloc(mem_ctx, NTTIME);
2616                 if (!r->out.old_mtime) {
2617                         return NT_STATUS_NO_MEMORY;
2618                 }
2619                 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
2620         }
2621         
2622         if (r->in.new_val) {
2623                 const struct ldb_val *new_val;
2624                 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
2625                 if (!r->out.new_val) {
2626                         return NT_STATUS_NO_MEMORY;
2627                 }
2628
2629                 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
2630                 
2631                 if (new_val && new_val->length) {
2632                         secret.data = new_val->data;
2633                         secret.length = new_val->length;
2634                 
2635                         /* Encrypt */
2636                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
2637                         if (!crypt_secret.length) {
2638                                 return NT_STATUS_NO_MEMORY;
2639                         }
2640                         r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
2641                         if (!r->out.new_val->buf) {
2642                                 return NT_STATUS_NO_MEMORY;
2643                         }
2644                         r->out.new_val->buf->length = crypt_secret.length;
2645                         r->out.new_val->buf->size = crypt_secret.length;
2646                         r->out.new_val->buf->data = crypt_secret.data;
2647                 }
2648         }
2649         
2650         if (r->in.new_mtime) {
2651                 r->out.new_mtime = talloc(mem_ctx, NTTIME);
2652                 if (!r->out.new_mtime) {
2653                         return NT_STATUS_NO_MEMORY;
2654                 }
2655                 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
2656         }
2657         
2658         return NT_STATUS_OK;
2659 }
2660
2661
2662 /* 
2663   lsa_LookupPrivValue
2664 */
2665 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call, 
2666                                     TALLOC_CTX *mem_ctx,
2667                                     struct lsa_LookupPrivValue *r)
2668 {
2669         struct dcesrv_handle *h;
2670         struct lsa_policy_state *state;
2671         int id;
2672
2673         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2674
2675         state = h->data;
2676
2677         id = sec_privilege_id(r->in.name->string);
2678         if (id == -1) {
2679                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2680         }
2681
2682         r->out.luid->low = id;
2683         r->out.luid->high = 0;
2684
2685         return NT_STATUS_OK;    
2686 }
2687
2688
2689 /* 
2690   lsa_LookupPrivName 
2691 */
2692 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call, 
2693                                    TALLOC_CTX *mem_ctx,
2694                                    struct lsa_LookupPrivName *r)
2695 {
2696         struct dcesrv_handle *h;
2697         struct lsa_policy_state *state;
2698         const char *privname;
2699
2700         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2701
2702         state = h->data;
2703
2704         if (r->in.luid->high != 0) {
2705                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2706         }
2707
2708         privname = sec_privilege_name(r->in.luid->low);
2709         if (privname == NULL) {
2710                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2711         }
2712
2713         r->out.name = talloc(mem_ctx, struct lsa_StringLarge);
2714         if (r->out.name == NULL) {
2715                 return NT_STATUS_NO_MEMORY;
2716         }
2717         r->out.name->string = privname;
2718
2719         return NT_STATUS_OK;    
2720 }
2721
2722
2723 /* 
2724   lsa_LookupPrivDisplayName
2725 */
2726 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call, 
2727                                           TALLOC_CTX *mem_ctx,
2728                                           struct lsa_LookupPrivDisplayName *r)
2729 {
2730         struct dcesrv_handle *h;
2731         struct lsa_policy_state *state;
2732         int id;
2733
2734         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2735
2736         state = h->data;
2737
2738         id = sec_privilege_id(r->in.name->string);
2739         if (id == -1) {
2740                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2741         }
2742         
2743         r->out.disp_name = talloc(mem_ctx, struct lsa_StringLarge);
2744         if (r->out.disp_name == NULL) {
2745                 return NT_STATUS_NO_MEMORY;
2746         }
2747
2748         r->out.disp_name->string = sec_privilege_display_name(id, r->in.language_id);
2749         if (r->out.disp_name->string == NULL) {
2750                 return NT_STATUS_INTERNAL_ERROR;
2751         }
2752
2753         return NT_STATUS_OK;
2754 }
2755
2756
2757 /* 
2758   lsa_EnumAccountsWithUserRight
2759 */
2760 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call, 
2761                                               TALLOC_CTX *mem_ctx,
2762                                               struct lsa_EnumAccountsWithUserRight *r)
2763 {
2764         struct dcesrv_handle *h;
2765         struct lsa_policy_state *state;
2766         int ret, i;
2767         struct ldb_message **res;
2768         const char * const attrs[] = { "objectSid", NULL};
2769         const char *privname;
2770
2771         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2772
2773         state = h->data;
2774
2775         if (r->in.name == NULL) {
2776                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2777         } 
2778
2779         privname = r->in.name->string;
2780         if (sec_privilege_id(privname) == -1) {
2781                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2782         }
2783
2784         ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, 
2785                            "privilege=%s", privname);
2786         if (ret == -1) {
2787                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2788         }
2789         if (ret == 0) {
2790                 return NT_STATUS_NO_MORE_ENTRIES;
2791         }
2792
2793         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
2794         if (r->out.sids->sids == NULL) {
2795                 return NT_STATUS_NO_MEMORY;
2796         }
2797         for (i=0;i<ret;i++) {
2798                 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
2799                                                                 res[i], "objectSid");
2800                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
2801         }
2802         r->out.sids->num_sids = ret;
2803
2804         return NT_STATUS_OK;
2805 }
2806
2807
2808 /* 
2809   lsa_AddAccountRights
2810 */
2811 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call, 
2812                                      TALLOC_CTX *mem_ctx,
2813                                      struct lsa_AddAccountRights *r)
2814 {
2815         struct dcesrv_handle *h;
2816         struct lsa_policy_state *state;
2817
2818         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2819
2820         state = h->data;
2821
2822         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
2823                                           LDB_FLAG_MOD_ADD,
2824                                           r->in.sid, r->in.rights);
2825 }
2826
2827
2828 /* 
2829   lsa_RemoveAccountRights
2830 */
2831 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call, 
2832                                         TALLOC_CTX *mem_ctx,
2833                                         struct lsa_RemoveAccountRights *r)
2834 {
2835         struct dcesrv_handle *h;
2836         struct lsa_policy_state *state;
2837
2838         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2839
2840         state = h->data;
2841
2842         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
2843                                           LDB_FLAG_MOD_DELETE,
2844                                           r->in.sid, r->in.rights);
2845 }
2846
2847
2848 /* 
2849   lsa_StorePrivateData
2850 */
2851 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2852                        struct lsa_StorePrivateData *r)
2853 {
2854         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2855 }
2856
2857
2858 /* 
2859   lsa_RetrievePrivateData
2860 */
2861 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2862                        struct lsa_RetrievePrivateData *r)
2863 {
2864         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2865 }
2866
2867
2868 /* 
2869   lsa_GetUserName
2870 */
2871 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2872                                 struct lsa_GetUserName *r)
2873 {
2874         NTSTATUS status = NT_STATUS_OK;
2875         const char *account_name;
2876         const char *authority_name;
2877         struct lsa_String *_account_name;
2878         struct lsa_StringPointer *_authority_name = NULL;
2879
2880         /* this is what w2k3 does */
2881         r->out.account_name = r->in.account_name;
2882         r->out.authority_name = r->in.authority_name;
2883
2884         if (r->in.account_name && r->in.account_name->string) {
2885                 return NT_STATUS_INVALID_PARAMETER;
2886         }
2887
2888         if (r->in.authority_name &&
2889             r->in.authority_name->string &&
2890             r->in.authority_name->string->string) {
2891                 return NT_STATUS_INVALID_PARAMETER;
2892         }
2893
2894         account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->account_name);
2895         authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->domain_name);
2896
2897         _account_name = talloc(mem_ctx, struct lsa_String);
2898         NT_STATUS_HAVE_NO_MEMORY(_account_name);
2899         _account_name->string = account_name;
2900
2901         if (r->in.authority_name) {
2902                 _authority_name = talloc(mem_ctx, struct lsa_StringPointer);
2903                 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
2904                 _authority_name->string = talloc(mem_ctx, struct lsa_String);
2905                 NT_STATUS_HAVE_NO_MEMORY(_authority_name->string);
2906                 _authority_name->string->string = authority_name;
2907         }
2908
2909         r->out.account_name = _account_name;
2910         r->out.authority_name = _authority_name;
2911
2912         return status;
2913 }
2914
2915 /*
2916   lsa_SetInfoPolicy2
2917 */
2918 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
2919                                    TALLOC_CTX *mem_ctx,
2920                                    struct lsa_SetInfoPolicy2 *r)
2921 {
2922         /* need to support these */
2923         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2924 }
2925
2926 /*
2927   lsa_QueryDomainInformationPolicy
2928 */
2929 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
2930                                                  TALLOC_CTX *mem_ctx,
2931                                                  struct lsa_QueryDomainInformationPolicy *r)
2932 {
2933         r->out.info = talloc(mem_ctx, union lsa_DomainInformationPolicy);
2934         if (!r->out.info) {
2935                 return NT_STATUS_NO_MEMORY;
2936         }
2937
2938         switch (r->in.level) {
2939         case LSA_DOMAIN_INFO_POLICY_EFS:
2940                 talloc_free(r->out.info);
2941                 r->out.info = NULL;
2942                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2943         case LSA_DOMAIN_INFO_POLICY_KERBEROS:
2944         {
2945                 struct lsa_DomainInfoKerberos *k = &r->out.info->kerberos_info;
2946                 struct smb_krb5_context *smb_krb5_context;
2947                 int ret = smb_krb5_init_context(mem_ctx, 
2948                                                         dce_call->event_ctx, 
2949                                                         dce_call->conn->dce_ctx->lp_ctx,
2950                                                         &smb_krb5_context);
2951                 if (ret != 0) {
2952                         talloc_free(r->out.info);
2953                         r->out.info = NULL;
2954                         return NT_STATUS_INTERNAL_ERROR;
2955                 }
2956                 k->enforce_restrictions = 0; /* FIXME, details missing from MS-LSAD 2.2.53 */
2957                 k->service_tkt_lifetime = 0; /* Need to find somewhere to store this, and query in KDC too */
2958                 k->user_tkt_lifetime = 0;    /* Need to find somewhere to store this, and query in KDC too */
2959                 k->user_tkt_renewaltime = 0; /* Need to find somewhere to store this, and query in KDC too */
2960                 k->clock_skew = krb5_get_max_time_skew(smb_krb5_context->krb5_context);
2961                 talloc_free(smb_krb5_context);
2962                 return NT_STATUS_OK;
2963         }
2964         default:
2965                 talloc_free(r->out.info);
2966                 r->out.info = NULL;
2967                 return NT_STATUS_INVALID_INFO_CLASS;
2968         }
2969 }
2970
2971 /*
2972   lsa_SetDomInfoPolicy
2973 */
2974 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
2975                                               TALLOC_CTX *mem_ctx,
2976                                               struct lsa_SetDomainInformationPolicy *r)
2977 {
2978         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2979 }
2980
2981 /*
2982   lsa_TestCall
2983 */
2984 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
2985                              TALLOC_CTX *mem_ctx,
2986                              struct lsa_TestCall *r)
2987 {
2988         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2989 }
2990
2991 /* 
2992   lsa_CREDRWRITE 
2993 */
2994 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2995                        struct lsa_CREDRWRITE *r)
2996 {
2997         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2998 }
2999
3000
3001 /* 
3002   lsa_CREDRREAD 
3003 */
3004 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3005                        struct lsa_CREDRREAD *r)
3006 {
3007         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3008 }
3009
3010
3011 /* 
3012   lsa_CREDRENUMERATE 
3013 */
3014 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3015                        struct lsa_CREDRENUMERATE *r)
3016 {
3017         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3018 }
3019
3020
3021 /* 
3022   lsa_CREDRWRITEDOMAINCREDENTIALS 
3023 */
3024 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3025                        struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3026 {
3027         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3028 }
3029
3030
3031 /* 
3032   lsa_CREDRREADDOMAINCREDENTIALS 
3033 */
3034 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3035                        struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3036 {
3037         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3038 }
3039
3040
3041 /* 
3042   lsa_CREDRDELETE 
3043 */
3044 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3045                        struct lsa_CREDRDELETE *r)
3046 {
3047         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3048 }
3049
3050
3051 /* 
3052   lsa_CREDRGETTARGETINFO 
3053 */
3054 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3055                        struct lsa_CREDRGETTARGETINFO *r)
3056 {
3057         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3058 }
3059
3060
3061 /* 
3062   lsa_CREDRPROFILELOADED 
3063 */
3064 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3065                        struct lsa_CREDRPROFILELOADED *r)
3066 {
3067         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3068 }
3069
3070
3071 /* 
3072   lsa_CREDRGETSESSIONTYPES 
3073 */
3074 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3075                        struct lsa_CREDRGETSESSIONTYPES *r)
3076 {
3077         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3078 }
3079
3080
3081 /* 
3082   lsa_LSARREGISTERAUDITEVENT 
3083 */
3084 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3085                        struct lsa_LSARREGISTERAUDITEVENT *r)
3086 {
3087         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3088 }
3089
3090
3091 /* 
3092   lsa_LSARGENAUDITEVENT 
3093 */
3094 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3095                        struct lsa_LSARGENAUDITEVENT *r)
3096 {
3097         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3098 }
3099
3100
3101 /* 
3102   lsa_LSARUNREGISTERAUDITEVENT 
3103 */
3104 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3105                        struct lsa_LSARUNREGISTERAUDITEVENT *r)
3106 {
3107         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3108 }
3109
3110
3111 /* 
3112   lsa_lsaRQueryForestTrustInformation 
3113 */
3114 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3115                        struct lsa_lsaRQueryForestTrustInformation *r)
3116 {
3117         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3118 }
3119
3120
3121 /* 
3122   lsa_LSARSETFORESTTRUSTINFORMATION 
3123 */
3124 static NTSTATUS dcesrv_lsa_LSARSETFORESTTRUSTINFORMATION(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3125                        struct lsa_LSARSETFORESTTRUSTINFORMATION *r)