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