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