s4:rpc_server/netlogon: Fix for NetApp
[gd/samba-autobuild/.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    endpoint server for the netlogon pipe
5
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
7    Copyright (C) Stefan Metzmacher <metze@samba.org>  2005
8    Copyright (C) Matthias Dieter Wallnöfer            2009-2010
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "rpc_server/dcerpc_server.h"
26 #include "auth/auth.h"
27 #include "auth/auth_sam_reply.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "../lib/util/util_ldb.h"
30 #include "../lib/util/memcache.h"
31 #include "../libcli/auth/schannel.h"
32 #include "libcli/security/security.h"
33 #include "param/param.h"
34 #include "lib/messaging/irpc.h"
35 #include "librpc/gen_ndr/ndr_irpc_c.h"
36 #include "../libcli/ldap/ldap_ndr.h"
37 #include "dsdb/samdb/ldb_modules/util.h"
38 #include "lib/tsocket/tsocket.h"
39 #include "librpc/gen_ndr/ndr_netlogon.h"
40 #include "librpc/gen_ndr/ndr_lsa.h"
41 #include "librpc/gen_ndr/ndr_samr.h"
42 #include "librpc/gen_ndr/ndr_irpc.h"
43 #include "librpc/gen_ndr/ndr_winbind.h"
44 #include "librpc/gen_ndr/ndr_winbind_c.h"
45 #include "lib/socket/netif.h"
46
47 static struct memcache *global_challenge_table;
48
49 struct netlogon_server_pipe_state {
50         struct netr_Credential client_challenge;
51         struct netr_Credential server_challenge;
52 };
53
54 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
55                                         struct netr_ServerReqChallenge *r)
56 {
57         struct netlogon_server_pipe_state *pipe_state =
58                 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
59         DATA_BLOB key, val;
60
61         ZERO_STRUCTP(r->out.return_credentials);
62
63         if (global_challenge_table == NULL) {
64                 /*
65                  * We maintain a global challenge table
66                  * with a fixed size (8k)
67                  *
68                  * This is required for the strange clients
69                  * which use different connections for
70                  * netr_ServerReqChallenge() and netr_ServerAuthenticate3()
71                  *
72                  */
73                 global_challenge_table = memcache_init(talloc_autofree_context(),
74                                                        8192);
75                 if (global_challenge_table == NULL) {
76                         return NT_STATUS_NO_MEMORY;
77                 }
78         }
79
80         /* destroyed on pipe shutdown */
81
82         if (pipe_state) {
83                 talloc_free(pipe_state);
84                 dce_call->context->private_data = NULL;
85         }
86
87         pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
88         NT_STATUS_HAVE_NO_MEMORY(pipe_state);
89
90         pipe_state->client_challenge = *r->in.credentials;
91
92         generate_random_buffer(pipe_state->server_challenge.data,
93                                sizeof(pipe_state->server_challenge.data));
94
95         *r->out.return_credentials = pipe_state->server_challenge;
96
97         dce_call->context->private_data = pipe_state;
98
99         key = data_blob_string_const(r->in.computer_name);
100         val = data_blob_const(pipe_state, sizeof(*pipe_state));
101
102         memcache_add(global_challenge_table, SINGLETON_CACHE, key, val);
103
104         return NT_STATUS_OK;
105 }
106
107 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
108                                          struct netr_ServerAuthenticate3 *r)
109 {
110         struct netlogon_server_pipe_state *pipe_state =
111                 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
112         DATA_BLOB challenge_key;
113         bool challenge_valid = false;
114         struct netlogon_server_pipe_state challenge;
115         struct netlogon_creds_CredentialState *creds;
116         struct ldb_context *sam_ctx;
117         struct samr_Password *curNtHash = NULL;
118         struct samr_Password *prevNtHash = NULL;
119         uint32_t user_account_control;
120         int num_records;
121         struct ldb_message **msgs;
122         NTSTATUS nt_status;
123         const char *attrs[] = {"unicodePwd", "userAccountControl",
124                                "objectSid", NULL};
125         const char *account_name;
126         uint32_t server_flags = 0;
127         uint32_t negotiate_flags = 0;
128         bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(dce_call->conn->dce_ctx->lp_ctx);
129         bool reject_des_client = !allow_nt4_crypto;
130         bool reject_md5_client = lpcfg_reject_md5_clients(dce_call->conn->dce_ctx->lp_ctx);
131
132         ZERO_STRUCTP(r->out.return_credentials);
133         *r->out.rid = 0;
134
135         challenge_key = data_blob_string_const(r->in.computer_name);
136         if (pipe_state != NULL) {
137                 dce_call->context->private_data = NULL;
138
139                 /*
140                  * If we had a challenge remembered on the connection
141                  * consider this for usage. This can't be cleanup
142                  * by other clients.
143                  *
144                  * This is the default code path for typical clients
145                  * which call netr_ServerReqChallenge() and
146                  * netr_ServerAuthenticate3() on the same dcerpc connection.
147                  */
148                 challenge = *pipe_state;
149                 TALLOC_FREE(pipe_state);
150                 challenge_valid = true;
151         } else {
152                 DATA_BLOB val;
153                 bool ok;
154
155                 /*
156                  * Fallback and try to get the challenge from
157                  * the global cache.
158                  *
159                  * If too many clients are using this code path,
160                  * they may destroy their cache entries as the
161                  * global_challenge_table memcache has a fixed size.
162                  *
163                  * Note: this handles global_challenge_table == NULL fine
164                  */
165                 ok = memcache_lookup(global_challenge_table, SINGLETON_CACHE,
166                                      challenge_key, &val);
167                 if (ok && val.length == sizeof(challenge)) {
168                         memcpy(&challenge, val.data, sizeof(challenge));
169                         challenge_valid = true;
170                 } else {
171                         ZERO_STRUCT(challenge);
172                 }
173         }
174
175         server_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
176                        NETLOGON_NEG_PERSISTENT_SAMREPL |
177                        NETLOGON_NEG_ARCFOUR |
178                        NETLOGON_NEG_PROMOTION_COUNT |
179                        NETLOGON_NEG_CHANGELOG_BDC |
180                        NETLOGON_NEG_FULL_SYNC_REPL |
181                        NETLOGON_NEG_MULTIPLE_SIDS |
182                        NETLOGON_NEG_REDO |
183                        NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
184                        NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
185                        NETLOGON_NEG_GENERIC_PASSTHROUGH |
186                        NETLOGON_NEG_CONCURRENT_RPC |
187                        NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
188                        NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
189                        NETLOGON_NEG_STRONG_KEYS |
190                        NETLOGON_NEG_TRANSITIVE_TRUSTS |
191                        NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
192                        NETLOGON_NEG_PASSWORD_SET2 |
193                        NETLOGON_NEG_GETDOMAININFO |
194                        NETLOGON_NEG_CROSS_FOREST_TRUSTS |
195                        NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
196                        NETLOGON_NEG_RODC_PASSTHROUGH |
197                        NETLOGON_NEG_SUPPORTS_AES |
198                        NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
199                        NETLOGON_NEG_AUTHENTICATED_RPC;
200
201         negotiate_flags = *r->in.negotiate_flags & server_flags;
202
203         if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
204                 reject_des_client = false;
205         }
206
207         if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
208                 reject_des_client = false;
209                 reject_md5_client = false;
210         }
211
212         if (reject_des_client || reject_md5_client) {
213                 /*
214                  * Here we match Windows 2012 and return no flags.
215                  */
216                 *r->out.negotiate_flags = 0;
217                 return NT_STATUS_DOWNGRADE_DETECTED;
218         }
219
220         /*
221          * At this point we can cleanup the cache entry,
222          * if we fail the client needs to call netr_ServerReqChallenge
223          * again.
224          *
225          * Note: this handles global_challenge_table == NULL
226          * and also a non existing record just fine.
227          */
228         memcache_delete(global_challenge_table,
229                         SINGLETON_CACHE, challenge_key);
230
231         /*
232          * According to Microsoft (see bugid #6099)
233          * Windows 7 looks at the negotiate_flags
234          * returned in this structure *even if the
235          * call fails with access denied!
236          */
237         *r->out.negotiate_flags = negotiate_flags;
238
239         switch (r->in.secure_channel_type) {
240         case SEC_CHAN_WKSTA:
241         case SEC_CHAN_DNS_DOMAIN:
242         case SEC_CHAN_DOMAIN:
243         case SEC_CHAN_BDC:
244         case SEC_CHAN_RODC:
245                 break;
246         case SEC_CHAN_NULL:
247                 return NT_STATUS_INVALID_PARAMETER;
248         default:
249                 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
250                           r->in.secure_channel_type));
251                 return NT_STATUS_INVALID_PARAMETER;
252         }
253
254         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
255                                 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
256         if (sam_ctx == NULL) {
257                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
258         }
259
260         if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
261             r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN)
262         {
263                 struct ldb_message *tdo_msg = NULL;
264                 const char * const tdo_attrs[] = {
265                         "trustAuthIncoming",
266                         "trustAttributes",
267                         "flatName",
268                         NULL
269                 };
270                 char *encoded_name = NULL;
271                 size_t len;
272                 const char *flatname = NULL;
273                 char trailer = '$';
274                 bool require_trailer = true;
275                 const char *netbios = NULL;
276                 const char *dns = NULL;
277
278                 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
279                         trailer = '.';
280                         require_trailer = false;
281                 }
282
283                 encoded_name = ldb_binary_encode_string(mem_ctx,
284                                                         r->in.account_name);
285                 if (encoded_name == NULL) {
286                         return NT_STATUS_NO_MEMORY;
287                 }
288
289                 len = strlen(encoded_name);
290                 if (len < 2) {
291                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
292                 }
293
294                 if (require_trailer && encoded_name[len - 1] != trailer) {
295                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
296                 }
297                 encoded_name[len - 1] = '\0';
298
299                 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
300                         dns = encoded_name;
301                 } else {
302                         netbios = encoded_name;
303                 }
304
305                 nt_status = dsdb_trust_search_tdo(sam_ctx,
306                                                   netbios, dns,
307                                                   tdo_attrs, mem_ctx, &tdo_msg);
308                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
309                         DEBUG(2, ("Client asked for a trusted domain secure channel, "
310                                   "but there's no tdo for [%s] => [%s] \n",
311                                   r->in.account_name, encoded_name));
312                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
313                 }
314                 if (!NT_STATUS_IS_OK(nt_status)) {
315                         return nt_status;
316                 }
317
318                 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
319                                                               &curNtHash,
320                                                               &prevNtHash);
321                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) {
322                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
323                 }
324                 if (!NT_STATUS_IS_OK(nt_status)) {
325                         return nt_status;
326                 }
327
328                 flatname = ldb_msg_find_attr_as_string(tdo_msg, "flatName", NULL);
329                 if (flatname == NULL) {
330                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
331                 }
332
333                 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
334                 if (account_name == NULL) {
335                         return NT_STATUS_NO_MEMORY;
336                 }
337         } else {
338                 account_name = r->in.account_name;
339         }
340
341         /* pull the user attributes */
342         num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
343                                    "(&(sAMAccountName=%s)(objectclass=user))",
344                                    ldb_binary_encode_string(mem_ctx, account_name));
345
346         if (num_records == 0) {
347                 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
348                          r->in.account_name));
349                 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
350         }
351
352         if (num_records > 1) {
353                 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
354                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
355         }
356
357         user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
358
359         if (user_account_control & UF_ACCOUNTDISABLE) {
360                 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
361                 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
362         }
363
364         if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
365                 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
366                         DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
367                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
368                 }
369         } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
370                    r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
371                 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
372                         DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
373
374                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
375                 }
376         } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
377                 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
378                         DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
379                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
380                 }
381         } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
382                 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
383                         DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
384                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
385                 }
386         } else {
387                 /* we should never reach this */
388                 return NT_STATUS_INTERNAL_ERROR;
389         }
390
391         if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
392                 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
393                                         dce_call->conn->dce_ctx->lp_ctx,
394                                         msgs[0], NULL, &curNtHash);
395                 if (!NT_STATUS_IS_OK(nt_status)) {
396                         return NT_STATUS_ACCESS_DENIED;
397                 }
398         }
399
400         if (curNtHash == NULL) {
401                 return NT_STATUS_ACCESS_DENIED;
402         }
403
404         if (!challenge_valid) {
405                 DEBUG(1, ("No challenge requested by client [%s/%s], "
406                           "cannot authenticate\n",
407                           r->in.computer_name,
408                           r->in.account_name));
409                 return NT_STATUS_ACCESS_DENIED;
410         }
411
412         creds = netlogon_creds_server_init(mem_ctx,
413                                            r->in.account_name,
414                                            r->in.computer_name,
415                                            r->in.secure_channel_type,
416                                            &challenge.client_challenge,
417                                            &challenge.server_challenge,
418                                            curNtHash,
419                                            r->in.credentials,
420                                            r->out.return_credentials,
421                                            negotiate_flags);
422         if (creds == NULL && prevNtHash != NULL) {
423                 /*
424                  * We fallback to the previous password for domain trusts.
425                  *
426                  * Note that lpcfg_old_password_allowed_period() doesn't
427                  * apply here.
428                  */
429                 creds = netlogon_creds_server_init(mem_ctx,
430                                                    r->in.account_name,
431                                                    r->in.computer_name,
432                                                    r->in.secure_channel_type,
433                                                    &challenge.client_challenge,
434                                                    &challenge.server_challenge,
435                                                    prevNtHash,
436                                                    r->in.credentials,
437                                                    r->out.return_credentials,
438                                                    negotiate_flags);
439         }
440         if (creds == NULL) {
441                 return NT_STATUS_ACCESS_DENIED;
442         }
443
444         creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
445
446         nt_status = schannel_save_creds_state(mem_ctx,
447                                               dce_call->conn->dce_ctx->lp_ctx,
448                                               creds);
449         if (!NT_STATUS_IS_OK(nt_status)) {
450                 ZERO_STRUCTP(r->out.return_credentials);
451                 return nt_status;
452         }
453
454         *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
455                                                 "objectSid", 0);
456
457         return NT_STATUS_OK;
458 }
459
460 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
461                                         struct netr_ServerAuthenticate *r)
462 {
463         struct netr_ServerAuthenticate3 a;
464         uint32_t rid;
465         /* TODO:
466          * negotiate_flags is used as an [in] parameter
467          * so it need to be initialised.
468          *
469          * (I think ... = 0; seems wrong here --metze)
470          */
471         uint32_t negotiate_flags_in = 0;
472         uint32_t negotiate_flags_out = 0;
473
474         a.in.server_name                = r->in.server_name;
475         a.in.account_name               = r->in.account_name;
476         a.in.secure_channel_type        = r->in.secure_channel_type;
477         a.in.computer_name              = r->in.computer_name;
478         a.in.credentials                = r->in.credentials;
479         a.in.negotiate_flags            = &negotiate_flags_in;
480
481         a.out.return_credentials        = r->out.return_credentials;
482         a.out.rid                       = &rid;
483         a.out.negotiate_flags           = &negotiate_flags_out;
484
485         return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
486 }
487
488 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
489                                          struct netr_ServerAuthenticate2 *r)
490 {
491         struct netr_ServerAuthenticate3 r3;
492         uint32_t rid = 0;
493
494         r3.in.server_name = r->in.server_name;
495         r3.in.account_name = r->in.account_name;
496         r3.in.secure_channel_type = r->in.secure_channel_type;
497         r3.in.computer_name = r->in.computer_name;
498         r3.in.credentials = r->in.credentials;
499         r3.out.return_credentials = r->out.return_credentials;
500         r3.in.negotiate_flags = r->in.negotiate_flags;
501         r3.out.negotiate_flags = r->out.negotiate_flags;
502         r3.out.rid = &rid;
503
504         return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
505 }
506
507 /*
508  * NOTE: The following functions are nearly identical to the ones available in
509  * source3/rpc_server/srv_nelog_nt.c
510  * The reason we keep 2 copies is that they use different structures to
511  * represent the auth_info and the decrpc pipes.
512  */
513
514 /*
515  * If schannel is required for this call test that it actually is available.
516  */
517 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
518                                         const char *computer_name,
519                                         bool integrity, bool privacy)
520 {
521
522         if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
523                 if (!privacy && !integrity) {
524                         return NT_STATUS_OK;
525                 }
526
527                 if ((!privacy && integrity) &&
528                     auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
529                         return NT_STATUS_OK;
530                 }
531
532                 if ((privacy || integrity) &&
533                     auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
534                         return NT_STATUS_OK;
535                 }
536         }
537
538         /* test didn't pass */
539         DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
540                   computer_name));
541
542         return NT_STATUS_ACCESS_DENIED;
543 }
544
545 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
546                                                     TALLOC_CTX *mem_ctx,
547                                                     const char *computer_name,
548                                                     struct netr_Authenticator *received_authenticator,
549                                                     struct netr_Authenticator *return_authenticator,
550                                                     struct netlogon_creds_CredentialState **creds_out)
551 {
552         NTSTATUS nt_status;
553         struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
554         bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
555
556         if (schannel_global_required) {
557                 nt_status = schannel_check_required(auth_info,
558                                                     computer_name,
559                                                     true, false);
560                 if (!NT_STATUS_IS_OK(nt_status)) {
561                         return nt_status;
562                 }
563         }
564
565         nt_status = schannel_check_creds_state(mem_ctx,
566                                                dce_call->conn->dce_ctx->lp_ctx,
567                                                computer_name,
568                                                received_authenticator,
569                                                return_authenticator,
570                                                creds_out);
571         return nt_status;
572 }
573
574 /*
575   Change the machine account password for the currently connected
576   client.  Supplies only the NT#.
577 */
578
579 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
580                                        struct netr_ServerPasswordSet *r)
581 {
582         struct netlogon_creds_CredentialState *creds;
583         struct ldb_context *sam_ctx;
584         const char * const attrs[] = { "unicodePwd", NULL };
585         struct ldb_message **res;
586         struct samr_Password *oldNtHash;
587         NTSTATUS nt_status;
588         int ret;
589
590         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
591                                                         mem_ctx,
592                                                         r->in.computer_name,
593                                                         r->in.credential, r->out.return_authenticator,
594                                                         &creds);
595         NT_STATUS_NOT_OK_RETURN(nt_status);
596
597         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
598         if (sam_ctx == NULL) {
599                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
600         }
601
602         netlogon_creds_des_decrypt(creds, r->in.new_password);
603
604         /* fetch the old password hashes (the NT hash has to exist) */
605
606         ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
607                            "(&(objectClass=user)(objectSid=%s))",
608                            ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
609         if (ret != 1) {
610                 return NT_STATUS_WRONG_PASSWORD;
611         }
612
613         nt_status = samdb_result_passwords_no_lockout(mem_ctx,
614                                                       dce_call->conn->dce_ctx->lp_ctx,
615                                                       res[0], NULL, &oldNtHash);
616         if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
617                 return NT_STATUS_WRONG_PASSWORD;
618         }
619
620         /* Using the sid for the account as the key, set the password */
621         nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
622                                            creds->sid,
623                                            NULL, /* Don't have version */
624                                            NULL, /* Don't have plaintext */
625                                            NULL, r->in.new_password,
626                                            NULL, oldNtHash, /* Password change */
627                                            NULL, NULL);
628         return nt_status;
629 }
630
631 /*
632   Change the machine account password for the currently connected
633   client.  Supplies new plaintext.
634 */
635 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
636                                        struct netr_ServerPasswordSet2 *r)
637 {
638         struct netlogon_creds_CredentialState *creds;
639         struct ldb_context *sam_ctx;
640         const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
641         struct ldb_message **res;
642         struct samr_Password *oldLmHash, *oldNtHash;
643         struct NL_PASSWORD_VERSION version = {};
644         const uint32_t *new_version = NULL;
645         NTSTATUS nt_status;
646         DATA_BLOB new_password;
647         int ret;
648         struct samr_CryptPassword password_buf;
649
650         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
651                                                         mem_ctx,
652                                                         r->in.computer_name,
653                                                         r->in.credential, r->out.return_authenticator,
654                                                         &creds);
655         NT_STATUS_NOT_OK_RETURN(nt_status);
656
657         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
658         if (sam_ctx == NULL) {
659                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
660         }
661
662         memcpy(password_buf.data, r->in.new_password->data, 512);
663         SIVAL(password_buf.data, 512, r->in.new_password->length);
664
665         if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
666                 netlogon_creds_aes_decrypt(creds, password_buf.data, 516);
667         } else {
668                 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
669         }
670
671         switch (creds->secure_channel_type) {
672         case SEC_CHAN_DOMAIN:
673         case SEC_CHAN_DNS_DOMAIN: {
674                 uint32_t len = IVAL(password_buf.data, 512);
675                 if (len <= 500) {
676                         uint32_t ofs = 500 - len;
677                         uint8_t *p;
678
679                         p = password_buf.data + ofs;
680
681                         version.ReservedField = IVAL(p, 0);
682                         version.PasswordVersionNumber = IVAL(p, 4);
683                         version.PasswordVersionPresent = IVAL(p, 8);
684
685                         if (version.PasswordVersionPresent == NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT) {
686                                 new_version = &version.PasswordVersionNumber;
687                         }
688                 }}
689                 break;
690         default:
691                 break;
692         }
693
694         if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
695                 DEBUG(3,("samr: failed to decode password buffer\n"));
696                 return NT_STATUS_WRONG_PASSWORD;
697         }
698
699         /* fetch the old password hashes (at least one of both has to exist) */
700
701         ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
702                            "(&(objectClass=user)(objectSid=%s))",
703                            ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
704         if (ret != 1) {
705                 return NT_STATUS_WRONG_PASSWORD;
706         }
707
708         nt_status = samdb_result_passwords_no_lockout(mem_ctx,
709                                                       dce_call->conn->dce_ctx->lp_ctx,
710                                                       res[0], &oldLmHash, &oldNtHash);
711         if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
712                 return NT_STATUS_WRONG_PASSWORD;
713         }
714
715         /* Using the sid for the account as the key, set the password */
716         nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
717                                            creds->sid,
718                                            new_version,
719                                            &new_password, /* we have plaintext */
720                                            NULL, NULL,
721                                            oldLmHash, oldNtHash, /* Password change */
722                                            NULL, NULL);
723         return nt_status;
724 }
725
726
727 /*
728   netr_LogonUasLogon
729 */
730 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
731                                  struct netr_LogonUasLogon *r)
732 {
733         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
734 }
735
736
737 /*
738   netr_LogonUasLogoff
739 */
740 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
741                        struct netr_LogonUasLogoff *r)
742 {
743         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
744 }
745
746
747 static NTSTATUS dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx *r)
748 {
749         switch (r->in.logon_level) {
750         case NetlogonInteractiveInformation:
751         case NetlogonServiceInformation:
752         case NetlogonInteractiveTransitiveInformation:
753         case NetlogonServiceTransitiveInformation:
754                 if (r->in.logon->password == NULL) {
755                         return NT_STATUS_INVALID_PARAMETER;
756                 }
757
758                 switch (r->in.validation_level) {
759                 case NetlogonValidationSamInfo:  /* 2 */
760                 case NetlogonValidationSamInfo2: /* 3 */
761                 case NetlogonValidationSamInfo4: /* 6 */
762                         break;
763                 default:
764                         return NT_STATUS_INVALID_INFO_CLASS;
765                 }
766
767                 break;
768         case NetlogonNetworkInformation:
769         case NetlogonNetworkTransitiveInformation:
770                 if (r->in.logon->network == NULL) {
771                         return NT_STATUS_INVALID_PARAMETER;
772                 }
773
774                 switch (r->in.validation_level) {
775                 case NetlogonValidationSamInfo:  /* 2 */
776                 case NetlogonValidationSamInfo2: /* 3 */
777                 case NetlogonValidationSamInfo4: /* 6 */
778                         break;
779                 default:
780                         return NT_STATUS_INVALID_INFO_CLASS;
781                 }
782
783                 break;
784
785         case NetlogonGenericInformation:
786                 if (r->in.logon->generic == NULL) {
787                         return NT_STATUS_INVALID_PARAMETER;
788                 }
789
790                 switch (r->in.validation_level) {
791                 /* TODO: case NetlogonValidationGenericInfo: 4 */
792                 case NetlogonValidationGenericInfo2: /* 5 */
793                         break;
794                 default:
795                         return NT_STATUS_INVALID_INFO_CLASS;
796                 }
797
798                 break;
799         default:
800                 return NT_STATUS_INVALID_PARAMETER;
801         }
802
803         return NT_STATUS_OK;
804 }
805
806 /*
807   netr_LogonSamLogon_base
808
809   This version of the function allows other wrappers to say 'do not check the credentials'
810
811   We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
812 */
813 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
814                                         struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
815 {
816         struct auth4_context *auth_context;
817         struct auth_usersupplied_info *user_info;
818         struct auth_user_info_dc *user_info_dc;
819         NTSTATUS nt_status;
820         struct netr_SamBaseInfo *sam;
821         struct netr_SamInfo2 *sam2;
822         struct netr_SamInfo3 *sam3;
823         struct netr_SamInfo6 *sam6;
824
825         *r->out.authoritative = 1;
826
827         user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
828         NT_STATUS_HAVE_NO_MEMORY(user_info);
829
830         netlogon_creds_decrypt_samlogon_logon(creds,
831                                               r->in.logon_level,
832                                               r->in.logon);
833
834         switch (r->in.logon_level) {
835         case NetlogonInteractiveInformation:
836         case NetlogonServiceInformation:
837         case NetlogonInteractiveTransitiveInformation:
838         case NetlogonServiceTransitiveInformation:
839
840                 /* TODO: we need to deny anonymous access here */
841                 nt_status = auth_context_create(mem_ctx,
842                                                 dce_call->event_ctx, dce_call->msg_ctx,
843                                                 dce_call->conn->dce_ctx->lp_ctx,
844                                                 &auth_context);
845                 NT_STATUS_NOT_OK_RETURN(nt_status);
846
847                 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
848                 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
849                 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
850                 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
851
852                 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
853                 user_info->password_state = AUTH_PASSWORD_HASH;
854
855                 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
856                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
857                 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
858
859                 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
860                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
861                 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
862
863                 break;
864         case NetlogonNetworkInformation:
865         case NetlogonNetworkTransitiveInformation:
866
867                 /* TODO: we need to deny anonymous access here */
868                 nt_status = auth_context_create(mem_ctx,
869                                                 dce_call->event_ctx, dce_call->msg_ctx,
870                                                 dce_call->conn->dce_ctx->lp_ctx,
871                                                 &auth_context);
872                 NT_STATUS_NOT_OK_RETURN(nt_status);
873
874                 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
875                 NT_STATUS_NOT_OK_RETURN(nt_status);
876
877                 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
878                 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
879                 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
880                 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
881
882                 user_info->password_state = AUTH_PASSWORD_RESPONSE;
883                 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
884                 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
885
886                 break;
887
888
889         case NetlogonGenericInformation:
890         {
891                 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
892                         /* OK */
893                 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
894                         /* OK */
895                 } else {
896                         /* Using DES to verify kerberos tickets makes no sense */
897                         return NT_STATUS_INVALID_PARAMETER;
898                 }
899
900                 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
901                         NTSTATUS status;
902                         struct dcerpc_binding_handle *irpc_handle;
903                         struct kdc_check_generic_kerberos check;
904                         struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
905                         NT_STATUS_HAVE_NO_MEMORY(generic);
906                         *r->out.authoritative = 1;
907
908                         /* TODO: Describe and deal with these flags */
909                         *r->out.flags = 0;
910
911                         r->out.validation->generic = generic;
912
913                         irpc_handle = irpc_binding_handle_by_name(mem_ctx,
914                                                                   dce_call->msg_ctx,
915                                                                   "kdc_server",
916                                                                   &ndr_table_irpc);
917                         if (irpc_handle == NULL) {
918                                 return NT_STATUS_NO_LOGON_SERVERS;
919                         }
920
921                         check.in.generic_request =
922                                 data_blob_const(r->in.logon->generic->data,
923                                                 r->in.logon->generic->length);
924
925                         /*
926                          * TODO: make this async and avoid
927                          * dcerpc_binding_handle_set_sync_ev()
928                          */
929                         dcerpc_binding_handle_set_sync_ev(irpc_handle,
930                                                           dce_call->event_ctx);
931                         status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
932                                                                      mem_ctx,
933                                                                      &check);
934                         if (!NT_STATUS_IS_OK(status)) {
935                                 return status;
936                         }
937                         generic->length = check.out.generic_reply.length;
938                         generic->data = check.out.generic_reply.data;
939                         return NT_STATUS_OK;
940                 }
941
942                 /* Until we get an implemetnation of these other packages */
943                 return NT_STATUS_INVALID_PARAMETER;
944         }
945         default:
946                 return NT_STATUS_INVALID_PARAMETER;
947         }
948
949         nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
950         /* TODO: set *r->out.authoritative = 0 on specific errors */
951         NT_STATUS_NOT_OK_RETURN(nt_status);
952
953         switch (r->in.validation_level) {
954         case 2:
955                 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
956                 NT_STATUS_NOT_OK_RETURN(nt_status);
957
958                 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
959                 NT_STATUS_HAVE_NO_MEMORY(sam2);
960                 sam2->base = *sam;
961
962                 /* And put into the talloc tree */
963                 talloc_steal(sam2, sam);
964                 r->out.validation->sam2 = sam2;
965
966                 sam = &sam2->base;
967                 break;
968
969         case 3:
970                 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
971                                                               user_info_dc,
972                                                               &sam3);
973                 NT_STATUS_NOT_OK_RETURN(nt_status);
974
975                 r->out.validation->sam3 = sam3;
976
977                 sam = &sam3->base;
978                 break;
979
980         case 6:
981                 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
982                                                            user_info_dc,
983                                                            &sam3);
984                 NT_STATUS_NOT_OK_RETURN(nt_status);
985
986                 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
987                 NT_STATUS_HAVE_NO_MEMORY(sam6);
988                 sam6->base = sam3->base;
989                 sam = &sam6->base;
990                 sam6->sidcount = sam3->sidcount;
991                 sam6->sids = sam3->sids;
992
993                 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
994                 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
995                                                          sam->account_name.string, sam6->dns_domainname.string);
996                 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
997                 /* And put into the talloc tree */
998                 talloc_steal(sam6, sam3);
999
1000                 r->out.validation->sam6 = sam6;
1001                 break;
1002
1003         default:
1004                 return NT_STATUS_INVALID_INFO_CLASS;
1005         }
1006
1007         netlogon_creds_encrypt_samlogon_validation(creds,
1008                                                    r->in.validation_level,
1009                                                    r->out.validation);
1010
1011         /* TODO: Describe and deal with these flags */
1012         *r->out.flags = 0;
1013
1014         return NT_STATUS_OK;
1015 }
1016
1017 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1018                                      struct netr_LogonSamLogonEx *r)
1019 {
1020         NTSTATUS nt_status;
1021         struct netlogon_creds_CredentialState *creds;
1022
1023         *r->out.authoritative = 1;
1024
1025         nt_status = dcesrv_netr_LogonSamLogon_check(r);
1026         if (!NT_STATUS_IS_OK(nt_status)) {
1027                 return nt_status;
1028         }
1029
1030         nt_status = schannel_get_creds_state(mem_ctx,
1031                                              dce_call->conn->dce_ctx->lp_ctx,
1032                                              r->in.computer_name, &creds);
1033         if (!NT_STATUS_IS_OK(nt_status)) {
1034                 return nt_status;
1035         }
1036
1037         if (!dce_call->conn->auth_state.auth_info ||
1038             dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1039                 return NT_STATUS_ACCESS_DENIED;
1040         }
1041         return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
1042 }
1043
1044 /*
1045   netr_LogonSamLogonWithFlags
1046
1047 */
1048 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1049                                             struct netr_LogonSamLogonWithFlags *r)
1050 {
1051         NTSTATUS nt_status;
1052         struct netlogon_creds_CredentialState *creds;
1053         struct netr_LogonSamLogonEx r2;
1054
1055         struct netr_Authenticator *return_authenticator;
1056
1057         ZERO_STRUCT(r2);
1058
1059         r2.in.server_name       = r->in.server_name;
1060         r2.in.computer_name     = r->in.computer_name;
1061         r2.in.logon_level       = r->in.logon_level;
1062         r2.in.logon             = r->in.logon;
1063         r2.in.validation_level  = r->in.validation_level;
1064         r2.in.flags             = r->in.flags;
1065         r2.out.validation       = r->out.validation;
1066         r2.out.authoritative    = r->out.authoritative;
1067         r2.out.flags            = r->out.flags;
1068
1069         *r->out.authoritative = 1;
1070
1071         nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
1072         if (!NT_STATUS_IS_OK(nt_status)) {
1073                 return nt_status;
1074         }
1075
1076         return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
1077         NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
1078
1079         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1080                                                         mem_ctx,
1081                                                         r->in.computer_name,
1082                                                         r->in.credential, return_authenticator,
1083                                                         &creds);
1084         NT_STATUS_NOT_OK_RETURN(nt_status);
1085
1086         nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
1087
1088         r->out.return_authenticator     = return_authenticator;
1089
1090         return nt_status;
1091 }
1092
1093 /*
1094   netr_LogonSamLogon
1095 */
1096 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1097                                    struct netr_LogonSamLogon *r)
1098 {
1099         struct netr_LogonSamLogonWithFlags r2;
1100         uint32_t flags = 0;
1101         NTSTATUS status;
1102
1103         ZERO_STRUCT(r2);
1104
1105         r2.in.server_name = r->in.server_name;
1106         r2.in.computer_name = r->in.computer_name;
1107         r2.in.credential  = r->in.credential;
1108         r2.in.return_authenticator = r->in.return_authenticator;
1109         r2.in.logon_level = r->in.logon_level;
1110         r2.in.logon = r->in.logon;
1111         r2.in.validation_level = r->in.validation_level;
1112         r2.in.flags = &flags;
1113         r2.out.validation = r->out.validation;
1114         r2.out.authoritative = r->out.authoritative;
1115         r2.out.flags = &flags;
1116
1117         status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
1118
1119         r->out.return_authenticator = r2.out.return_authenticator;
1120
1121         return status;
1122 }
1123
1124
1125 /*
1126   netr_LogonSamLogoff
1127 */
1128 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1129                        struct netr_LogonSamLogoff *r)
1130 {
1131         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1132 }
1133
1134
1135
1136 /*
1137   netr_DatabaseDeltas
1138 */
1139 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1140                        struct netr_DatabaseDeltas *r)
1141 {
1142         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1143 }
1144
1145
1146 /*
1147   netr_DatabaseSync2
1148 */
1149 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1150                        struct netr_DatabaseSync2 *r)
1151 {
1152         /* win2k3 native mode returns  "NOT IMPLEMENTED" for this call */
1153         return NT_STATUS_NOT_IMPLEMENTED;
1154 }
1155
1156
1157 /*
1158   netr_DatabaseSync
1159 */
1160 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1161                        struct netr_DatabaseSync *r)
1162 {
1163         struct netr_DatabaseSync2 r2;
1164         NTSTATUS status;
1165
1166         ZERO_STRUCT(r2);
1167
1168         r2.in.logon_server = r->in.logon_server;
1169         r2.in.computername = r->in.computername;
1170         r2.in.credential = r->in.credential;
1171         r2.in.database_id = r->in.database_id;
1172         r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1173         r2.in.sync_context = r->in.sync_context;
1174         r2.out.sync_context = r->out.sync_context;
1175         r2.out.delta_enum_array = r->out.delta_enum_array;
1176         r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1177
1178         status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1179
1180         return status;
1181 }
1182
1183
1184 /*
1185   netr_AccountDeltas
1186 */
1187 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1188                        struct netr_AccountDeltas *r)
1189 {
1190         /* w2k3 returns "NOT IMPLEMENTED" for this call */
1191         return NT_STATUS_NOT_IMPLEMENTED;
1192 }
1193
1194
1195 /*
1196   netr_AccountSync
1197 */
1198 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1199                        struct netr_AccountSync *r)
1200 {
1201         /* w2k3 returns "NOT IMPLEMENTED" for this call */
1202         return NT_STATUS_NOT_IMPLEMENTED;
1203 }
1204
1205
1206 /*
1207   netr_GetDcName
1208 */
1209 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1210                        struct netr_GetDcName *r)
1211 {
1212         const char * const attrs[] = { NULL };
1213         struct ldb_context *sam_ctx;
1214         struct ldb_message **res;
1215         struct ldb_dn *domain_dn;
1216         int ret;
1217         const char *dcname;
1218
1219         /*
1220          * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1221          * that the domainname needs to be a valid netbios domain
1222          * name, if it is not NULL.
1223          */
1224         if (r->in.domainname) {
1225                 const char *dot = strchr(r->in.domainname, '.');
1226                 size_t len = strlen(r->in.domainname);
1227
1228                 if (dot || len > 15) {
1229                         return WERR_DCNOTFOUND;
1230                 }
1231
1232                 /*
1233                  * TODO: Should we also varify that only valid
1234                  *       netbios name characters are used?
1235                  */
1236         }
1237
1238         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1239                                 dce_call->conn->dce_ctx->lp_ctx,
1240                                 dce_call->conn->auth_state.session_info, 0);
1241         if (sam_ctx == NULL) {
1242                 return WERR_DS_UNAVAILABLE;
1243         }
1244
1245         domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1246                                        r->in.domainname);
1247         if (domain_dn == NULL) {
1248                 return WERR_NO_SUCH_DOMAIN;
1249         }
1250
1251         ret = gendb_search_dn(sam_ctx, mem_ctx,
1252                               domain_dn, &res, attrs);
1253         if (ret != 1) {
1254                 return WERR_NO_SUCH_DOMAIN;
1255         }
1256
1257         /* TODO: - return real IP address
1258          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
1259          */
1260         dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1261                                  lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1262         W_ERROR_HAVE_NO_MEMORY(dcname);
1263
1264         *r->out.dcname = dcname;
1265         return WERR_OK;
1266 }
1267
1268 struct dcesrv_netr_LogonControl_base_state {
1269         struct dcesrv_call_state *dce_call;
1270
1271         TALLOC_CTX *mem_ctx;
1272
1273         struct netr_LogonControl2Ex r;
1274
1275         struct {
1276                 struct netr_LogonControl *l;
1277                 struct netr_LogonControl2 *l2;
1278                 struct netr_LogonControl2Ex *l2ex;
1279         } _r;
1280 };
1281
1282 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
1283
1284 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
1285 {
1286         struct dcesrv_connection *conn = state->dce_call->conn;
1287         struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
1288         struct auth_session_info *session_info = conn->auth_state.session_info;
1289         enum security_user_level security_level;
1290         struct dcerpc_binding_handle *irpc_handle;
1291         struct tevent_req *subreq;
1292         bool ok;
1293
1294         /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
1295
1296         if (state->_r.l != NULL) {
1297                 /*
1298                  * netr_LogonControl
1299                  */
1300                 if (state->r.in.level == 0x00000002) {
1301                         return WERR_NOT_SUPPORTED;
1302                 } else if (state->r.in.level != 0x00000001) {
1303                         return WERR_INVALID_LEVEL;
1304                 }
1305
1306                 switch (state->r.in.function_code) {
1307                 case NETLOGON_CONTROL_QUERY:
1308                 case NETLOGON_CONTROL_REPLICATE:
1309                 case NETLOGON_CONTROL_SYNCHRONIZE:
1310                 case NETLOGON_CONTROL_PDC_REPLICATE:
1311                 case NETLOGON_CONTROL_BREAKPOINT:
1312                 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
1313                 case NETLOGON_CONTROL_TRUNCATE_LOG:
1314                         break;
1315                 default:
1316                         return WERR_NOT_SUPPORTED;
1317                 }
1318         }
1319
1320         if (state->r.in.level < 0x00000001) {
1321                 return WERR_INVALID_LEVEL;
1322         }
1323
1324         if (state->r.in.level > 0x00000004) {
1325                 return WERR_INVALID_LEVEL;
1326         }
1327
1328         if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
1329                 struct netr_NETLOGON_INFO_1 *info1 = NULL;
1330                 struct netr_NETLOGON_INFO_3 *info3 = NULL;
1331
1332                 switch (state->r.in.level) {
1333                 case 0x00000001:
1334                         info1 = talloc_zero(state->mem_ctx,
1335                                             struct netr_NETLOGON_INFO_1);
1336                         if (info1 == NULL) {
1337                                 return WERR_NOMEM;
1338                         }
1339                         state->r.out.query->info1 = info1;
1340                         return WERR_OK;
1341
1342                 case 0x00000003:
1343                         info3 = talloc_zero(state->mem_ctx,
1344                                             struct netr_NETLOGON_INFO_3);
1345                         if (info3 == NULL) {
1346                                 return WERR_NOMEM;
1347                         }
1348                         state->r.out.query->info3 = info3;
1349                         return WERR_OK;
1350
1351                 default:
1352                         return WERR_INVALID_PARAMETER;
1353                 }
1354         }
1355
1356         /*
1357          * Some validations are done before the access check
1358          * and some after the access check
1359          */
1360         security_level = security_session_user_level(session_info, NULL);
1361         if (security_level < SECURITY_ADMINISTRATOR) {
1362                 return WERR_ACCESS_DENIED;
1363         }
1364
1365         if (state->_r.l2 != NULL) {
1366                 /*
1367                  * netr_LogonControl2
1368                  */
1369                 if (state->r.in.level == 0x00000004) {
1370                         return WERR_INVALID_LEVEL;
1371                 }
1372         }
1373
1374         switch (state->r.in.level) {
1375         case 0x00000001:
1376                 break;
1377
1378         case 0x00000002:
1379                 switch (state->r.in.function_code) {
1380                 case NETLOGON_CONTROL_REDISCOVER:
1381                 case NETLOGON_CONTROL_TC_QUERY:
1382                 case NETLOGON_CONTROL_TC_VERIFY:
1383                         break;
1384                 default:
1385                         return WERR_INVALID_PARAMETER;
1386                 }
1387
1388                 break;
1389
1390         case 0x00000003:
1391                 break;
1392
1393         case 0x00000004:
1394                 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
1395                         return WERR_INVALID_PARAMETER;
1396                 }
1397
1398                 break;
1399
1400         default:
1401                 return WERR_INVALID_LEVEL;
1402         }
1403
1404         switch (state->r.in.function_code) {
1405         case NETLOGON_CONTROL_REDISCOVER:
1406         case NETLOGON_CONTROL_TC_QUERY:
1407         case NETLOGON_CONTROL_TC_VERIFY:
1408                 if (state->r.in.level != 2) {
1409                         return WERR_INVALID_PARAMETER;
1410                 }
1411
1412                 if (state->r.in.data == NULL) {
1413                         return WERR_INVALID_PARAMETER;
1414                 }
1415
1416                 if (state->r.in.data->domain == NULL) {
1417                         return WERR_INVALID_PARAMETER;
1418                 }
1419
1420                 break;
1421
1422         case NETLOGON_CONTROL_CHANGE_PASSWORD:
1423                 if (state->r.in.level != 1) {
1424                         return WERR_INVALID_PARAMETER;
1425                 }
1426
1427                 if (state->r.in.data == NULL) {
1428                         return WERR_INVALID_PARAMETER;
1429                 }
1430
1431                 if (state->r.in.data->domain == NULL) {
1432                         return WERR_INVALID_PARAMETER;
1433                 }
1434
1435                 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
1436                                                  state->r.in.data->domain);
1437                 if (!ok) {
1438                         struct ldb_context *sam_ctx;
1439
1440                         sam_ctx = samdb_connect(state, state->dce_call->event_ctx,
1441                                                 lp_ctx, system_session(lp_ctx), 0);
1442                         if (sam_ctx == NULL) {
1443                                 return WERR_DS_UNAVAILABLE;
1444                         }
1445
1446                         /*
1447                          * Secrets for trusted domains can only be triggered on
1448                          * the PDC.
1449                          */
1450                         ok = samdb_is_pdc(sam_ctx);
1451                         TALLOC_FREE(sam_ctx);
1452                         if (!ok) {
1453                                 return WERR_INVALID_DOMAIN_ROLE;
1454                         }
1455                 }
1456
1457                 break;
1458         default:
1459                 return WERR_NOT_SUPPORTED;
1460         }
1461
1462         irpc_handle = irpc_binding_handle_by_name(state,
1463                                                   state->dce_call->msg_ctx,
1464                                                   "winbind_server",
1465                                                   &ndr_table_winbind);
1466         if (irpc_handle == NULL) {
1467                 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
1468                 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1469                 return WERR_SERVICE_NOT_FOUND;
1470         }
1471
1472         /*
1473          * 60 seconds timeout should be enough
1474          */
1475         dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1476
1477         subreq = dcerpc_winbind_LogonControl_send(state,
1478                                                   state->dce_call->event_ctx,
1479                                                   irpc_handle,
1480                                                   state->r.in.function_code,
1481                                                   state->r.in.level,
1482                                                   state->r.in.data,
1483                                                   state->r.out.query);
1484         if (subreq == NULL) {
1485                 return WERR_NOMEM;
1486         }
1487         state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1488         tevent_req_set_callback(subreq,
1489                                 dcesrv_netr_LogonControl_base_done,
1490                                 state);
1491
1492         return WERR_OK;
1493 }
1494
1495 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
1496 {
1497         struct dcesrv_netr_LogonControl_base_state *state =
1498                 tevent_req_callback_data(subreq,
1499                 struct dcesrv_netr_LogonControl_base_state);
1500         NTSTATUS status;
1501
1502         status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
1503                                                   &state->r.out.result);
1504         TALLOC_FREE(subreq);
1505         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
1506                 state->r.out.result = WERR_TIMEOUT;
1507         } else if (!NT_STATUS_IS_OK(status)) {
1508                 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1509                 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
1510                          nt_errstr(status)));
1511         }
1512
1513         if (state->_r.l2ex != NULL) {
1514                 struct netr_LogonControl2Ex *r = state->_r.l2ex;
1515                 r->out.result = state->r.out.result;
1516         } else if (state->_r.l2 != NULL) {
1517                 struct netr_LogonControl2 *r = state->_r.l2;
1518                 r->out.result = state->r.out.result;
1519         } else if (state->_r.l != NULL) {
1520                 struct netr_LogonControl *r = state->_r.l;
1521                 r->out.result = state->r.out.result;
1522         }
1523
1524         status = dcesrv_reply(state->dce_call);
1525         if (!NT_STATUS_IS_OK(status)) {
1526                 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
1527         }
1528 }
1529
1530 /*
1531   netr_LogonControl
1532 */
1533 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1534                        struct netr_LogonControl *r)
1535 {
1536         struct dcesrv_netr_LogonControl_base_state *state;
1537         WERROR werr;
1538
1539         state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1540         if (state == NULL) {
1541                 return WERR_NOMEM;
1542         }
1543
1544         state->dce_call = dce_call;
1545         state->mem_ctx = mem_ctx;
1546
1547         state->r.in.logon_server = r->in.logon_server;
1548         state->r.in.function_code = r->in.function_code;
1549         state->r.in.level = r->in.level;
1550         state->r.in.data = NULL;
1551         state->r.out.query = r->out.query;
1552
1553         state->_r.l = r;
1554
1555         werr = dcesrv_netr_LogonControl_base_call(state);
1556
1557         if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1558                 return werr;
1559         }
1560
1561         return werr;
1562 }
1563
1564 /*
1565   netr_LogonControl2
1566 */
1567 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1568                        struct netr_LogonControl2 *r)
1569 {
1570         struct dcesrv_netr_LogonControl_base_state *state;
1571         WERROR werr;
1572
1573         state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1574         if (state == NULL) {
1575                 return WERR_NOMEM;
1576         }
1577
1578         state->dce_call = dce_call;
1579         state->mem_ctx = mem_ctx;
1580
1581         state->r.in.logon_server = r->in.logon_server;
1582         state->r.in.function_code = r->in.function_code;
1583         state->r.in.level = r->in.level;
1584         state->r.in.data = r->in.data;
1585         state->r.out.query = r->out.query;
1586
1587         state->_r.l2 = r;
1588
1589         werr = dcesrv_netr_LogonControl_base_call(state);
1590
1591         if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1592                 return werr;
1593         }
1594
1595         return werr;
1596 }
1597
1598 /*
1599   netr_LogonControl2Ex
1600 */
1601 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1602                        struct netr_LogonControl2Ex *r)
1603 {
1604         struct dcesrv_netr_LogonControl_base_state *state;
1605         WERROR werr;
1606
1607         state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1608         if (state == NULL) {
1609                 return WERR_NOMEM;
1610         }
1611
1612         state->dce_call = dce_call;
1613         state->mem_ctx = mem_ctx;
1614
1615         state->r = *r;
1616         state->_r.l2ex = r;
1617
1618         werr = dcesrv_netr_LogonControl_base_call(state);
1619
1620         if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1621                 return werr;
1622         }
1623
1624         return werr;
1625 }
1626
1627 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1628                                          struct ldb_context *sam_ctx,
1629                                          struct netr_DomainTrustList *trusts,
1630                                          uint32_t trust_flags);
1631
1632 /*
1633   netr_GetAnyDCName
1634 */
1635 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1636                        struct netr_GetAnyDCName *r)
1637 {
1638         struct netr_DomainTrustList *trusts;
1639         struct ldb_context *sam_ctx;
1640         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1641         uint32_t i;
1642         WERROR werr;
1643
1644         *r->out.dcname = NULL;
1645
1646         if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1647                 /* if the domainname parameter wasn't set assume our domain */
1648                 r->in.domainname = lpcfg_workgroup(lp_ctx);
1649         }
1650
1651         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1652                                 dce_call->conn->auth_state.session_info, 0);
1653         if (sam_ctx == NULL) {
1654                 return WERR_DS_UNAVAILABLE;
1655         }
1656
1657         if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1658                 /* well we asked for a DC of our own domain */
1659                 if (samdb_is_pdc(sam_ctx)) {
1660                         /* we are the PDC of the specified domain */
1661                         return WERR_NO_SUCH_DOMAIN;
1662                 }
1663
1664                 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1665                                                 lpcfg_netbios_name(lp_ctx));
1666                 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1667
1668                 return WERR_OK;
1669         }
1670
1671         /* Okay, now we have to consider the trusted domains */
1672
1673         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1674         W_ERROR_HAVE_NO_MEMORY(trusts);
1675
1676         trusts->count = 0;
1677
1678         werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1679                                           NETR_TRUST_FLAG_INBOUND
1680                                           | NETR_TRUST_FLAG_OUTBOUND);
1681         W_ERROR_NOT_OK_RETURN(werr);
1682
1683         for (i = 0; i < trusts->count; i++) {
1684                 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1685                         /* FIXME: Here we need to find a DC for the specified
1686                          * trusted domain. */
1687
1688                         /* return WERR_OK; */
1689                         return WERR_NO_SUCH_DOMAIN;
1690                 }
1691         }
1692
1693         return WERR_NO_SUCH_DOMAIN;
1694 }
1695
1696
1697 /*
1698   netr_DatabaseRedo
1699 */
1700 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1701                        struct netr_DatabaseRedo *r)
1702 {
1703         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1704 }
1705
1706
1707 /*
1708   netr_NetrEnumerateTrustedDomains
1709 */
1710 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1711                        struct netr_NetrEnumerateTrustedDomains *r)
1712 {
1713         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1714 }
1715
1716
1717 /*
1718   netr_LogonGetCapabilities
1719 */
1720 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1721                        struct netr_LogonGetCapabilities *r)
1722 {
1723         struct netlogon_creds_CredentialState *creds;
1724         NTSTATUS status;
1725
1726         status = dcesrv_netr_creds_server_step_check(dce_call,
1727                                                      mem_ctx,
1728                                                      r->in.computer_name,
1729                                                      r->in.credential,
1730                                                      r->out.return_authenticator,
1731                                                      &creds);
1732         if (!NT_STATUS_IS_OK(status)) {
1733                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1734         }
1735         NT_STATUS_NOT_OK_RETURN(status);
1736
1737         if (r->in.query_level != 1) {
1738                 return NT_STATUS_NOT_SUPPORTED;
1739         }
1740
1741         r->out.capabilities->server_capabilities = creds->negotiate_flags;
1742
1743         return NT_STATUS_OK;
1744 }
1745
1746
1747 /*
1748   netr_NETRLOGONSETSERVICEBITS
1749 */
1750 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1751                        struct netr_NETRLOGONSETSERVICEBITS *r)
1752 {
1753         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1754 }
1755
1756
1757 /*
1758   netr_LogonGetTrustRid
1759 */
1760 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1761                        struct netr_LogonGetTrustRid *r)
1762 {
1763         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1764 }
1765
1766
1767 /*
1768   netr_NETRLOGONCOMPUTESERVERDIGEST
1769 */
1770 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1771                        struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1772 {
1773         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1774 }
1775
1776
1777 /*
1778   netr_NETRLOGONCOMPUTECLIENTDIGEST
1779 */
1780 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1781                        struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1782 {
1783         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1784 }
1785
1786
1787
1788 /*
1789   netr_DsRGetSiteName
1790 */
1791 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1792                                   struct netr_DsRGetSiteName *r)
1793 {
1794         struct ldb_context *sam_ctx;
1795         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1796
1797         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1798                                 dce_call->conn->auth_state.session_info, 0);
1799         if (sam_ctx == NULL) {
1800                 return WERR_DS_UNAVAILABLE;
1801         }
1802
1803         /*
1804          * We assume to be a DC when we get called over NETLOGON. Hence we
1805          * get our site name always by using "samdb_server_site_name()"
1806          * and not "samdb_client_site_name()".
1807          */
1808         *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1809         W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1810
1811         return WERR_OK;
1812 }
1813
1814
1815 /*
1816   fill in a netr_OneDomainInfo from a ldb search result
1817 */
1818 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1819                                      struct loadparm_context *lp_ctx,
1820                                      struct ldb_context *sam_ctx,
1821                                      struct ldb_message *res,
1822                                      struct netr_OneDomainInfo *info,
1823                                      bool is_local, bool is_trust_list)
1824 {
1825         ZERO_STRUCTP(info);
1826
1827         if (is_trust_list) {
1828                 /* w2k8 only fills this on trusted domains */
1829                 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1830                 info->trust_extension.length = 16;
1831                 info->trust_extension.info->flags =
1832                         NETR_TRUST_FLAG_TREEROOT |
1833                         NETR_TRUST_FLAG_IN_FOREST |
1834                         NETR_TRUST_FLAG_PRIMARY |
1835                         NETR_TRUST_FLAG_NATIVE;
1836
1837                 info->trust_extension.info->parent_index = 0; /* should be index into array
1838                                                                  of parent */
1839                 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1840                 info->trust_extension.info->trust_attributes = 0; /*    TODO: base on ldb search? */
1841         }
1842
1843         if (is_trust_list) {
1844                 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1845                 info->dns_forestname.string = NULL;
1846         } else {
1847                 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1848                 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1849                 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1850                 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1851         }
1852
1853         if (is_local) {
1854                 info->domainname.string = lpcfg_workgroup(lp_ctx);
1855                 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1856                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1857                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1858         } else {
1859                 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1860                 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1861                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1862                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1863         }
1864         if (!is_trust_list) {
1865                 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1866         }
1867
1868         return NT_STATUS_OK;
1869 }
1870
1871 /*
1872   netr_LogonGetDomainInfo
1873   this is called as part of the ADS domain logon procedure.
1874
1875   It has an important role in convaying details about the client, such
1876   as Operating System, Version, Service Pack etc.
1877 */
1878 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1879         TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1880 {
1881         struct netlogon_creds_CredentialState *creds;
1882         const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1883                 "securityIdentifier", "trustPartner", NULL };
1884         const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1885                 "msDS-SupportedEncryptionTypes", NULL };
1886         const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1887         struct ldb_context *sam_ctx;
1888         struct ldb_message **res1, **res2, **res3, *new_msg;
1889         struct ldb_dn *workstation_dn;
1890         struct netr_DomainInformation *domain_info;
1891         struct netr_LsaPolicyInformation *lsa_policy_info;
1892         uint32_t default_supported_enc_types = 0xFFFFFFFF;
1893         bool update_dns_hostname = true;
1894         int ret, ret3, i;
1895         NTSTATUS status;
1896
1897         status = dcesrv_netr_creds_server_step_check(dce_call,
1898                                                      mem_ctx,
1899                                                      r->in.computer_name,
1900                                                      r->in.credential,
1901                                                      r->out.return_authenticator,
1902                                                      &creds);
1903         if (!NT_STATUS_IS_OK(status)) {
1904                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1905         }
1906         NT_STATUS_NOT_OK_RETURN(status);
1907
1908         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1909                                 dce_call->conn->dce_ctx->lp_ctx,
1910                                 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1911         if (sam_ctx == NULL) {
1912                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1913         }
1914
1915         switch (r->in.level) {
1916         case 1: /* Domain information */
1917
1918                 if (r->in.query->workstation_info == NULL) {
1919                         return NT_STATUS_INVALID_PARAMETER;
1920                 }
1921
1922                 /* Prepares the workstation DN */
1923                 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1924                                                 dom_sid_string(mem_ctx, creds->sid));
1925                 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1926
1927                 /* Lookup for attributes in workstation object */
1928                 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1929                                       attrs2);
1930                 if (ret != 1) {
1931                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1932                 }
1933
1934                 /* Gets the sam account name which is checked against the DNS
1935                  * hostname parameter. */
1936                 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1937                                                                "sAMAccountName",
1938                                                                NULL);
1939                 if (sam_account_name == NULL) {
1940                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1941                 }
1942
1943                 /*
1944                  * Checks that the sam account name without a possible "$"
1945                  * matches as prefix with the DNS hostname in the workstation
1946                  * info structure.
1947                  */
1948                 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1949                                          strcspn(sam_account_name, "$"));
1950                 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1951                 if (r->in.query->workstation_info->dns_hostname != NULL) {
1952                         prefix2 = talloc_strndup(mem_ctx,
1953                                                  r->in.query->workstation_info->dns_hostname,
1954                                                  strcspn(r->in.query->workstation_info->dns_hostname, "."));
1955                         NT_STATUS_HAVE_NO_MEMORY(prefix2);
1956
1957                         if (strcasecmp(prefix1, prefix2) != 0) {
1958                                 update_dns_hostname = false;
1959                         }
1960                 } else {
1961                         update_dns_hostname = false;
1962                 }
1963
1964                 /* Gets the old DNS hostname */
1965                 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1966                                                                "dNSHostName",
1967                                                                NULL);
1968
1969                 /*
1970                  * Updates the DNS hostname when the client wishes that the
1971                  * server should handle this for him
1972                  * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1973                  * obviously only checked when we do already have a
1974                  * "dNSHostName".
1975                  * See MS-NRPC section 3.5.4.3.9
1976                  */
1977                 if ((old_dns_hostname != NULL) &&
1978                     (r->in.query->workstation_info->workstation_flags
1979                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1980                         update_dns_hostname = false;
1981                 }
1982
1983                 /* Gets host information and put them into our directory */
1984
1985                 new_msg = ldb_msg_new(mem_ctx);
1986                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1987
1988                 new_msg->dn = workstation_dn;
1989
1990                 /* Sets the OS name */
1991
1992                 if (r->in.query->workstation_info->os_name.string == NULL) {
1993                         return NT_STATUS_INVALID_PARAMETER;
1994                 }
1995
1996                 ret = ldb_msg_add_string(new_msg, "operatingSystem",
1997                                          r->in.query->workstation_info->os_name.string);
1998                 if (ret != LDB_SUCCESS) {
1999                         return NT_STATUS_NO_MEMORY;
2000                 }
2001
2002                 /*
2003                  * Sets information from "os_version". On an empty structure
2004                  * the values are cleared.
2005                  */
2006                 if (r->in.query->workstation_info->os_version.os != NULL) {
2007                         struct netr_OsVersionInfoEx *os_version;
2008                         const char *os_version_str;
2009
2010                         os_version = &r->in.query->workstation_info->os_version.os->os;
2011
2012                         if (os_version->CSDVersion == NULL) {
2013                                 return NT_STATUS_INVALID_PARAMETER;
2014                         }
2015
2016                         os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
2017                                                          os_version->MajorVersion,
2018                                                          os_version->MinorVersion,
2019                                                          os_version->BuildNumber);
2020                         NT_STATUS_HAVE_NO_MEMORY(os_version_str);
2021
2022                         ret = ldb_msg_add_string(new_msg,
2023                                                  "operatingSystemServicePack",
2024                                                  os_version->CSDVersion);
2025                         if (ret != LDB_SUCCESS) {
2026                                 return NT_STATUS_NO_MEMORY;
2027                         }
2028
2029                         ret = ldb_msg_add_string(new_msg,
2030                                                  "operatingSystemVersion",
2031                                                  os_version_str);
2032                         if (ret != LDB_SUCCESS) {
2033                                 return NT_STATUS_NO_MEMORY;
2034                         }
2035                 } else {
2036                         ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2037                                                    "operatingSystemServicePack");
2038                         if (ret != LDB_SUCCESS) {
2039                                 return NT_STATUS_NO_MEMORY;
2040                         }
2041
2042                         ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2043                                                    "operatingSystemVersion");
2044                         if (ret != LDB_SUCCESS) {
2045                                 return NT_STATUS_NO_MEMORY;
2046                         }
2047                 }
2048
2049                 /*
2050                  * If the boolean "update_dns_hostname" remained true, then we
2051                  * are fine to start the update.
2052                  */
2053                 if (update_dns_hostname) {
2054                         ret = ldb_msg_add_string(new_msg,
2055                                                  "dNSHostname",
2056                                                  r->in.query->workstation_info->dns_hostname);
2057                         if (ret != LDB_SUCCESS) {
2058                                 return NT_STATUS_NO_MEMORY;
2059                         }
2060
2061                         /* This manual "servicePrincipalName" generation is
2062                          * still needed! Since the update in the samldb LDB
2063                          * module does only work if the entries already exist
2064                          * which isn't always the case. */
2065                         ret = ldb_msg_add_string(new_msg,
2066                                                  "servicePrincipalName",
2067                                                  talloc_asprintf(new_msg, "HOST/%s",
2068                                                  r->in.computer_name));
2069                         if (ret != LDB_SUCCESS) {
2070                                 return NT_STATUS_NO_MEMORY;
2071                         }
2072
2073                         ret = ldb_msg_add_string(new_msg,
2074                                                  "servicePrincipalName",
2075                                                  talloc_asprintf(new_msg, "HOST/%s",
2076                                                  r->in.query->workstation_info->dns_hostname));
2077                         if (ret != LDB_SUCCESS) {
2078                                 return NT_STATUS_NO_MEMORY;
2079                         }
2080                 }
2081
2082                 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
2083                         DEBUG(3,("Impossible to update samdb: %s\n",
2084                                 ldb_errstring(sam_ctx)));
2085                 }
2086
2087                 talloc_free(new_msg);
2088
2089                 /* Writes back the domain information */
2090
2091                 /* We need to do two searches. The first will pull our primary
2092                    domain and the second will pull any trusted domains. Our
2093                    primary domain is also a "trusted" domain, so we need to
2094                    put the primary domain into the lists of returned trusts as
2095                    well. */
2096                 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
2097                         &res2, attrs);
2098                 if (ret != 1) {
2099                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2100                 }
2101
2102                 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
2103                         "(objectClass=trustedDomain)");
2104                 if (ret3 == -1) {
2105                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2106                 }
2107
2108                 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
2109                 NT_STATUS_HAVE_NO_MEMORY(domain_info);
2110
2111                 ZERO_STRUCTP(domain_info);
2112
2113                 /* Informations about the local and trusted domains */
2114
2115                 status = fill_one_domain_info(mem_ctx,
2116                         dce_call->conn->dce_ctx->lp_ctx,
2117                         sam_ctx, res2[0], &domain_info->primary_domain,
2118                         true, false);
2119                 NT_STATUS_NOT_OK_RETURN(status);
2120
2121                 domain_info->trusted_domain_count = ret3 + 1;
2122                 domain_info->trusted_domains = talloc_array(mem_ctx,
2123                         struct netr_OneDomainInfo,
2124                         domain_info->trusted_domain_count);
2125                 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
2126
2127                 for (i=0;i<ret3;i++) {
2128                         status = fill_one_domain_info(mem_ctx,
2129                                 dce_call->conn->dce_ctx->lp_ctx,
2130                                 sam_ctx, res3[i],
2131                                 &domain_info->trusted_domains[i],
2132                                 false, true);
2133                         NT_STATUS_NOT_OK_RETURN(status);
2134                 }
2135
2136                 status = fill_one_domain_info(mem_ctx,
2137                         dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
2138                         &domain_info->trusted_domains[i], true, true);
2139                 NT_STATUS_NOT_OK_RETURN(status);
2140
2141                 /* Sets the supported encryption types */
2142                 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
2143                         "msDS-SupportedEncryptionTypes",
2144                         default_supported_enc_types);
2145
2146                 /* Other host domain information */
2147
2148                 lsa_policy_info = talloc(mem_ctx,
2149                         struct netr_LsaPolicyInformation);
2150                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2151                 ZERO_STRUCTP(lsa_policy_info);
2152
2153                 domain_info->lsa_policy = *lsa_policy_info;
2154
2155                 /* The DNS hostname is only returned back when there is a chance
2156                  * for a change. */
2157                 if ((r->in.query->workstation_info->workstation_flags
2158                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2159                         domain_info->dns_hostname.string = old_dns_hostname;
2160                 } else {
2161                         domain_info->dns_hostname.string = NULL;
2162                 }
2163
2164                 domain_info->workstation_flags =
2165                         r->in.query->workstation_info->workstation_flags & (
2166                         NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
2167
2168                 r->out.info->domain_info = domain_info;
2169         break;
2170         case 2: /* LSA policy information - not used at the moment */
2171                 lsa_policy_info = talloc(mem_ctx,
2172                         struct netr_LsaPolicyInformation);
2173                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2174                 ZERO_STRUCTP(lsa_policy_info);
2175
2176                 r->out.info->lsa_policy_info = lsa_policy_info;
2177         break;
2178         default:
2179                 return NT_STATUS_INVALID_LEVEL;
2180         break;
2181         }
2182
2183         return NT_STATUS_OK;
2184 }
2185
2186
2187 /*
2188   netr_ServerPasswordGet
2189 */
2190 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2191                        struct netr_ServerPasswordGet *r)
2192 {
2193         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2194 }
2195
2196
2197 /*
2198   netr_NETRLOGONSENDTOSAM
2199 */
2200 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2201                        struct netr_NETRLOGONSENDTOSAM *r)
2202 {
2203         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2204 }
2205
2206
2207 /*
2208   netr_DsRGetDCNameEx2
2209 */
2210 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
2211                                           TALLOC_CTX *mem_ctx,
2212                                           struct netr_DsRGetDCNameEx2 *r)
2213 {
2214         struct ldb_context *sam_ctx;
2215         struct netr_DsRGetDCNameInfo *info;
2216         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2217         const struct tsocket_address *local_address;
2218         char *local_addr = NULL;
2219         const struct tsocket_address *remote_address;
2220         char *remote_addr = NULL;
2221         const char *server_site_name;
2222         char *guid_str;
2223         struct netlogon_samlogon_response response;
2224         NTSTATUS status;
2225         const char *dc_name = NULL;
2226         const char *domain_name = NULL;
2227         const char *pdc_ip;
2228
2229         ZERO_STRUCTP(r->out.info);
2230
2231         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2232                                 dce_call->conn->auth_state.session_info, 0);
2233         if (sam_ctx == NULL) {
2234                 return WERR_DS_UNAVAILABLE;
2235         }
2236
2237         local_address = dcesrv_connection_get_local_address(dce_call->conn);
2238         if (tsocket_address_is_inet(local_address, "ip")) {
2239                 local_addr = tsocket_address_inet_addr_string(local_address, mem_ctx);
2240                 W_ERROR_HAVE_NO_MEMORY(local_addr);
2241         }
2242
2243         remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
2244         if (tsocket_address_is_inet(remote_address, "ip")) {
2245                 remote_addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
2246                 W_ERROR_HAVE_NO_MEMORY(remote_addr);
2247         }
2248
2249         /* "server_unc" is ignored by w2k3 */
2250
2251         if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
2252                 return WERR_INVALID_FLAGS;
2253         }
2254
2255         if (r->in.flags & DS_GC_SERVER_REQUIRED &&
2256             r->in.flags & DS_PDC_REQUIRED &&
2257             r->in.flags & DS_KDC_REQUIRED) {
2258                 return WERR_INVALID_FLAGS;
2259         }
2260         if (r->in.flags & DS_IS_FLAT_NAME &&
2261             r->in.flags & DS_IS_DNS_NAME) {
2262                 return WERR_INVALID_FLAGS;
2263         }
2264         if (r->in.flags & DS_RETURN_DNS_NAME &&
2265             r->in.flags & DS_RETURN_FLAT_NAME) {
2266                 return WERR_INVALID_FLAGS;
2267         }
2268         if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
2269             r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
2270                 return WERR_INVALID_FLAGS;
2271         }
2272
2273         if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
2274             r->in.flags &
2275             (DS_DIRECTORY_SERVICE_REQUIRED |
2276              DS_DIRECTORY_SERVICE_PREFERRED |
2277              DS_GC_SERVER_REQUIRED |
2278              DS_PDC_REQUIRED |
2279              DS_KDC_REQUIRED)) {
2280                 return WERR_INVALID_FLAGS;
2281         }
2282
2283         if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
2284             r->in.site_name) {
2285                 return WERR_INVALID_FLAGS;
2286         }
2287
2288         /* Proof server site parameter "site_name" if it was specified */
2289         server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
2290         W_ERROR_HAVE_NO_MEMORY(server_site_name);
2291         if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
2292                                                      server_site_name) != 0)) {
2293                 return WERR_NO_SUCH_DOMAIN;
2294         }
2295
2296         guid_str = r->in.domain_guid != NULL ?
2297                  GUID_string(mem_ctx, r->in.domain_guid) : NULL;
2298
2299         status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
2300                                                  r->in.domain_name,
2301                                                  r->in.domain_name,
2302                                                  NULL, guid_str,
2303                                                  r->in.client_account,
2304                                                  r->in.mask, remote_addr,
2305                                                  NETLOGON_NT_VERSION_5EX_WITH_IP,
2306                                                  lp_ctx, &response, true);
2307         if (!NT_STATUS_IS_OK(status)) {
2308                 return ntstatus_to_werror(status);
2309         }
2310
2311         /*
2312          * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
2313          * (O) flag when the returned forest name is in DNS format. This is here
2314          * always the case (see below).
2315          */
2316         response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
2317
2318         if (r->in.flags & DS_RETURN_DNS_NAME) {
2319                 dc_name = response.data.nt5_ex.pdc_dns_name;
2320                 domain_name = response.data.nt5_ex.dns_domain;
2321                 /*
2322                  * According to MS-NRPC 2.2.1.2.1 we should set the
2323                  * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
2324                  * the returned information is in DNS form.
2325                  */
2326                 response.data.nt5_ex.server_type |=
2327                         DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
2328         } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
2329                 dc_name = response.data.nt5_ex.pdc_name;
2330                 domain_name = response.data.nt5_ex.domain_name;
2331         } else {
2332
2333                 /*
2334                  * TODO: autodetect what we need to return
2335                  * based on the given arguments
2336                  */
2337                 dc_name = response.data.nt5_ex.pdc_name;
2338                 domain_name = response.data.nt5_ex.domain_name;
2339         }
2340
2341         if (!dc_name || !dc_name[0]) {
2342                 return WERR_NO_SUCH_DOMAIN;
2343         }
2344
2345         if (!domain_name || !domain_name[0]) {
2346                 return WERR_NO_SUCH_DOMAIN;
2347         }
2348
2349         info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
2350         W_ERROR_HAVE_NO_MEMORY(info);
2351         info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
2352                         dc_name[0] != '\\'? "\\\\":"",
2353                         talloc_strdup(mem_ctx, dc_name));
2354         W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
2355
2356         pdc_ip = local_addr;
2357         if (pdc_ip == NULL) {
2358                 pdc_ip = "127.0.0.1";
2359         }
2360         info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
2361         W_ERROR_HAVE_NO_MEMORY(info->dc_address);
2362         info->dc_address_type  = DS_ADDRESS_TYPE_INET;
2363         info->domain_guid      = response.data.nt5_ex.domain_uuid;
2364         info->domain_name      = domain_name;
2365         info->forest_name      = response.data.nt5_ex.forest;
2366         info->dc_flags         = response.data.nt5_ex.server_type;
2367         if (r->in.flags & DS_RETURN_DNS_NAME) {
2368                 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
2369                  * returned if we are returning info->dc_unc containing a FQDN.
2370                  * This attribute is called DomainControllerName in the specs,
2371                  * it seems that we decide to return FQDN or netbios depending on
2372                  * DS_RETURN_DNS_NAME.
2373                  */
2374                 info->dc_flags |= DS_DNS_CONTROLLER;
2375         }
2376         info->dc_site_name     = response.data.nt5_ex.server_site;
2377         info->client_site_name = response.data.nt5_ex.client_site;
2378
2379         *r->out.info = info;
2380
2381         return WERR_OK;
2382 }
2383
2384 /*
2385   netr_DsRGetDCNameEx
2386 */
2387 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2388                                   struct netr_DsRGetDCNameEx *r)
2389 {
2390         struct netr_DsRGetDCNameEx2 r2;
2391         WERROR werr;
2392
2393         ZERO_STRUCT(r2);
2394
2395         r2.in.server_unc = r->in.server_unc;
2396         r2.in.client_account = NULL;
2397         r2.in.mask = 0;
2398         r2.in.domain_guid = r->in.domain_guid;
2399         r2.in.domain_name = r->in.domain_name;
2400         r2.in.site_name = r->in.site_name;
2401         r2.in.flags = r->in.flags;
2402         r2.out.info = r->out.info;
2403
2404         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2405
2406         return werr;
2407 }
2408
2409 /*
2410   netr_DsRGetDCName
2411 */
2412 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2413                                 struct netr_DsRGetDCName *r)
2414 {
2415         struct netr_DsRGetDCNameEx2 r2;
2416         WERROR werr;
2417
2418         ZERO_STRUCT(r2);
2419
2420         r2.in.server_unc = r->in.server_unc;
2421         r2.in.client_account = NULL;
2422         r2.in.mask = 0;
2423         r2.in.domain_name = r->in.domain_name;
2424         r2.in.domain_guid = r->in.domain_guid;
2425
2426         r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
2427         r2.in.flags = r->in.flags;
2428         r2.out.info = r->out.info;
2429
2430         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2431
2432         return werr;
2433 }
2434 /*
2435   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
2436 */
2437 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2438                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
2439 {
2440         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2441 }
2442
2443
2444 /*
2445   netr_NetrEnumerateTrustedDomainsEx
2446 */
2447 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2448                        struct netr_NetrEnumerateTrustedDomainsEx *r)
2449 {
2450         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2451 }
2452
2453
2454 /*
2455   netr_DsRAddressToSitenamesExW
2456 */
2457 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2458                                                    struct netr_DsRAddressToSitenamesExW *r)
2459 {
2460         struct ldb_context *sam_ctx;
2461         struct netr_DsRAddressToSitenamesExWCtr *ctr;
2462         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2463         sa_family_t sin_family;
2464         struct sockaddr_in *addr;
2465 #ifdef HAVE_IPV6
2466         struct sockaddr_in6 *addr6;
2467         char addr_str[INET6_ADDRSTRLEN];
2468 #else
2469         char addr_str[INET_ADDRSTRLEN];
2470 #endif
2471         char *subnet_name;
2472         const char *res;
2473         uint32_t i;
2474
2475         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2476                                 dce_call->conn->auth_state.session_info, 0);
2477         if (sam_ctx == NULL) {
2478                 return WERR_DS_UNAVAILABLE;
2479         }
2480
2481         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
2482         W_ERROR_HAVE_NO_MEMORY(ctr);
2483
2484         *r->out.ctr = ctr;
2485
2486         ctr->count = r->in.count;
2487         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2488         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2489         ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
2490         W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
2491
2492         for (i=0; i<ctr->count; i++) {
2493                 ctr->sitename[i].string = NULL;
2494                 ctr->subnetname[i].string = NULL;
2495
2496                 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2497                         continue;
2498                 }
2499                 /* The first two byte of the buffer are reserved for the
2500                  * "sin_family" but for now only the first one is used. */
2501                 sin_family = r->in.addresses[i].buffer[0];
2502
2503                 switch (sin_family) {
2504                 case AF_INET:
2505                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2506                                 continue;
2507                         }
2508                         addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2509                         res = inet_ntop(AF_INET, &addr->sin_addr,
2510                                         addr_str, sizeof(addr_str));
2511                         break;
2512 #ifdef HAVE_IPV6
2513                 case AF_INET6:
2514                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2515                                 continue;
2516                         }
2517                         addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2518                         res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2519                                         addr_str, sizeof(addr_str));
2520                         break;
2521 #endif
2522                 default:
2523                         continue;
2524                 }
2525
2526                 if (res == NULL) {
2527                         continue;
2528                 }
2529
2530                 ctr->sitename[i].string   = samdb_client_site_name(sam_ctx,
2531                                                                    mem_ctx,
2532                                                                    addr_str,
2533                                                                    &subnet_name);
2534                 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2535                 ctr->subnetname[i].string = subnet_name;
2536         }
2537
2538         return WERR_OK;
2539 }
2540
2541
2542 /*
2543   netr_DsRAddressToSitenamesW
2544 */
2545 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2546                        struct netr_DsRAddressToSitenamesW *r)
2547 {
2548         struct netr_DsRAddressToSitenamesExW r2;
2549         struct netr_DsRAddressToSitenamesWCtr *ctr;
2550         uint32_t i;
2551         WERROR werr;
2552
2553         ZERO_STRUCT(r2);
2554
2555         r2.in.server_name = r->in.server_name;
2556         r2.in.count = r->in.count;
2557         r2.in.addresses = r->in.addresses;
2558
2559         r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2560         W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2561
2562         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2563         W_ERROR_HAVE_NO_MEMORY(ctr);
2564
2565         *r->out.ctr = ctr;
2566
2567         ctr->count = r->in.count;
2568         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2569         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2570
2571         werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2572
2573         for (i=0; i<ctr->count; i++) {
2574                 ctr->sitename[i].string   = (*r2.out.ctr)->sitename[i].string;
2575         }
2576
2577         return werr;
2578 }
2579
2580
2581 /*
2582   netr_DsrGetDcSiteCoverageW
2583 */
2584 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2585                        struct netr_DsrGetDcSiteCoverageW *r)
2586 {
2587         struct ldb_context *sam_ctx;
2588         struct DcSitesCtr *ctr;
2589         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2590
2591         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2592                                 dce_call->conn->auth_state.session_info, 0);
2593         if (sam_ctx == NULL) {
2594                 return WERR_DS_UNAVAILABLE;
2595         }
2596
2597         ctr = talloc(mem_ctx, struct DcSitesCtr);
2598         W_ERROR_HAVE_NO_MEMORY(ctr);
2599
2600         *r->out.ctr = ctr;
2601
2602         /* For now only return our default site */
2603         ctr->num_sites = 1;
2604         ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2605         W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2606         ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2607         W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2608
2609         return WERR_OK;
2610 }
2611
2612
2613 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2614                                          struct ldb_context *sam_ctx,
2615                                          struct netr_DomainTrustList *trusts,
2616                                          uint32_t trust_flags)
2617 {
2618         struct ldb_dn *system_dn;
2619         struct ldb_message **dom_res = NULL;
2620         const char *trust_attrs[] = { "flatname", "trustPartner",
2621                                       "securityIdentifier", "trustDirection",
2622                                       "trustType", "trustAttributes", NULL };
2623         uint32_t n;
2624         int i;
2625         int ret;
2626
2627         if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2628                              NETR_TRUST_FLAG_OUTBOUND))) {
2629                 return WERR_INVALID_FLAGS;
2630         }
2631
2632         system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2633                                     ldb_get_default_basedn(sam_ctx),
2634                                     "(&(objectClass=container)(cn=System))");
2635         if (!system_dn) {
2636                 return WERR_GENERAL_FAILURE;
2637         }
2638
2639         ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2640                            &dom_res, trust_attrs,
2641                            "(objectclass=trustedDomain)");
2642
2643         for (i = 0; i < ret; i++) {
2644                 unsigned int trust_dir;
2645                 uint32_t flags = 0;
2646
2647                 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2648                                                       "trustDirection", 0);
2649
2650                 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2651                         flags |= NETR_TRUST_FLAG_INBOUND;
2652                 }
2653                 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2654                         flags |= NETR_TRUST_FLAG_OUTBOUND;
2655                 }
2656
2657                 if (!(flags & trust_flags)) {
2658                         /* this trust direction was not requested */
2659                         continue;
2660                 }
2661
2662                 n = trusts->count;
2663                 trusts->array = talloc_realloc(trusts, trusts->array,
2664                                                struct netr_DomainTrust,
2665                                                n + 1);
2666                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2667
2668                 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2669                 if (!trusts->array[n].netbios_name) {
2670                         DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2671                                   "without flatname\n", 
2672                                   ldb_dn_get_linearized(dom_res[i]->dn)));
2673                 }
2674
2675                 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2676
2677                 trusts->array[n].trust_flags = flags;
2678                 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2679                     !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2680                         /* TODO: find if we have parent in the list */
2681                         trusts->array[n].parent_index = 0;
2682                 }
2683
2684                 trusts->array[n].trust_type =
2685                                 ldb_msg_find_attr_as_uint(dom_res[i],
2686                                                   "trustType", 0);
2687                 trusts->array[n].trust_attributes =
2688                                 ldb_msg_find_attr_as_uint(dom_res[i],
2689                                                   "trustAttributes", 0);
2690
2691                 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
2692                     (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
2693                         struct dom_sid zero_sid;
2694                         ZERO_STRUCT(zero_sid);
2695                         trusts->array[n].sid =
2696                                 dom_sid_dup(trusts, &zero_sid);
2697                 } else {
2698                         trusts->array[n].sid =
2699                                 samdb_result_dom_sid(trusts, dom_res[i],
2700                                                      "securityIdentifier");
2701                 }
2702                 trusts->array[n].guid = GUID_zero();
2703
2704                 trusts->count = n + 1;
2705         }
2706
2707         talloc_free(dom_res);
2708         return WERR_OK;
2709 }
2710
2711 /*
2712   netr_DsrEnumerateDomainTrusts
2713 */
2714 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2715                                                    TALLOC_CTX *mem_ctx,
2716                                                    struct netr_DsrEnumerateDomainTrusts *r)
2717 {
2718         struct netr_DomainTrustList *trusts;
2719         struct ldb_context *sam_ctx;
2720         int ret;
2721         struct ldb_message **dom_res;
2722         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2723         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2724         const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2725         const char *p;
2726         WERROR werr;
2727
2728         if (r->in.trust_flags & 0xFFFFFE00) {
2729                 return WERR_INVALID_FLAGS;
2730         }
2731
2732         /* TODO: turn to hard check once we are sure this is 100% correct */
2733         if (!r->in.server_name) {
2734                 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2735                           "But received NULL!\n", dnsdomain));
2736         } else {
2737                 p = strchr(r->in.server_name, '.');
2738                 if (!p) {
2739                         DEBUG(3, ("Invalid domain! Expected name in domain "
2740                                   "[%s]. But received [%s]!\n",
2741                                   dnsdomain, r->in.server_name));
2742                         p = r->in.server_name;
2743                 } else {
2744                         p++;
2745                 }
2746                 if (strcasecmp(p, dnsdomain)) {
2747                         DEBUG(3, ("Invalid domain! Expected name in domain "
2748                                   "[%s]. But received [%s]!\n",
2749                                   dnsdomain, r->in.server_name));
2750                 }
2751         }
2752
2753         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2754         W_ERROR_HAVE_NO_MEMORY(trusts);
2755
2756         trusts->count = 0;
2757         r->out.trusts = trusts;
2758
2759         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2760                                 dce_call->conn->auth_state.session_info, 0);
2761         if (sam_ctx == NULL) {
2762                 return WERR_GENERAL_FAILURE;
2763         }
2764
2765         if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2766             (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2767
2768                 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2769                                                   trusts, r->in.trust_flags);
2770                 W_ERROR_NOT_OK_RETURN(werr);
2771         }
2772
2773         /* NOTE: we currently are always the root of the forest */
2774         if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2775                 uint32_t n = trusts->count;
2776
2777                 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2778                                       &dom_res, dom_attrs);
2779                 if (ret != 1) {
2780                         return WERR_GENERAL_FAILURE;
2781                 }
2782
2783                 trusts->count = n + 1;
2784                 trusts->array = talloc_realloc(trusts, trusts->array,
2785                                                struct netr_DomainTrust,
2786                                                trusts->count);
2787                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2788
2789                 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2790                 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2791                 trusts->array[n].trust_flags =
2792                         NETR_TRUST_FLAG_NATIVE |
2793                         NETR_TRUST_FLAG_TREEROOT |
2794                         NETR_TRUST_FLAG_IN_FOREST |
2795                         NETR_TRUST_FLAG_PRIMARY;
2796                 /* we are always the root domain for now */
2797                 trusts->array[n].parent_index = 0;
2798                 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
2799                 trusts->array[n].trust_attributes = 0;
2800                 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2801                                                             dom_res[0],
2802                                                             "objectSid");
2803                 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2804                                                           "objectGUID");
2805                 talloc_free(dom_res);
2806         }
2807
2808         return WERR_OK;
2809 }
2810
2811
2812 /*
2813   netr_DsrDeregisterDNSHostRecords
2814 */
2815 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2816                        struct netr_DsrDeregisterDNSHostRecords *r)
2817 {
2818         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2819 }
2820
2821
2822 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2823                        struct netr_ServerGetTrustInfo *r);
2824
2825 /*
2826   netr_ServerTrustPasswordsGet
2827 */
2828 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2829                        struct netr_ServerTrustPasswordsGet *r)
2830 {
2831         struct netr_ServerGetTrustInfo r2 = {};
2832         struct netr_TrustInfo *_ti = NULL;
2833         NTSTATUS status;
2834
2835         r2.in.server_name = r->in.server_name;
2836         r2.in.account_name = r->in.account_name;
2837         r2.in.secure_channel_type = r->in.secure_channel_type;
2838         r2.in.computer_name = r->in.computer_name;
2839         r2.in.credential = r->in.credential;
2840
2841         r2.out.return_authenticator = r->out.return_authenticator;
2842         r2.out.new_owf_password = r->out.new_owf_password;
2843         r2.out.old_owf_password = r->out.old_owf_password;
2844         r2.out.trust_info = &_ti;
2845
2846         status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
2847
2848         r->out.return_authenticator = r2.out.return_authenticator;
2849         r->out.new_owf_password = r2.out.new_owf_password;
2850         r->out.old_owf_password = r2.out.old_owf_password;
2851
2852         return status;
2853 }
2854
2855 /*
2856   netr_DsRGetForestTrustInformation
2857 */
2858 struct dcesrv_netr_DsRGetForestTrustInformation_state {
2859         struct dcesrv_call_state *dce_call;
2860         TALLOC_CTX *mem_ctx;
2861         struct netr_DsRGetForestTrustInformation *r;
2862 };
2863
2864 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
2865
2866 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2867                                                        TALLOC_CTX *mem_ctx,
2868                                                        struct netr_DsRGetForestTrustInformation *r)
2869 {
2870         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2871         struct dcesrv_connection *conn = dce_call->conn;
2872         struct auth_session_info *session_info = conn->auth_state.session_info;
2873         enum security_user_level security_level;
2874         struct ldb_context *sam_ctx = NULL;
2875         struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
2876         struct dcerpc_binding_handle *irpc_handle = NULL;
2877         struct tevent_req *subreq = NULL;
2878         struct ldb_dn *domain_dn = NULL;
2879         struct ldb_dn *forest_dn = NULL;
2880         int cmp;
2881         int forest_level;
2882
2883         security_level = security_session_user_level(session_info, NULL);
2884         if (security_level < SECURITY_USER) {
2885                 return WERR_ACCESS_DENIED;
2886         }
2887
2888         if (r->in.flags & 0xFFFFFFFE) {
2889                 return WERR_INVALID_FLAGS;
2890         }
2891
2892         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2893                                 dce_call->conn->auth_state.session_info, 0);
2894         if (sam_ctx == NULL) {
2895                 return WERR_GENERAL_FAILURE;
2896         }
2897
2898         domain_dn = ldb_get_default_basedn(sam_ctx);
2899         if (domain_dn == NULL) {
2900                 return WERR_GENERAL_FAILURE;
2901         }
2902
2903         forest_dn = ldb_get_root_basedn(sam_ctx);
2904         if (forest_dn == NULL) {
2905                 return WERR_GENERAL_FAILURE;
2906         }
2907
2908         cmp = ldb_dn_compare(domain_dn, forest_dn);
2909         if (cmp != 0) {
2910                 return WERR_NERR_ACFNOTLOADED;
2911         }
2912
2913         forest_level = dsdb_forest_functional_level(sam_ctx);
2914         if (forest_level < DS_DOMAIN_FUNCTION_2003) {
2915                 return WERR_INVALID_FUNCTION;
2916         }
2917
2918         if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2919                 if (!samdb_is_pdc(sam_ctx)) {
2920                         return WERR_NERR_NOTPRIMARY;
2921                 }
2922
2923                 if (r->in.trusted_domain_name == NULL) {
2924                         return WERR_INVALID_FLAGS;
2925                 }
2926         }
2927
2928         if (r->in.trusted_domain_name == NULL) {
2929                 NTSTATUS status;
2930
2931                 /*
2932                  * information about our own domain
2933                  */
2934                 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
2935                                                 r->out.forest_trust_info);
2936                 if (!NT_STATUS_IS_OK(status)) {
2937                         return ntstatus_to_werror(status);
2938                 }
2939
2940                 return WERR_OK;
2941         }
2942
2943         /*
2944          * Forward the request to winbindd
2945          */
2946
2947         state = talloc_zero(mem_ctx,
2948                         struct dcesrv_netr_DsRGetForestTrustInformation_state);
2949         if (state == NULL) {
2950                 return WERR_NOMEM;
2951         }
2952         state->dce_call = dce_call;
2953         state->mem_ctx = mem_ctx;
2954         state->r = r;
2955
2956         irpc_handle = irpc_binding_handle_by_name(state,
2957                                                   state->dce_call->msg_ctx,
2958                                                   "winbind_server",
2959                                                   &ndr_table_winbind);
2960         if (irpc_handle == NULL) {
2961                 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
2962                 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2963                 return WERR_SERVICE_NOT_FOUND;
2964         }
2965
2966         /*
2967          * 60 seconds timeout should be enough
2968          */
2969         dcerpc_binding_handle_set_timeout(irpc_handle, 60);
2970
2971         subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
2972                                                 state->dce_call->event_ctx,
2973                                                 irpc_handle,
2974                                                 r->in.trusted_domain_name,
2975                                                 r->in.flags,
2976                                                 r->out.forest_trust_info);
2977         if (subreq == NULL) {
2978                 return WERR_NOMEM;
2979         }
2980         state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2981         tevent_req_set_callback(subreq,
2982                                 dcesrv_netr_DsRGetForestTrustInformation_done,
2983                                 state);
2984
2985         return WERR_OK;
2986 }
2987
2988 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
2989 {
2990         struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
2991                 tevent_req_callback_data(subreq,
2992                 struct dcesrv_netr_DsRGetForestTrustInformation_state);
2993         NTSTATUS status;
2994
2995         status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
2996                                                         state->mem_ctx,
2997                                                         &state->r->out.result);
2998         TALLOC_FREE(subreq);
2999         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3000                 state->r->out.result = WERR_TIMEOUT;
3001         } else if (!NT_STATUS_IS_OK(status)) {
3002                 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3003                 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
3004                          nt_errstr(status)));
3005         }
3006
3007         status = dcesrv_reply(state->dce_call);
3008         if (!NT_STATUS_IS_OK(status)) {
3009                 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3010         }
3011 }
3012
3013 /*
3014   netr_GetForestTrustInformation
3015 */
3016 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
3017                                                       TALLOC_CTX *mem_ctx,
3018                                                       struct netr_GetForestTrustInformation *r)
3019 {
3020         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3021         struct netlogon_creds_CredentialState *creds = NULL;
3022         struct ldb_context *sam_ctx = NULL;
3023         struct ldb_dn *domain_dn = NULL;
3024         struct ldb_dn *forest_dn = NULL;
3025         int cmp;
3026         int forest_level;
3027         NTSTATUS status;
3028
3029         status = dcesrv_netr_creds_server_step_check(dce_call,
3030                                                      mem_ctx,
3031                                                      r->in.computer_name,
3032                                                      r->in.credential,
3033                                                      r->out.return_authenticator,
3034                                                      &creds);
3035         if (!NT_STATUS_IS_OK(status)) {
3036                 return status;
3037         }
3038
3039         if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
3040             (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
3041                 return NT_STATUS_NOT_IMPLEMENTED;
3042         }
3043
3044         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3045                                 dce_call->conn->auth_state.session_info, 0);
3046         if (sam_ctx == NULL) {
3047                 return NT_STATUS_INTERNAL_ERROR;
3048         }
3049
3050         /* TODO: check r->in.server_name is our name */
3051
3052         domain_dn = ldb_get_default_basedn(sam_ctx);
3053         if (domain_dn == NULL) {
3054                 return NT_STATUS_INTERNAL_ERROR;
3055         }
3056
3057         forest_dn = ldb_get_root_basedn(sam_ctx);
3058         if (forest_dn == NULL) {
3059                 return NT_STATUS_INTERNAL_ERROR;
3060         }
3061
3062         cmp = ldb_dn_compare(domain_dn, forest_dn);
3063         if (cmp != 0) {
3064                 return NT_STATUS_INVALID_DOMAIN_STATE;
3065         }
3066
3067         forest_level = dsdb_forest_functional_level(sam_ctx);
3068         if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3069                 return NT_STATUS_INVALID_DOMAIN_STATE;
3070         }
3071
3072         status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3073                                              r->out.forest_trust_info);
3074         if (!NT_STATUS_IS_OK(status)) {
3075                 return status;
3076         }
3077
3078         return NT_STATUS_OK;
3079 }
3080
3081
3082 /*
3083   netr_ServerGetTrustInfo
3084 */
3085 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3086                        struct netr_ServerGetTrustInfo *r)
3087 {
3088         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3089         struct netlogon_creds_CredentialState *creds = NULL;
3090         struct ldb_context *sam_ctx = NULL;
3091         const char * const attrs[] = {
3092                 "unicodePwd",
3093                 "sAMAccountName",
3094                 "userAccountControl",
3095                 NULL
3096         };
3097         struct ldb_message **res = NULL;
3098         struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
3099         NTSTATUS nt_status;
3100         int ret;
3101         const char *asid = NULL;
3102         uint32_t uac = 0;
3103         const char *aname = NULL;
3104         struct ldb_message *tdo_msg = NULL;
3105         const char * const tdo_attrs[] = {
3106                 "trustAuthIncoming",
3107                 "trustAttributes",
3108                 NULL
3109         };
3110         struct netr_TrustInfo *trust_info = NULL;
3111
3112         ZERO_STRUCTP(r->out.new_owf_password);
3113         ZERO_STRUCTP(r->out.old_owf_password);
3114
3115         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3116                                                         mem_ctx,
3117                                                         r->in.computer_name,
3118                                                         r->in.credential,
3119                                                         r->out.return_authenticator,
3120                                                         &creds);
3121         if (!NT_STATUS_IS_OK(nt_status)) {
3122                 return nt_status;
3123         }
3124
3125         /* TODO: check r->in.server_name is our name */
3126
3127         if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
3128                 return NT_STATUS_INVALID_PARAMETER;
3129         }
3130
3131         if (r->in.secure_channel_type != creds->secure_channel_type) {
3132                 return NT_STATUS_INVALID_PARAMETER;
3133         }
3134
3135         if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
3136                 return NT_STATUS_INVALID_PARAMETER;
3137         }
3138
3139         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
3140                                 lp_ctx, system_session(lp_ctx), 0);
3141         if (sam_ctx == NULL) {
3142                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
3143         }
3144
3145         asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
3146         if (asid == NULL) {
3147                 return NT_STATUS_NO_MEMORY;
3148         }
3149
3150         ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
3151                            "(&(objectClass=user)(objectSid=%s))",
3152                            asid);
3153         if (ret != 1) {
3154                 return NT_STATUS_ACCOUNT_DISABLED;
3155         }
3156
3157         switch (creds->secure_channel_type) {
3158         case SEC_CHAN_DNS_DOMAIN:
3159         case SEC_CHAN_DOMAIN:
3160                 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
3161
3162                 if (uac & UF_ACCOUNTDISABLE) {
3163                         return NT_STATUS_ACCOUNT_DISABLED;
3164                 }
3165
3166                 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
3167                         return NT_STATUS_ACCOUNT_DISABLED;
3168                 }
3169
3170                 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
3171                 if (aname == NULL) {
3172                         return NT_STATUS_ACCOUNT_DISABLED;
3173                 }
3174
3175                 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
3176                                                 SEC_CHAN_DOMAIN, aname,
3177                                                 tdo_attrs, mem_ctx, &tdo_msg);
3178                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3179                         return NT_STATUS_ACCOUNT_DISABLED;
3180                 }
3181                 if (!NT_STATUS_IS_OK(nt_status)) {
3182                         return nt_status;
3183                 }
3184
3185                 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
3186                                                               &curNtHash,
3187                                                               &prevNtHash);
3188                 if (!NT_STATUS_IS_OK(nt_status)) {
3189                         return nt_status;
3190                 }
3191
3192                 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
3193                 if (trust_info == NULL) {
3194                         return NT_STATUS_NO_MEMORY;
3195                 }
3196
3197                 trust_info->count = 1;
3198                 trust_info->data = talloc_array(trust_info, uint32_t,
3199                                                 trust_info->count);
3200                 if (trust_info->data == NULL) {
3201                         return NT_STATUS_NO_MEMORY;
3202                 }
3203
3204                 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
3205                                                         "trustAttributes",
3206                                                         0);
3207                 break;
3208
3209         default:
3210                 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
3211                                                               res[0],
3212                                                               NULL, &curNtHash);
3213                 if (!NT_STATUS_IS_OK(nt_status)) {
3214                         return nt_status;
3215                 }
3216
3217                 prevNtHash = talloc(mem_ctx, struct samr_Password);
3218                 if (prevNtHash == NULL) {
3219                         return NT_STATUS_NO_MEMORY;
3220                 }
3221
3222                 E_md4hash("", prevNtHash->hash);
3223                 break;
3224         }
3225
3226         if (curNtHash != NULL) {
3227                 *r->out.new_owf_password = *curNtHash;
3228                 netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
3229         }
3230         if (prevNtHash != NULL) {
3231                 *r->out.old_owf_password = *prevNtHash;
3232                 netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
3233         }
3234
3235         if (trust_info != NULL) {
3236                 *r->out.trust_info = trust_info;
3237         }
3238
3239         return NT_STATUS_OK;
3240 }
3241
3242 /*
3243   netr_Unused47
3244 */
3245 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3246                                      struct netr_Unused47 *r)
3247 {
3248         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3249 }
3250
3251
3252 struct netr_dnsupdate_RODC_state {
3253         struct dcesrv_call_state *dce_call;
3254         struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
3255         struct dnsupdate_RODC *r2;
3256 };
3257
3258 /*
3259   called when the forwarded RODC dns update request is finished
3260  */
3261 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
3262 {
3263         struct netr_dnsupdate_RODC_state *st =
3264                 tevent_req_callback_data(subreq,
3265                                          struct netr_dnsupdate_RODC_state);
3266         NTSTATUS status;
3267
3268         status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
3269         TALLOC_FREE(subreq);
3270         if (!NT_STATUS_IS_OK(status)) {
3271                 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
3272                 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3273         }
3274
3275         st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
3276
3277         status = dcesrv_reply(st->dce_call);
3278         if (!NT_STATUS_IS_OK(status)) {
3279                 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3280         }
3281 }
3282
3283 /*
3284   netr_DsrUpdateReadOnlyServerDnsRecords
3285 */
3286 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
3287                                                               TALLOC_CTX *mem_ctx,
3288                                                               struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
3289 {
3290         struct netlogon_creds_CredentialState *creds;
3291         NTSTATUS nt_status;
3292         struct dcerpc_binding_handle *binding_handle;
3293         struct netr_dnsupdate_RODC_state *st;
3294         struct tevent_req *subreq;
3295
3296         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3297                                                         mem_ctx,
3298                                                         r->in.computer_name,
3299                                                         r->in.credential,
3300                                                         r->out.return_authenticator,
3301                                                         &creds);
3302         NT_STATUS_NOT_OK_RETURN(nt_status);
3303
3304         if (creds->secure_channel_type != SEC_CHAN_RODC) {
3305                 return NT_STATUS_ACCESS_DENIED;
3306         }
3307
3308         st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
3309         NT_STATUS_HAVE_NO_MEMORY(st);
3310
3311         st->dce_call = dce_call;
3312         st->r = r;
3313         st->r2 = talloc_zero(st, struct dnsupdate_RODC);
3314         NT_STATUS_HAVE_NO_MEMORY(st->r2);
3315
3316         st->r2->in.dom_sid = creds->sid;
3317         st->r2->in.site_name = r->in.site_name;
3318         st->r2->in.dns_ttl = r->in.dns_ttl;
3319         st->r2->in.dns_names = r->in.dns_names;
3320         st->r2->out.dns_names = r->out.dns_names;
3321
3322         binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
3323                                                      "dnsupdate", &ndr_table_irpc);
3324         if (binding_handle == NULL) {
3325                 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
3326                 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3327                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3328         }
3329
3330         /* forward the call */
3331         subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
3332                                               binding_handle, st->r2);
3333         NT_STATUS_HAVE_NO_MEMORY(subreq);
3334
3335         dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3336
3337         /* setup the callback */
3338         tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
3339
3340         return NT_STATUS_OK;
3341 }
3342
3343
3344 /* include the generated boilerplate */
3345 #include "librpc/gen_ndr/ndr_netlogon_s.c"