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