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