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