auth: Add functionality to log client and server policy information
[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 "rpc_server/common/common.h"
27 #include "auth/auth.h"
28 #include "auth/auth_sam_reply.h"
29 #include "dsdb/samdb/samdb.h"
30 #include "../lib/util/util_ldb.h"
31 #include "../libcli/auth/schannel.h"
32 #include "libcli/security/security.h"
33 #include "param/param.h"
34 #include "lib/messaging/irpc.h"
35 #include "librpc/gen_ndr/ndr_irpc_c.h"
36 #include "../libcli/ldap/ldap_ndr.h"
37 #include "dsdb/samdb/ldb_modules/util.h"
38 #include "lib/tsocket/tsocket.h"
39 #include "librpc/gen_ndr/ndr_netlogon.h"
40 #include "librpc/gen_ndr/ndr_lsa.h"
41 #include "librpc/gen_ndr/ndr_samr.h"
42 #include "librpc/gen_ndr/ndr_irpc.h"
43 #include "librpc/gen_ndr/ndr_winbind.h"
44 #include "librpc/gen_ndr/ndr_winbind_c.h"
45 #include "librpc/rpc/server/netlogon/schannel_util.h"
46 #include "lib/socket/netif.h"
47 #include "lib/util/util_str_escape.h"
48 #include "lib/param/loadparm.h"
49
50 #define DCESRV_INTERFACE_NETLOGON_BIND(context, iface) \
51        dcesrv_interface_netlogon_bind(context, iface)
52
53 #undef strcasecmp
54
55 /*
56  * This #define allows the netlogon interface to accept invalid
57  * association groups, because association groups are to coordinate
58  * handles, and handles are not used in NETLOGON. This in turn avoids
59  * the need to coordinate these across multiple possible NETLOGON
60  * processes
61  */
62 #define DCESRV_INTERFACE_NETLOGON_FLAGS DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED
63
64 static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_connection_context *context,
65                                                const struct dcesrv_interface *iface)
66 {
67         struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx;
68         bool global_allow_nt4_crypto = lpcfg_allow_nt4_crypto(lp_ctx);
69         bool global_reject_md5_client = lpcfg_reject_md5_clients(lp_ctx);
70         int schannel = lpcfg_server_schannel(lp_ctx);
71         bool schannel_global_required = (schannel == true);
72         bool global_require_seal = lpcfg_server_schannel_require_seal(lp_ctx);
73         static bool warned_global_nt4_once = false;
74         static bool warned_global_md5_once = false;
75         static bool warned_global_schannel_once = false;
76         static bool warned_global_seal_once = false;
77
78         if (global_allow_nt4_crypto && !warned_global_nt4_once) {
79                 /*
80                  * We want admins to notice their misconfiguration!
81                  */
82                 D_ERR("CVE-2022-38023 (and others): "
83                       "Please configure 'allow nt4 crypto = no' (the default), "
84                       "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n");
85                 warned_global_nt4_once = true;
86         }
87
88         if (!global_reject_md5_client && !warned_global_md5_once) {
89                 /*
90                  * We want admins to notice their misconfiguration!
91                  */
92                 D_ERR("CVE-2022-38023: "
93                       "Please configure 'reject md5 clients = yes' (the default), "
94                       "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n");
95                 warned_global_md5_once = true;
96         }
97
98         if (!schannel_global_required && !warned_global_schannel_once) {
99                 /*
100                  * We want admins to notice their misconfiguration!
101                  */
102                 D_ERR("CVE-2020-1472(ZeroLogon): "
103                       "Please configure 'server schannel = yes' (the default), "
104                       "See https://bugzilla.samba.org/show_bug.cgi?id=14497\n");
105                 warned_global_schannel_once = true;
106         }
107
108         if (!global_require_seal && !warned_global_seal_once) {
109                 /*
110                  * We want admins to notice their misconfiguration!
111                  */
112                 D_ERR("CVE-2022-38023 (and others): "
113                       "Please configure 'server schannel require seal = yes' (the default), "
114                       "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n");
115                 warned_global_seal_once = true;
116         }
117
118         return dcesrv_interface_bind_reject_connect(context, iface);
119 }
120
121 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
122                                         struct netr_ServerReqChallenge *r)
123 {
124         struct netlogon_server_pipe_state *pipe_state = NULL;
125         NTSTATUS ntstatus;
126
127         ZERO_STRUCTP(r->out.return_credentials);
128
129         pipe_state = dcesrv_iface_state_find_conn(dce_call,
130                         NETLOGON_SERVER_PIPE_STATE_MAGIC,
131                         struct netlogon_server_pipe_state);
132         TALLOC_FREE(pipe_state);
133
134         pipe_state = talloc_zero(dce_call,
135                                  struct netlogon_server_pipe_state);
136         if (pipe_state == NULL) {
137                 return NT_STATUS_NO_MEMORY;
138         }
139
140         pipe_state->client_challenge = *r->in.credentials;
141
142         netlogon_creds_random_challenge(&pipe_state->server_challenge);
143
144         *r->out.return_credentials = pipe_state->server_challenge;
145
146         ntstatus = dcesrv_iface_state_store_conn(dce_call,
147                         NETLOGON_SERVER_PIPE_STATE_MAGIC,
148                         pipe_state);
149         if (!NT_STATUS_IS_OK(ntstatus)) {
150                 return ntstatus;
151         }
152
153         ntstatus = schannel_save_challenge(dce_call->conn->dce_ctx->lp_ctx,
154                                            &pipe_state->client_challenge,
155                                            &pipe_state->server_challenge,
156                                            r->in.computer_name);
157         if (!NT_STATUS_IS_OK(ntstatus)) {
158                 TALLOC_FREE(pipe_state);
159                 return ntstatus;
160         }
161
162         return NT_STATUS_OK;
163 }
164
165 static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade(
166         struct dcesrv_call_state *dce_call,
167         struct netr_ServerAuthenticate3 *r,
168         struct netlogon_server_pipe_state *pipe_state,
169         uint32_t negotiate_flags,
170         const char *trust_account_in_db,
171         NTSTATUS orig_status)
172 {
173         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
174         bool global_allow_nt4_crypto = lpcfg_allow_nt4_crypto(lp_ctx);
175         bool account_allow_nt4_crypto = global_allow_nt4_crypto;
176         const char *explicit_nt4_opt = NULL;
177         bool global_reject_md5_client = lpcfg_reject_md5_clients(lp_ctx);
178         bool account_reject_md5_client = global_reject_md5_client;
179         const char *explicit_md5_opt = NULL;
180         bool reject_des_client;
181         bool allow_nt4_crypto;
182         bool reject_md5_client;
183         bool need_des = true;
184         bool need_md5 = true;
185         int CVE_2022_38023_warn_level = lpcfg_parm_int(lp_ctx, NULL,
186                         "CVE_2022_38023", "warn_about_unused_debug_level", DBGLVL_ERR);
187         int CVE_2022_38023_error_level = lpcfg_parm_int(lp_ctx, NULL,
188                         "CVE_2022_38023", "error_debug_level", DBGLVL_ERR);
189
190         /*
191          * We don't use lpcfg_parm_bool(), as we
192          * need the explicit_opt pointer in order to
193          * adjust the debug messages.
194          */
195
196         if (trust_account_in_db != NULL) {
197                 explicit_nt4_opt = lpcfg_get_parametric(lp_ctx,
198                                                         NULL,
199                                                         "allow nt4 crypto",
200                                                         trust_account_in_db);
201         }
202         if (explicit_nt4_opt != NULL) {
203                 account_allow_nt4_crypto = lp_bool(explicit_nt4_opt);
204         }
205         allow_nt4_crypto = account_allow_nt4_crypto;
206         if (trust_account_in_db != NULL) {
207                 explicit_md5_opt = lpcfg_get_parametric(lp_ctx,
208                                                         NULL,
209                                                         "server reject md5 schannel",
210                                                         trust_account_in_db);
211         }
212         if (explicit_md5_opt != NULL) {
213                 account_reject_md5_client = lp_bool(explicit_md5_opt);
214         }
215         reject_md5_client = account_reject_md5_client;
216
217         reject_des_client = !allow_nt4_crypto;
218
219         /*
220          * If weak cryto is disabled, do not announce that we support RC4.
221          */
222         if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) {
223                 /* Without RC4 and DES we require AES */
224                 reject_des_client = true;
225                 reject_md5_client = true;
226         }
227
228         if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
229                 need_des = false;
230                 reject_des_client = false;
231         }
232
233         if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
234                 need_des = false;
235                 need_md5 = false;
236                 reject_des_client = false;
237                 reject_md5_client = false;
238         }
239
240         if (reject_des_client || reject_md5_client) {
241                 TALLOC_CTX *frame = talloc_stackframe();
242
243                 if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) {
244                         if (CVE_2022_38023_error_level < DBGLVL_NOTICE) {
245                                 CVE_2022_38023_error_level = DBGLVL_NOTICE;
246                         }
247                         DEBUG(CVE_2022_38023_error_level, (
248                               "CVE-2022-38023: "
249                               "client_account[%s] computer_name[%s] "
250                               "schannel_type[%u] "
251                               "client_negotiate_flags[0x%x] "
252                               "%s%s%s "
253                               "NT_STATUS_DOWNGRADE_DETECTED "
254                               "WEAK_CRYPTO_DISALLOWED\n",
255                               log_escape(frame, r->in.account_name),
256                               log_escape(frame, r->in.computer_name),
257                               r->in.secure_channel_type,
258                               (unsigned)*r->in.negotiate_flags,
259                               trust_account_in_db ? "real_account[" : "",
260                               trust_account_in_db ? trust_account_in_db : "",
261                               trust_account_in_db ? "]" : ""));
262                         goto return_downgrade;
263                 }
264
265                 DEBUG(CVE_2022_38023_error_level, (
266                       "CVE-2022-38023: "
267                       "client_account[%s] computer_name[%s] "
268                       "schannel_type[%u] "
269                       "client_negotiate_flags[0x%x] "
270                       "%s%s%s "
271                       "NT_STATUS_DOWNGRADE_DETECTED "
272                       "reject_des[%u] reject_md5[%u]\n",
273                       log_escape(frame, r->in.account_name),
274                       log_escape(frame, r->in.computer_name),
275                       r->in.secure_channel_type,
276                       (unsigned)*r->in.negotiate_flags,
277                       trust_account_in_db ? "real_account[" : "",
278                       trust_account_in_db ? trust_account_in_db : "",
279                       trust_account_in_db ? "]" : "",
280                       reject_des_client,
281                       reject_md5_client));
282                 if (trust_account_in_db == NULL) {
283                         goto return_downgrade;
284                 }
285
286                 if (reject_md5_client && explicit_md5_opt == NULL) {
287                         DEBUG(CVE_2022_38023_error_level, (
288                               "CVE-2022-38023: Check if option "
289                               "'server reject md5 schannel:%s = no' "
290                               "might be needed for a legacy client.\n",
291                               trust_account_in_db));
292                 }
293                 if (reject_des_client && explicit_nt4_opt == NULL) {
294                         DEBUG(CVE_2022_38023_error_level, (
295                               "CVE-2022-38023: Check if option "
296                               "'allow nt4 crypto:%s = yes' "
297                               "might be needed for a legacy client.\n",
298                               trust_account_in_db));
299                 }
300
301 return_downgrade:
302                 /*
303                  * Here we match Windows 2012 and return no flags.
304                  */
305                 *r->out.negotiate_flags = 0;
306                 TALLOC_FREE(frame);
307                 return NT_STATUS_DOWNGRADE_DETECTED;
308         }
309
310         /*
311          * This talloc_free is important to prevent re-use of the
312          * challenge.  We have to delay it this far due to NETApp
313          * servers per:
314          * https://bugzilla.samba.org/show_bug.cgi?id=11291
315          */
316         TALLOC_FREE(pipe_state);
317
318         /*
319          * At this point we must also cleanup the TDB cache
320          * entry, if we fail the client needs to call
321          * netr_ServerReqChallenge again.
322          *
323          * Note: this handles a non existing record just fine,
324          * the r->in.computer_name might not be the one used
325          * in netr_ServerReqChallenge(), but we are trying to
326          * just tidy up the normal case to prevent re-use.
327          */
328         schannel_delete_challenge(dce_call->conn->dce_ctx->lp_ctx,
329                                   r->in.computer_name);
330
331         /*
332          * According to Microsoft (see bugid #6099)
333          * Windows 7 looks at the negotiate_flags
334          * returned in this structure *even if the
335          * call fails with access denied!
336          */
337         *r->out.negotiate_flags = negotiate_flags;
338
339         if (!NT_STATUS_IS_OK(orig_status) || trust_account_in_db == NULL) {
340                 return orig_status;
341         }
342
343         if (global_reject_md5_client && account_reject_md5_client && explicit_md5_opt) {
344                 D_INFO("CVE-2022-38023: Check if option "
345                        "'server reject md5 schannel:%s = yes' not needed!?\n",
346                        trust_account_in_db);
347         } else if (need_md5 && !account_reject_md5_client && explicit_md5_opt) {
348                 D_INFO("CVE-2022-38023: Check if option "
349                          "'server reject md5 schannel:%s = no' "
350                          "still needed for a legacy client.\n",
351                          trust_account_in_db);
352         } else if (need_md5 && explicit_md5_opt == NULL) {
353                 DEBUG(CVE_2022_38023_error_level, (
354                       "CVE-2022-38023: Check if option "
355                       "'server reject md5 schannel:%s = no' "
356                       "might be needed for a legacy client.\n",
357                       trust_account_in_db));
358         } else if (!account_reject_md5_client && explicit_md5_opt) {
359                 DEBUG(CVE_2022_38023_warn_level, (
360                       "CVE-2022-38023: Check if option "
361                       "'server reject md5 schannel:%s = no' not needed!?\n",
362                       trust_account_in_db));
363         }
364
365         if (!global_allow_nt4_crypto && !account_allow_nt4_crypto && explicit_nt4_opt) {
366                 D_INFO("CVE-2022-38023: Check if option "
367                        "'allow nt4 crypto:%s = no' not needed!?\n",
368                        trust_account_in_db);
369         } else if (need_des && account_allow_nt4_crypto && explicit_nt4_opt) {
370                 D_INFO("CVE-2022-38023: Check if option "
371                          "'allow nt4 crypto:%s = yes' "
372                          "still needed for a legacy client.\n",
373                          trust_account_in_db);
374         } else if (need_des && explicit_nt4_opt == NULL) {
375                 DEBUG(CVE_2022_38023_error_level, (
376                       "CVE-2022-38023: Check if option "
377                       "'allow nt4 crypto:%s = yes' "
378                       "might be needed for a legacy client.\n",
379                       trust_account_in_db));
380         } else if (account_allow_nt4_crypto && explicit_nt4_opt) {
381                 DEBUG(CVE_2022_38023_warn_level, (
382                       "CVE-2022-38023: Check if option "
383                       "'allow nt4 crypto:%s = yes' not needed!?\n",
384                       trust_account_in_db));
385         }
386
387         return orig_status;
388 }
389
390 /*
391  * Do the actual processing of a netr_ServerAuthenticate3 message.
392  * called from dcesrv_netr_ServerAuthenticate3, which handles the logging.
393  */
394 static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
395         struct dcesrv_call_state *dce_call,
396         TALLOC_CTX *mem_ctx,
397         struct netr_ServerAuthenticate3 *r,
398         const char **trust_account_for_search,
399         const char **trust_account_in_db,
400         struct dom_sid **sid)
401 {
402         struct netlogon_server_pipe_state *pipe_state = NULL;
403         bool challenge_valid = false;
404         struct netlogon_server_pipe_state challenge;
405         struct netlogon_creds_CredentialState *creds;
406         struct ldb_context *sam_ctx;
407         struct samr_Password *curNtHash = NULL;
408         struct samr_Password *prevNtHash = NULL;
409         uint32_t user_account_control;
410         int num_records;
411         struct ldb_message **msgs;
412         NTSTATUS nt_status;
413         const char *attrs[] = {"unicodePwd", "userAccountControl",
414                                "objectSid", "samAccountName", NULL};
415         uint32_t server_flags = 0;
416         uint32_t negotiate_flags = 0;
417
418         ZERO_STRUCTP(r->out.return_credentials);
419         *r->out.negotiate_flags = 0;
420         *r->out.rid = 0;
421
422         pipe_state = dcesrv_iface_state_find_conn(dce_call,
423                         NETLOGON_SERVER_PIPE_STATE_MAGIC,
424                         struct netlogon_server_pipe_state);
425         if (pipe_state != NULL) {
426                 /*
427                  * If we had a challenge remembered on the connection
428                  * consider this for usage. This can't be cleanup
429                  * by other clients.
430                  *
431                  * This is the default code path for typical clients
432                  * which call netr_ServerReqChallenge() and
433                  * netr_ServerAuthenticate3() on the same dcerpc connection.
434                  */
435                 challenge = *pipe_state;
436
437                 challenge_valid = true;
438
439         } else {
440                 NTSTATUS ntstatus;
441
442                 /*
443                  * Fallback and try to get the challenge from
444                  * the global cache.
445                  *
446                  * If too many clients are using this code path,
447                  * they may destroy their cache entries as the
448                  * TDB has a fixed size limited via a lossy hash
449                  *
450                  * The TDB used is the schannel store, which is
451                  * initialised at startup.
452                  *
453                  * NOTE: The challenge is deleted from the DB as soon as it is
454                  * fetched, to prevent reuse.
455                  *
456                  */
457
458                 ntstatus = schannel_get_challenge(dce_call->conn->dce_ctx->lp_ctx,
459                                                   &challenge.client_challenge,
460                                                   &challenge.server_challenge,
461                                                   r->in.computer_name);
462
463                 if (!NT_STATUS_IS_OK(ntstatus)) {
464                         ZERO_STRUCT(challenge);
465                 } else {
466                         challenge_valid = true;
467                 }
468         }
469
470         server_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
471                        NETLOGON_NEG_PERSISTENT_SAMREPL |
472                        NETLOGON_NEG_ARCFOUR |
473                        NETLOGON_NEG_PROMOTION_COUNT |
474                        NETLOGON_NEG_CHANGELOG_BDC |
475                        NETLOGON_NEG_FULL_SYNC_REPL |
476                        NETLOGON_NEG_MULTIPLE_SIDS |
477                        NETLOGON_NEG_REDO |
478                        NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
479                        NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
480                        NETLOGON_NEG_GENERIC_PASSTHROUGH |
481                        NETLOGON_NEG_CONCURRENT_RPC |
482                        NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
483                        NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
484                        NETLOGON_NEG_STRONG_KEYS |
485                        NETLOGON_NEG_TRANSITIVE_TRUSTS |
486                        NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
487                        NETLOGON_NEG_PASSWORD_SET2 |
488                        NETLOGON_NEG_GETDOMAININFO |
489                        NETLOGON_NEG_CROSS_FOREST_TRUSTS |
490                        NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
491                        NETLOGON_NEG_RODC_PASSTHROUGH |
492                        NETLOGON_NEG_SUPPORTS_AES |
493                        NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
494                        NETLOGON_NEG_AUTHENTICATED_RPC;
495
496         /*
497          * If weak cryto is disabled, do not announce that we support RC4.
498          */
499         if (lpcfg_weak_crypto(dce_call->conn->dce_ctx->lp_ctx) ==
500             SAMBA_WEAK_CRYPTO_DISALLOWED) {
501                 server_flags &= ~NETLOGON_NEG_ARCFOUR;
502         }
503
504         negotiate_flags = *r->in.negotiate_flags & server_flags;
505
506         switch (r->in.secure_channel_type) {
507         case SEC_CHAN_WKSTA:
508         case SEC_CHAN_DNS_DOMAIN:
509         case SEC_CHAN_DOMAIN:
510         case SEC_CHAN_BDC:
511         case SEC_CHAN_RODC:
512                 break;
513         case SEC_CHAN_NULL:
514                 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
515                                 dce_call, r, pipe_state, negotiate_flags,
516                                 NULL, /* trust_account_in_db */
517                                 NT_STATUS_INVALID_PARAMETER);
518         default:
519                 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
520                           r->in.secure_channel_type));
521                 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
522                                 dce_call, r, pipe_state, negotiate_flags,
523                                 NULL, /* trust_account_in_db */
524                                 NT_STATUS_INVALID_PARAMETER);
525         }
526
527         sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
528         if (sam_ctx == NULL) {
529                 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
530                                 dce_call, r, pipe_state, negotiate_flags,
531                                 NULL, /* trust_account_in_db */
532                                 NT_STATUS_INVALID_SYSTEM_SERVICE);
533         }
534
535         if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
536             r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN)
537         {
538                 struct ldb_message *tdo_msg = NULL;
539                 const char * const tdo_attrs[] = {
540                         "trustAuthIncoming",
541                         "trustAttributes",
542                         "flatName",
543                         NULL
544                 };
545                 char *encoded_name = NULL;
546                 size_t len;
547                 const char *flatname = NULL;
548                 char trailer = '$';
549                 bool require_trailer = true;
550                 const char *netbios = NULL;
551                 const char *dns = NULL;
552
553                 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
554                         trailer = '.';
555                         require_trailer = false;
556                 }
557
558                 encoded_name = ldb_binary_encode_string(mem_ctx,
559                                                         r->in.account_name);
560                 if (encoded_name == NULL) {
561                         return dcesrv_netr_ServerAuthenticate3_check_downgrade(
562                                 dce_call, r, pipe_state, negotiate_flags,
563                                 NULL, /* trust_account_in_db */
564                                 NT_STATUS_NO_MEMORY);
565                 }
566
567                 len = strlen(encoded_name);
568                 if (len < 2) {
569                         return dcesrv_netr_ServerAuthenticate3_check_downgrade(
570                                 dce_call, r, pipe_state, negotiate_flags,
571                                 NULL, /* trust_account_in_db */
572                                 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
573                 }
574
575                 if (require_trailer && encoded_name[len - 1] != trailer) {
576                         return dcesrv_netr_ServerAuthenticate3_check_downgrade(
577                                 dce_call, r, pipe_state, negotiate_flags,
578                                 NULL, /* trust_account_in_db */
579                                 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
580                 }
581                 encoded_name[len - 1] = '\0';
582
583                 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
584                         dns = encoded_name;
585                 } else {
586                         netbios = encoded_name;
587                 }
588
589                 nt_status = dsdb_trust_search_tdo(sam_ctx,
590                                                   netbios, dns,
591                                                   tdo_attrs, mem_ctx, &tdo_msg);
592                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
593                         DEBUG(2, ("Client asked for a trusted domain secure channel, "
594                                   "but there's no tdo for [%s] => [%s] \n",
595                                   log_escape(mem_ctx, r->in.account_name),
596                                   encoded_name));
597                         return dcesrv_netr_ServerAuthenticate3_check_downgrade(
598                                 dce_call, r, pipe_state, negotiate_flags,
599                                 NULL, /* trust_account_in_db */
600                                 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
601                 }
602                 if (!NT_STATUS_IS_OK(nt_status)) {
603                         return dcesrv_netr_ServerAuthenticate3_check_downgrade(
604                                 dce_call, r, pipe_state, negotiate_flags,
605                                 NULL, /* trust_account_in_db */
606                                 nt_status);
607                 }
608
609                 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
610                                                               &curNtHash,
611                                                               &prevNtHash);
612                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) {
613                         return dcesrv_netr_ServerAuthenticate3_check_downgrade(
614                                 dce_call, r, pipe_state, negotiate_flags,
615                                 NULL, /* trust_account_in_db */
616                                 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
617                 }
618                 if (!NT_STATUS_IS_OK(nt_status)) {
619                         return dcesrv_netr_ServerAuthenticate3_check_downgrade(
620                                 dce_call, r, pipe_state, negotiate_flags,
621                                 NULL, /* trust_account_in_db */
622                                 nt_status);
623                 }
624
625                 flatname = ldb_msg_find_attr_as_string(tdo_msg, "flatName", NULL);
626                 if (flatname == NULL) {
627                         return dcesrv_netr_ServerAuthenticate3_check_downgrade(
628                                 dce_call, r, pipe_state, negotiate_flags,
629                                 NULL, /* trust_account_in_db */
630                                 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
631                 }
632
633                 *trust_account_for_search = talloc_asprintf(mem_ctx, "%s$", flatname);
634                 if (*trust_account_for_search == NULL) {
635                         return dcesrv_netr_ServerAuthenticate3_check_downgrade(
636                                 dce_call, r, pipe_state, negotiate_flags,
637                                 NULL, /* trust_account_in_db */
638                                 NT_STATUS_NO_MEMORY);
639                 }
640         } else {
641                 *trust_account_for_search = r->in.account_name;
642         }
643
644         /* pull the user attributes */
645         num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
646                                    "(&(sAMAccountName=%s)(objectclass=user))",
647                                    ldb_binary_encode_string(mem_ctx,
648                                                             *trust_account_for_search));
649
650         if (num_records == 0) {
651                 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
652                          log_escape(mem_ctx, r->in.account_name)));
653                 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
654                                 dce_call, r, pipe_state, negotiate_flags,
655                                 NULL, /* trust_account_in_db */
656                                 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
657         }
658
659         if (num_records > 1) {
660                 DEBUG(0,("Found %d records matching user [%s]\n",
661                          num_records,
662                          log_escape(mem_ctx, r->in.account_name)));
663                 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
664                                 dce_call, r, pipe_state, negotiate_flags,
665                                 NULL, /* trust_account_in_db */
666                                 NT_STATUS_INTERNAL_DB_CORRUPTION);
667         }
668
669         *trust_account_in_db = ldb_msg_find_attr_as_string(msgs[0],
670                                                            "samAccountName",
671                                                            NULL);
672         if (*trust_account_in_db == NULL) {
673                 DEBUG(0,("No samAccountName returned in record matching user [%s]\n",
674                          r->in.account_name));
675                 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
676                                 dce_call, r, pipe_state, negotiate_flags,
677                                 NULL, /* trust_account_in_db */
678                                 NT_STATUS_INTERNAL_DB_CORRUPTION);
679         }
680
681         nt_status = dcesrv_netr_ServerAuthenticate3_check_downgrade(
682                         dce_call, r, pipe_state, negotiate_flags,
683                         *trust_account_in_db,
684                         NT_STATUS_OK);
685         if (!NT_STATUS_IS_OK(nt_status)) {
686                 return nt_status;
687         }
688
689         user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
690
691         if (user_account_control & UF_ACCOUNTDISABLE) {
692                 DEBUG(1, ("Account [%s] is disabled\n",
693                           log_escape(mem_ctx, r->in.account_name)));
694                 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
695         }
696
697         if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
698                 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
699                         DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
700                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
701                 }
702         } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
703                    r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
704                 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
705                         DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
706
707                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
708                 }
709         } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
710                 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
711                         DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
712                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
713                 }
714         } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
715                 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
716                         DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
717                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
718                 }
719         } else {
720                 /* we should never reach this */
721                 return NT_STATUS_INTERNAL_ERROR;
722         }
723
724         if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
725                 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
726                                         dce_call->conn->dce_ctx->lp_ctx,
727                                         msgs[0], &curNtHash);
728                 if (!NT_STATUS_IS_OK(nt_status)) {
729                         return NT_STATUS_ACCESS_DENIED;
730                 }
731         }
732
733         if (curNtHash == NULL) {
734                 return NT_STATUS_ACCESS_DENIED;
735         }
736
737         if (!challenge_valid) {
738                 DEBUG(1, ("No challenge requested by client [%s/%s], "
739                           "cannot authenticate\n",
740                           log_escape(mem_ctx, r->in.computer_name),
741                           log_escape(mem_ctx, r->in.account_name)));
742                 return NT_STATUS_ACCESS_DENIED;
743         }
744
745         creds = netlogon_creds_server_init(mem_ctx,
746                                            r->in.account_name,
747                                            r->in.computer_name,
748                                            r->in.secure_channel_type,
749                                            &challenge.client_challenge,
750                                            &challenge.server_challenge,
751                                            curNtHash,
752                                            r->in.credentials,
753                                            r->out.return_credentials,
754                                            negotiate_flags);
755         if (creds == NULL && prevNtHash != NULL) {
756                 /*
757                  * We fallback to the previous password for domain trusts.
758                  *
759                  * Note that lpcfg_old_password_allowed_period() doesn't
760                  * apply here.
761                  */
762                 creds = netlogon_creds_server_init(mem_ctx,
763                                                    r->in.account_name,
764                                                    r->in.computer_name,
765                                                    r->in.secure_channel_type,
766                                                    &challenge.client_challenge,
767                                                    &challenge.server_challenge,
768                                                    prevNtHash,
769                                                    r->in.credentials,
770                                                    r->out.return_credentials,
771                                                    negotiate_flags);
772         }
773
774         if (creds == NULL) {
775                 return NT_STATUS_ACCESS_DENIED;
776         }
777         creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
778         *sid = talloc_memdup(mem_ctx, creds->sid, sizeof(struct dom_sid));
779
780         nt_status = schannel_save_creds_state(mem_ctx,
781                                               dce_call->conn->dce_ctx->lp_ctx,
782                                               creds);
783         if (!NT_STATUS_IS_OK(nt_status)) {
784                 ZERO_STRUCTP(r->out.return_credentials);
785                 return nt_status;
786         }
787
788         *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
789                                                 "objectSid", 0);
790
791         return NT_STATUS_OK;
792 }
793
794 /*
795  * Log a netr_ServerAuthenticate3 request, and then invoke
796  * dcesrv_netr_ServerAuthenticate3_helper to perform the actual processing
797  */
798 static NTSTATUS dcesrv_netr_ServerAuthenticate3(
799         struct dcesrv_call_state *dce_call,
800         TALLOC_CTX *mem_ctx,
801         struct netr_ServerAuthenticate3 *r)
802 {
803         NTSTATUS status;
804         struct dom_sid *sid = NULL;
805         const char *trust_account_for_search = NULL;
806         const char *trust_account_in_db = NULL;
807         struct imessaging_context *imsg_ctx =
808                 dcesrv_imessaging_context(dce_call->conn);
809         struct auth_usersupplied_info ui = {
810                 .local_host = dce_call->conn->local_address,
811                 .remote_host = dce_call->conn->remote_address,
812                 .client = {
813                         .account_name = r->in.account_name,
814                         .domain_name = lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
815                 },
816                 .service_description = "NETLOGON",
817                 .auth_description = "ServerAuthenticate",
818                 .netlogon_trust_account = {
819                         .computer_name = r->in.computer_name,
820                         .negotiate_flags = *r->in.negotiate_flags,
821                         .secure_channel_type = r->in.secure_channel_type,
822                 },
823         };
824
825         status = dcesrv_netr_ServerAuthenticate3_helper(dce_call,
826                                                         mem_ctx,
827                                                         r,
828                                                         &trust_account_for_search,
829                                                         &trust_account_in_db,
830                                                         &sid);
831         ui.netlogon_trust_account.sid = sid;
832         ui.netlogon_trust_account.account_name = trust_account_in_db;
833         ui.mapped.account_name = trust_account_for_search;
834         log_authentication_event(
835                 imsg_ctx,
836                 dce_call->conn->dce_ctx->lp_ctx,
837                 NULL,
838                 &ui,
839                 status,
840                 lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
841                 trust_account_in_db,
842                 sid,
843                 NULL /* client_audit_info */,
844                 NULL /* server_audit_info */);
845
846         return status;
847 }
848 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
849                                         struct netr_ServerAuthenticate *r)
850 {
851         struct netr_ServerAuthenticate3 a;
852         uint32_t rid;
853         /* TODO:
854          * negotiate_flags is used as an [in] parameter
855          * so it need to be initialised.
856          *
857          * (I think ... = 0; seems wrong here --metze)
858          */
859         uint32_t negotiate_flags_in = 0;
860         uint32_t negotiate_flags_out = 0;
861
862         a.in.server_name                = r->in.server_name;
863         a.in.account_name               = r->in.account_name;
864         a.in.secure_channel_type        = r->in.secure_channel_type;
865         a.in.computer_name              = r->in.computer_name;
866         a.in.credentials                = r->in.credentials;
867         a.in.negotiate_flags            = &negotiate_flags_in;
868
869         a.out.return_credentials        = r->out.return_credentials;
870         a.out.rid                       = &rid;
871         a.out.negotiate_flags           = &negotiate_flags_out;
872
873         return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
874 }
875
876 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
877                                          struct netr_ServerAuthenticate2 *r)
878 {
879         struct netr_ServerAuthenticate3 r3;
880         uint32_t rid = 0;
881
882         r3.in.server_name = r->in.server_name;
883         r3.in.account_name = r->in.account_name;
884         r3.in.secure_channel_type = r->in.secure_channel_type;
885         r3.in.computer_name = r->in.computer_name;
886         r3.in.credentials = r->in.credentials;
887         r3.out.return_credentials = r->out.return_credentials;
888         r3.in.negotiate_flags = r->in.negotiate_flags;
889         r3.out.negotiate_flags = r->out.negotiate_flags;
890         r3.out.rid = &rid;
891
892         return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
893 }
894
895 /*
896   Change the machine account password for the currently connected
897   client.  Supplies only the NT#.
898 */
899
900 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
901                                        struct netr_ServerPasswordSet *r)
902 {
903         struct netlogon_creds_CredentialState *creds;
904         struct ldb_context *sam_ctx;
905         NTSTATUS nt_status;
906
907         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
908                                                         mem_ctx,
909                                                         r->in.computer_name,
910                                                         r->in.credential, r->out.return_authenticator,
911                                                         &creds);
912         NT_STATUS_NOT_OK_RETURN(nt_status);
913
914         sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
915         if (sam_ctx == NULL) {
916                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
917         }
918
919         nt_status = netlogon_creds_des_decrypt(creds, r->in.new_password);
920         NT_STATUS_NOT_OK_RETURN(nt_status);
921
922         /* Using the sid for the account as the key, set the password */
923         nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
924                                            creds->sid,
925                                            NULL, /* Don't have version */
926                                            NULL, /* Don't have plaintext */
927                                            r->in.new_password,
928                                            DSDB_PASSWORD_CHECKED_AND_CORRECT, /* Password change */
929                                            NULL, NULL);
930         return nt_status;
931 }
932
933 /*
934   Change the machine account password for the currently connected
935   client.  Supplies new plaintext.
936 */
937 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
938                                        struct netr_ServerPasswordSet2 *r)
939 {
940         struct netlogon_creds_CredentialState *creds;
941         struct ldb_context *sam_ctx;
942         struct NL_PASSWORD_VERSION version = {};
943         const uint32_t *new_version = NULL;
944         NTSTATUS nt_status;
945         DATA_BLOB new_password = data_blob_null;
946         size_t confounder_len;
947         DATA_BLOB dec_blob = data_blob_null;
948         DATA_BLOB enc_blob = data_blob_null;
949         struct samr_CryptPassword password_buf;
950
951         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
952                                                         mem_ctx,
953                                                         r->in.computer_name,
954                                                         r->in.credential, r->out.return_authenticator,
955                                                         &creds);
956         NT_STATUS_NOT_OK_RETURN(nt_status);
957
958         sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
959         if (sam_ctx == NULL) {
960                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
961         }
962
963         memcpy(password_buf.data, r->in.new_password->data, 512);
964         SIVAL(password_buf.data, 512, r->in.new_password->length);
965
966         if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
967                 nt_status = netlogon_creds_aes_decrypt(creds,
968                                                        password_buf.data,
969                                                        516);
970         } else {
971                 nt_status = netlogon_creds_arcfour_crypt(creds,
972                                                          password_buf.data,
973                                                          516);
974         }
975
976         if (!NT_STATUS_IS_OK(nt_status)) {
977                 return nt_status;
978         }
979
980         switch (creds->secure_channel_type) {
981         case SEC_CHAN_DOMAIN:
982         case SEC_CHAN_DNS_DOMAIN: {
983                 uint32_t len = IVAL(password_buf.data, 512);
984                 if (len <= 500) {
985                         uint32_t ofs = 500 - len;
986                         uint8_t *p;
987
988                         p = password_buf.data + ofs;
989
990                         version.ReservedField = IVAL(p, 0);
991                         version.PasswordVersionNumber = IVAL(p, 4);
992                         version.PasswordVersionPresent = IVAL(p, 8);
993
994                         if (version.PasswordVersionPresent == NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT) {
995                                 new_version = &version.PasswordVersionNumber;
996                         }
997                 }}
998                 break;
999         default:
1000                 break;
1001         }
1002
1003         if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
1004                 DEBUG(3,("samr: failed to decode password buffer\n"));
1005                 return NT_STATUS_WRONG_PASSWORD;
1006         }
1007
1008         /*
1009          * Make sure the length field was encrypted,
1010          * otherwise we are under attack.
1011          */
1012         if (new_password.length == r->in.new_password->length) {
1013                 DBG_WARNING("Length[%zu] field not encrypted\n",
1014                             new_password.length);
1015                 return NT_STATUS_WRONG_PASSWORD;
1016         }
1017
1018         /*
1019          * We don't allow empty passwords for machine accounts.
1020          */
1021         if (new_password.length < 2) {
1022                 DBG_WARNING("Empty password Length[%zu]\n",
1023                             new_password.length);
1024                 return NT_STATUS_WRONG_PASSWORD;
1025         }
1026
1027         /*
1028          * Make sure the confounder part of CryptPassword
1029          * buffer was encrypted, otherwise we are under attack.
1030          */
1031         confounder_len = 512 - new_password.length;
1032         enc_blob = data_blob_const(r->in.new_password->data, confounder_len);
1033         dec_blob = data_blob_const(password_buf.data, confounder_len);
1034         if (confounder_len > 0 && data_blob_equal_const_time(&dec_blob, &enc_blob)) {
1035                 DBG_WARNING("Confounder buffer not encrypted Length[%zu]\n",
1036                             confounder_len);
1037                 return NT_STATUS_WRONG_PASSWORD;
1038         }
1039
1040         /*
1041          * Check that the password part was actually encrypted,
1042          * otherwise we are under attack.
1043          */
1044         enc_blob = data_blob_const(r->in.new_password->data + confounder_len,
1045                                    new_password.length);
1046         dec_blob = data_blob_const(password_buf.data + confounder_len,
1047                                    new_password.length);
1048         if (data_blob_equal_const_time(&dec_blob, &enc_blob)) {
1049                 DBG_WARNING("Password buffer not encrypted Length[%zu]\n",
1050                             new_password.length);
1051                 return NT_STATUS_WRONG_PASSWORD;
1052         }
1053
1054         /*
1055          * don't allow zero buffers
1056          */
1057         if (all_zero(new_password.data, new_password.length)) {
1058                 DBG_WARNING("Password zero buffer Length[%zu]\n",
1059                             new_password.length);
1060                 return NT_STATUS_WRONG_PASSWORD;
1061         }
1062
1063         /* Using the sid for the account as the key, set the password */
1064         nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
1065                                            creds->sid,
1066                                            new_version,
1067                                            &new_password, /* we have plaintext */
1068                                            NULL,
1069                                            DSDB_PASSWORD_CHECKED_AND_CORRECT, /* Password change */
1070                                            NULL, NULL);
1071         return nt_status;
1072 }
1073
1074
1075 /*
1076   netr_LogonUasLogon
1077 */
1078 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1079                                  struct netr_LogonUasLogon *r)
1080 {
1081         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1082 }
1083
1084
1085 /*
1086   netr_LogonUasLogoff
1087 */
1088 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1089                        struct netr_LogonUasLogoff *r)
1090 {
1091         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1092 }
1093
1094
1095 static NTSTATUS dcesrv_netr_LogonSamLogon_check(struct dcesrv_call_state *dce_call,
1096                                                 const struct netr_LogonSamLogonEx *r)
1097 {
1098         enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
1099
1100         switch (r->in.logon_level) {
1101         case NetlogonInteractiveInformation:
1102         case NetlogonServiceInformation:
1103         case NetlogonInteractiveTransitiveInformation:
1104         case NetlogonServiceTransitiveInformation:
1105                 if (r->in.logon->password == NULL) {
1106                         return NT_STATUS_INVALID_PARAMETER;
1107                 }
1108
1109                 switch (r->in.validation_level) {
1110                 case NetlogonValidationSamInfo:  /* 2 */
1111                 case NetlogonValidationSamInfo2: /* 3 */
1112                 case NetlogonValidationSamInfo4: /* 6 */
1113                         break;
1114                 default:
1115                         return NT_STATUS_INVALID_INFO_CLASS;
1116                 }
1117
1118                 break;
1119         case NetlogonNetworkInformation:
1120         case NetlogonNetworkTransitiveInformation:
1121                 if (r->in.logon->network == NULL) {
1122                         return NT_STATUS_INVALID_PARAMETER;
1123                 }
1124
1125                 switch (r->in.validation_level) {
1126                 case NetlogonValidationSamInfo:  /* 2 */
1127                 case NetlogonValidationSamInfo2: /* 3 */
1128                 case NetlogonValidationSamInfo4: /* 6 */
1129                         break;
1130                 default:
1131                         return NT_STATUS_INVALID_INFO_CLASS;
1132                 }
1133
1134                 break;
1135
1136         case NetlogonGenericInformation:
1137                 if (r->in.logon->generic == NULL) {
1138                         return NT_STATUS_INVALID_PARAMETER;
1139                 }
1140
1141                 switch (r->in.validation_level) {
1142                 /* TODO: case NetlogonValidationGenericInfo: 4 */
1143                 case NetlogonValidationGenericInfo2: /* 5 */
1144                         break;
1145                 default:
1146                         return NT_STATUS_INVALID_INFO_CLASS;
1147                 }
1148
1149                 break;
1150         default:
1151                 return NT_STATUS_INVALID_PARAMETER;
1152         }
1153
1154         dcesrv_call_auth_info(dce_call, NULL, &auth_level);
1155
1156         switch (r->in.validation_level) {
1157         case NetlogonValidationSamInfo4: /* 6 */
1158                 if (auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
1159                         return NT_STATUS_INVALID_PARAMETER;
1160                 }
1161                 break;
1162
1163         default:
1164                 break;
1165         }
1166
1167         return NT_STATUS_OK;
1168 }
1169
1170 struct dcesrv_netr_LogonSamLogon_base_state {
1171         struct dcesrv_call_state *dce_call;
1172
1173         TALLOC_CTX *mem_ctx;
1174
1175         struct netlogon_creds_CredentialState *creds;
1176
1177         struct netr_LogonSamLogonEx r;
1178
1179         uint32_t _ignored_flags;
1180
1181         struct {
1182                 struct netr_LogonSamLogon *lsl;
1183                 struct netr_LogonSamLogonWithFlags *lslwf;
1184                 struct netr_LogonSamLogonEx *lslex;
1185         } _r;
1186
1187         struct kdc_check_generic_kerberos kr;
1188 };
1189
1190 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq);
1191 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq);
1192 static void dcesrv_netr_LogonSamLogon_base_reply(
1193         struct dcesrv_netr_LogonSamLogon_base_state *state);
1194
1195 /*
1196   netr_LogonSamLogon_base
1197
1198   This version of the function allows other wrappers to say 'do not check the credentials'
1199
1200   We can't do the traditional 'wrapping' format completely, as this
1201   function must only run under schannel
1202 */
1203 static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamLogon_base_state *state)
1204 {
1205         struct dcesrv_call_state *dce_call = state->dce_call;
1206         struct imessaging_context *imsg_ctx =
1207                 dcesrv_imessaging_context(dce_call->conn);
1208         TALLOC_CTX *mem_ctx = state->mem_ctx;
1209         struct netr_LogonSamLogonEx *r = &state->r;
1210         struct netlogon_creds_CredentialState *creds = state->creds;
1211         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1212         const char *workgroup = lpcfg_workgroup(lp_ctx);
1213         struct auth4_context *auth_context = NULL;
1214         struct auth_usersupplied_info *user_info = NULL;
1215         NTSTATUS nt_status;
1216         struct tevent_req *subreq = NULL;
1217         enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
1218         enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
1219
1220         dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
1221
1222         switch (dce_call->pkt.u.request.opnum) {
1223         case NDR_NETR_LOGONSAMLOGON:
1224         case NDR_NETR_LOGONSAMLOGONWITHFLAGS:
1225                 /*
1226                  * These already called dcesrv_netr_check_schannel()
1227                  * via dcesrv_netr_creds_server_step_check()
1228                  */
1229                 break;
1230         case NDR_NETR_LOGONSAMLOGONEX:
1231         default:
1232                 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1233                         return NT_STATUS_ACCESS_DENIED;
1234                 }
1235
1236                 nt_status = dcesrv_netr_check_schannel(dce_call,
1237                                                        creds,
1238                                                        auth_type,
1239                                                        auth_level,
1240                                                        dce_call->pkt.u.request.opnum);
1241                 if (!NT_STATUS_IS_OK(nt_status)) {
1242                         return nt_status;
1243                 }
1244                 break;
1245         }
1246
1247         *r->out.authoritative = 1;
1248
1249         if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_TO_FOREST_ROOT) {
1250                 /*
1251                  * Currently we're always the forest root ourself.
1252                  */
1253                 return NT_STATUS_NO_SUCH_USER;
1254         }
1255
1256         if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_CROSS_FOREST_HOP) {
1257                 /*
1258                  * Currently we don't support trusts correctly yet.
1259                  */
1260                 return NT_STATUS_NO_SUCH_USER;
1261         }
1262
1263         user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
1264         NT_STATUS_HAVE_NO_MEMORY(user_info);
1265
1266         user_info->service_description = "SamLogon";
1267
1268         nt_status = netlogon_creds_decrypt_samlogon_logon(creds,
1269                                                           r->in.logon_level,
1270                                                           r->in.logon);
1271         NT_STATUS_NOT_OK_RETURN(nt_status);
1272
1273         switch (r->in.logon_level) {
1274         case NetlogonInteractiveInformation:
1275         case NetlogonServiceInformation:
1276         case NetlogonInteractiveTransitiveInformation:
1277         case NetlogonServiceTransitiveInformation:
1278         case NetlogonNetworkInformation:
1279         case NetlogonNetworkTransitiveInformation:
1280
1281                 nt_status = auth_context_create_for_netlogon(mem_ctx,
1282                                         dce_call->event_ctx,
1283                                         imsg_ctx,
1284                                         dce_call->conn->dce_ctx->lp_ctx,
1285                                         &auth_context);
1286                 NT_STATUS_NOT_OK_RETURN(nt_status);
1287
1288                 user_info->remote_host = dce_call->conn->remote_address;
1289                 user_info->local_host = dce_call->conn->local_address;
1290
1291                 user_info->netlogon_trust_account.secure_channel_type
1292                         = creds->secure_channel_type;
1293                 user_info->netlogon_trust_account.negotiate_flags
1294                         = creds->negotiate_flags;
1295
1296                 /*
1297                  * These two can be unrelated when the account is
1298                  * actually that of a trusted domain, so we want to
1299                  * know which DC in that trusted domain contacted
1300                  * us
1301                  */
1302                 user_info->netlogon_trust_account.computer_name
1303                         = creds->computer_name;
1304                 user_info->netlogon_trust_account.account_name
1305                         = creds->account_name;
1306                 user_info->netlogon_trust_account.sid
1307                         = creds->sid;
1308
1309                 break;
1310         default:
1311                 /* We do not need to set up the user_info in this case */
1312                 break;
1313         }
1314
1315         switch (r->in.logon_level) {
1316         case NetlogonInteractiveInformation:
1317         case NetlogonServiceInformation:
1318         case NetlogonInteractiveTransitiveInformation:
1319         case NetlogonServiceTransitiveInformation:
1320                 user_info->auth_description = "interactive";
1321
1322                 user_info->logon_parameters
1323                         = r->in.logon->password->identity_info.parameter_control;
1324                 user_info->client.account_name
1325                         = r->in.logon->password->identity_info.account_name.string;
1326                 user_info->client.domain_name
1327                         = r->in.logon->password->identity_info.domain_name.string;
1328                 user_info->workstation_name
1329                         = r->in.logon->password->identity_info.workstation.string;
1330                 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
1331                 user_info->password_state = AUTH_PASSWORD_HASH;
1332
1333                 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
1334                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
1335                 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
1336
1337                 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
1338                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
1339                 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
1340
1341                 user_info->logon_id
1342                     = r->in.logon->password->identity_info.logon_id;
1343
1344                 break;
1345         case NetlogonNetworkInformation:
1346         case NetlogonNetworkTransitiveInformation:
1347                 user_info->auth_description = "network";
1348
1349                 nt_status = auth_context_set_challenge(
1350                         auth_context,
1351                         r->in.logon->network->challenge,
1352                         "netr_LogonSamLogonWithFlags");
1353                 NT_STATUS_NOT_OK_RETURN(nt_status);
1354
1355                 user_info->logon_parameters
1356                         = r->in.logon->network->identity_info.parameter_control;
1357                 user_info->client.account_name
1358                         = r->in.logon->network->identity_info.account_name.string;
1359                 user_info->client.domain_name
1360                         = r->in.logon->network->identity_info.domain_name.string;
1361                 user_info->workstation_name
1362                         = r->in.logon->network->identity_info.workstation.string;
1363
1364                 user_info->password_state = AUTH_PASSWORD_RESPONSE;
1365                 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
1366                 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
1367
1368                 user_info->logon_id
1369                     = r->in.logon->network->identity_info.logon_id;
1370
1371                 nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
1372                                         user_info->client.account_name,
1373                                         user_info->client.domain_name,
1374                                         user_info->password.response.nt,
1375                                         creds, workgroup);
1376                 NT_STATUS_NOT_OK_RETURN(nt_status);
1377
1378                 break;
1379
1380
1381         case NetlogonGenericInformation:
1382         {
1383                 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1384                         /* OK */
1385                 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1386                         /* OK */
1387                 } else {
1388                         /* Using DES to verify kerberos tickets makes no sense */
1389                         return NT_STATUS_INVALID_PARAMETER;
1390                 }
1391
1392                 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
1393                         struct dcerpc_binding_handle *irpc_handle;
1394                         struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
1395                         NT_STATUS_HAVE_NO_MEMORY(generic);
1396
1397                         r->out.validation->generic = generic;
1398
1399                         user_info->logon_id
1400                             = r->in.logon->generic->identity_info.logon_id;
1401
1402                         irpc_handle = irpc_binding_handle_by_name(mem_ctx,
1403                                                                   imsg_ctx,
1404                                                                   "kdc_server",
1405                                                                   &ndr_table_irpc);
1406                         if (irpc_handle == NULL) {
1407                                 return NT_STATUS_NO_LOGON_SERVERS;
1408                         }
1409
1410                         state->kr.in.generic_request =
1411                                 data_blob_const(r->in.logon->generic->data,
1412                                                 r->in.logon->generic->length);
1413
1414                         /*
1415                          * 60 seconds should be enough
1416                          */
1417                         dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1418                         subreq = dcerpc_kdc_check_generic_kerberos_r_send(state,
1419                                                 state->dce_call->event_ctx,
1420                                                 irpc_handle, &state->kr);
1421                         if (subreq == NULL) {
1422                                 return NT_STATUS_NO_MEMORY;
1423                         }
1424                         state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1425                         tevent_req_set_callback(subreq,
1426                                         dcesrv_netr_LogonSamLogon_base_krb5_done,
1427                                         state);
1428                         return NT_STATUS_OK;
1429                 }
1430
1431                 /* Until we get an implemetnation of these other packages */
1432                 return NT_STATUS_INVALID_PARAMETER;
1433         }
1434         default:
1435                 return NT_STATUS_INVALID_PARAMETER;
1436         }
1437
1438         subreq = auth_check_password_send(state, state->dce_call->event_ctx,
1439                                           auth_context, user_info);
1440         state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1441         tevent_req_set_callback(subreq,
1442                                 dcesrv_netr_LogonSamLogon_base_auth_done,
1443                                 state);
1444         return NT_STATUS_OK;
1445 }
1446
1447 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq)
1448 {
1449         struct dcesrv_netr_LogonSamLogon_base_state *state =
1450                 tevent_req_callback_data(subreq,
1451                 struct dcesrv_netr_LogonSamLogon_base_state);
1452         TALLOC_CTX *mem_ctx = state->mem_ctx;
1453         struct netr_LogonSamLogonEx *r = &state->r;
1454         struct auth_user_info_dc *user_info_dc = NULL;
1455         struct netr_SamInfo2 *sam2 = NULL;
1456         struct netr_SamInfo3 *sam3 = NULL;
1457         struct netr_SamInfo6 *sam6 = NULL;
1458         NTSTATUS nt_status;
1459
1460         nt_status = auth_check_password_recv(subreq, mem_ctx,
1461                                              &user_info_dc,
1462                                              r->out.authoritative);
1463         TALLOC_FREE(subreq);
1464         if (!NT_STATUS_IS_OK(nt_status)) {
1465                 r->out.result = nt_status;
1466                 dcesrv_netr_LogonSamLogon_base_reply(state);
1467                 return;
1468         }
1469
1470         switch (r->in.validation_level) {
1471         case 2:
1472                 nt_status = auth_convert_user_info_dc_saminfo2(mem_ctx,
1473                                                                user_info_dc,
1474                                                                AUTH_INCLUDE_RESOURCE_GROUPS,
1475                                                                &sam2);
1476                 if (!NT_STATUS_IS_OK(nt_status)) {
1477                         r->out.result = nt_status;
1478                         dcesrv_netr_LogonSamLogon_base_reply(state);
1479                         return;
1480                 }
1481
1482                 r->out.validation->sam2 = sam2;
1483                 break;
1484
1485         case 3:
1486                 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
1487                                                                user_info_dc,
1488                                                                AUTH_INCLUDE_RESOURCE_GROUPS,
1489                                                                &sam3, NULL);
1490                 if (!NT_STATUS_IS_OK(nt_status)) {
1491                         r->out.result = nt_status;
1492                         dcesrv_netr_LogonSamLogon_base_reply(state);
1493                         return;
1494                 }
1495
1496                 r->out.validation->sam3 = sam3;
1497                 break;
1498
1499         case 6:
1500                 nt_status = auth_convert_user_info_dc_saminfo6(mem_ctx,
1501                                                                user_info_dc,
1502                                                                AUTH_INCLUDE_RESOURCE_GROUPS,
1503                                                                &sam6, NULL);
1504                 if (!NT_STATUS_IS_OK(nt_status)) {
1505                         r->out.result = nt_status;
1506                         dcesrv_netr_LogonSamLogon_base_reply(state);
1507                         return;
1508                 }
1509
1510                 r->out.validation->sam6 = sam6;
1511                 break;
1512
1513         default:
1514                 if (!NT_STATUS_IS_OK(nt_status)) {
1515                         r->out.result = NT_STATUS_INVALID_INFO_CLASS;
1516                         dcesrv_netr_LogonSamLogon_base_reply(state);
1517                         return;
1518                 }
1519         }
1520
1521         /* TODO: Describe and deal with these flags */
1522         *r->out.flags = 0;
1523
1524         r->out.result = NT_STATUS_OK;
1525
1526         dcesrv_netr_LogonSamLogon_base_reply(state);
1527 }
1528
1529 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq)
1530 {
1531         struct dcesrv_netr_LogonSamLogon_base_state *state =
1532                 tevent_req_callback_data(subreq,
1533                 struct dcesrv_netr_LogonSamLogon_base_state);
1534         TALLOC_CTX *mem_ctx = state->mem_ctx;
1535         struct netr_LogonSamLogonEx *r = &state->r;
1536         struct netr_GenericInfo2 *generic = NULL;
1537         NTSTATUS status;
1538
1539         status = dcerpc_kdc_check_generic_kerberos_r_recv(subreq, mem_ctx);
1540         TALLOC_FREE(subreq);
1541         if (!NT_STATUS_IS_OK(status)) {
1542                 r->out.result = status;
1543                 dcesrv_netr_LogonSamLogon_base_reply(state);
1544                 return;
1545         }
1546
1547         generic = r->out.validation->generic;
1548         generic->length = state->kr.out.generic_reply.length;
1549         generic->data = state->kr.out.generic_reply.data;
1550
1551         /* TODO: Describe and deal with these flags */
1552         *r->out.flags = 0;
1553
1554         r->out.result = NT_STATUS_OK;
1555
1556         dcesrv_netr_LogonSamLogon_base_reply(state);
1557 }
1558
1559 static void dcesrv_netr_LogonSamLogon_base_reply(
1560         struct dcesrv_netr_LogonSamLogon_base_state *state)
1561 {
1562         struct netr_LogonSamLogonEx *r = &state->r;
1563         NTSTATUS status;
1564
1565         if (NT_STATUS_IS_OK(r->out.result)) {
1566                 status = netlogon_creds_encrypt_samlogon_validation(state->creds,
1567                                                                     r->in.validation_level,
1568                                                                     r->out.validation);
1569                 if (!NT_STATUS_IS_OK(status)) {
1570                         DBG_ERR("netlogon_creds_encrypt_samlogon_validation() "
1571                                 "failed - %s\n",
1572                                 nt_errstr(status));
1573                 }
1574         }
1575
1576         if (state->_r.lslex != NULL) {
1577                 struct netr_LogonSamLogonEx *_r = state->_r.lslex;
1578                 _r->out.result = r->out.result;
1579         } else if (state->_r.lslwf != NULL) {
1580                 struct netr_LogonSamLogonWithFlags *_r = state->_r.lslwf;
1581                 _r->out.result = r->out.result;
1582         } else if (state->_r.lsl != NULL) {
1583                 struct netr_LogonSamLogon *_r = state->_r.lsl;
1584                 _r->out.result = r->out.result;
1585         }
1586
1587         status = dcesrv_reply(state->dce_call);
1588         if (!NT_STATUS_IS_OK(status)) {
1589                 DBG_ERR("dcesrv_reply() failed - %s\n",
1590                         nt_errstr(status));
1591         }
1592 }
1593
1594 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1595                                      struct netr_LogonSamLogonEx *r)
1596 {
1597         struct dcesrv_netr_LogonSamLogon_base_state *state;
1598         NTSTATUS nt_status;
1599
1600         *r->out.authoritative = 1;
1601
1602         state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1603         if (state == NULL) {
1604                 return NT_STATUS_NO_MEMORY;
1605         }
1606
1607         state->dce_call = dce_call;
1608         state->mem_ctx = mem_ctx;
1609
1610         state->r.in.server_name      = r->in.server_name;
1611         state->r.in.computer_name    = r->in.computer_name;
1612         state->r.in.logon_level      = r->in.logon_level;
1613         state->r.in.logon            = r->in.logon;
1614         state->r.in.validation_level = r->in.validation_level;
1615         state->r.in.flags            = r->in.flags;
1616         state->r.out.validation      = r->out.validation;
1617         state->r.out.authoritative   = r->out.authoritative;
1618         state->r.out.flags           = r->out.flags;
1619
1620         state->_r.lslex = r;
1621
1622         nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1623         if (!NT_STATUS_IS_OK(nt_status)) {
1624                 return nt_status;
1625         }
1626
1627         nt_status = schannel_get_creds_state(mem_ctx,
1628                                              dce_call->conn->dce_ctx->lp_ctx,
1629                                              r->in.computer_name, &state->creds);
1630         if (!NT_STATUS_IS_OK(nt_status)) {
1631                 return nt_status;
1632         }
1633
1634         nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1635
1636         if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1637                 return nt_status;
1638         }
1639
1640         return nt_status;
1641 }
1642
1643 /*
1644   netr_LogonSamLogonWithFlags
1645
1646 */
1647 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1648                                             struct netr_LogonSamLogonWithFlags *r)
1649 {
1650         struct dcesrv_netr_LogonSamLogon_base_state *state;
1651         NTSTATUS nt_status;
1652
1653         *r->out.authoritative = 1;
1654
1655         state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1656         if (state == NULL) {
1657                 return NT_STATUS_NO_MEMORY;
1658         }
1659
1660         state->dce_call = dce_call;
1661         state->mem_ctx = mem_ctx;
1662
1663         state->r.in.server_name      = r->in.server_name;
1664         state->r.in.computer_name    = r->in.computer_name;
1665         state->r.in.logon_level      = r->in.logon_level;
1666         state->r.in.logon            = r->in.logon;
1667         state->r.in.validation_level = r->in.validation_level;
1668         state->r.in.flags            = r->in.flags;
1669         state->r.out.validation      = r->out.validation;
1670         state->r.out.authoritative   = r->out.authoritative;
1671         state->r.out.flags           = r->out.flags;
1672
1673         state->_r.lslwf = r;
1674
1675         nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1676         if (!NT_STATUS_IS_OK(nt_status)) {
1677                 return nt_status;
1678         }
1679
1680         r->out.return_authenticator = talloc_zero(mem_ctx,
1681                                                   struct netr_Authenticator);
1682         if (r->out.return_authenticator == NULL) {
1683                 return NT_STATUS_NO_MEMORY;
1684         }
1685
1686         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1687                                                         mem_ctx,
1688                                                         r->in.computer_name,
1689                                                         r->in.credential,
1690                                                         r->out.return_authenticator,
1691                                                         &state->creds);
1692         if (!NT_STATUS_IS_OK(nt_status)) {
1693                 return nt_status;
1694         }
1695
1696         nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1697
1698         if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1699                 return nt_status;
1700         }
1701
1702         return nt_status;
1703 }
1704
1705 /*
1706   netr_LogonSamLogon
1707 */
1708 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1709                                    struct netr_LogonSamLogon *r)
1710 {
1711         struct dcesrv_netr_LogonSamLogon_base_state *state;
1712         NTSTATUS nt_status;
1713
1714         *r->out.authoritative = 1;
1715
1716         state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1717         if (state == NULL) {
1718                 return NT_STATUS_NO_MEMORY;
1719         }
1720
1721         state->dce_call = dce_call;
1722         state->mem_ctx = mem_ctx;
1723
1724         state->r.in.server_name      = r->in.server_name;
1725         state->r.in.computer_name    = r->in.computer_name;
1726         state->r.in.logon_level      = r->in.logon_level;
1727         state->r.in.logon            = r->in.logon;
1728         state->r.in.validation_level = r->in.validation_level;
1729         state->r.in.flags            = &state->_ignored_flags;
1730         state->r.out.validation      = r->out.validation;
1731         state->r.out.authoritative   = r->out.authoritative;
1732         state->r.out.flags           = &state->_ignored_flags;
1733
1734         state->_r.lsl = r;
1735
1736         nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1737         if (!NT_STATUS_IS_OK(nt_status)) {
1738                 return nt_status;
1739         }
1740
1741         r->out.return_authenticator = talloc_zero(mem_ctx,
1742                                                   struct netr_Authenticator);
1743         if (r->out.return_authenticator == NULL) {
1744                 return NT_STATUS_NO_MEMORY;
1745         }
1746
1747         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1748                                                         mem_ctx,
1749                                                         r->in.computer_name,
1750                                                         r->in.credential,
1751                                                         r->out.return_authenticator,
1752                                                         &state->creds);
1753         if (!NT_STATUS_IS_OK(nt_status)) {
1754                 return nt_status;
1755         }
1756
1757         nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1758
1759         if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1760                 return nt_status;
1761         }
1762
1763         return nt_status;
1764 }
1765
1766
1767 /*
1768   netr_LogonSamLogoff
1769 */
1770 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1771                        struct netr_LogonSamLogoff *r)
1772 {
1773         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1774 }
1775
1776
1777
1778 /*
1779   netr_DatabaseDeltas
1780 */
1781 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1782                        struct netr_DatabaseDeltas *r)
1783 {
1784         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1785 }
1786
1787
1788 /*
1789   netr_DatabaseSync2
1790 */
1791 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1792                        struct netr_DatabaseSync2 *r)
1793 {
1794         /* win2k3 native mode returns  "NOT IMPLEMENTED" for this call */
1795         return NT_STATUS_NOT_IMPLEMENTED;
1796 }
1797
1798
1799 /*
1800   netr_DatabaseSync
1801 */
1802 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1803                        struct netr_DatabaseSync *r)
1804 {
1805         struct netr_DatabaseSync2 r2;
1806         NTSTATUS status;
1807
1808         ZERO_STRUCT(r2);
1809
1810         r2.in.logon_server = r->in.logon_server;
1811         r2.in.computername = r->in.computername;
1812         r2.in.credential = r->in.credential;
1813         r2.in.database_id = r->in.database_id;
1814         r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1815         r2.in.sync_context = r->in.sync_context;
1816         r2.out.sync_context = r->out.sync_context;
1817         r2.out.delta_enum_array = r->out.delta_enum_array;
1818         r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1819
1820         status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1821
1822         return status;
1823 }
1824
1825
1826 /*
1827   netr_AccountDeltas
1828 */
1829 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1830                        struct netr_AccountDeltas *r)
1831 {
1832         /* w2k3 returns "NOT IMPLEMENTED" for this call */
1833         return NT_STATUS_NOT_IMPLEMENTED;
1834 }
1835
1836
1837 /*
1838   netr_AccountSync
1839 */
1840 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1841                        struct netr_AccountSync *r)
1842 {
1843         /* w2k3 returns "NOT IMPLEMENTED" for this call */
1844         return NT_STATUS_NOT_IMPLEMENTED;
1845 }
1846
1847
1848 /*
1849   netr_GetDcName
1850 */
1851 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1852                        struct netr_GetDcName *r)
1853 {
1854         const char * const attrs[] = { NULL };
1855         struct ldb_context *sam_ctx;
1856         struct ldb_message **res;
1857         struct ldb_dn *domain_dn;
1858         int ret;
1859         const char *dcname;
1860
1861         /*
1862          * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1863          * that the domainname needs to be a valid netbios domain
1864          * name, if it is not NULL.
1865          */
1866         if (r->in.domainname) {
1867                 const char *dot = strchr(r->in.domainname, '.');
1868                 size_t len = strlen(r->in.domainname);
1869
1870                 if (dot || len > 15) {
1871                         return WERR_NERR_DCNOTFOUND;
1872                 }
1873
1874                 /*
1875                  * TODO: Should we also varify that only valid
1876                  *       netbios name characters are used?
1877                  */
1878         }
1879
1880         sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
1881         if (sam_ctx == NULL) {
1882                 return WERR_DS_UNAVAILABLE;
1883         }
1884
1885         domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1886                                        r->in.domainname);
1887         if (domain_dn == NULL) {
1888                 return WERR_NO_SUCH_DOMAIN;
1889         }
1890
1891         ret = gendb_search_dn(sam_ctx, mem_ctx,
1892                               domain_dn, &res, attrs);
1893         if (ret != 1) {
1894                 return WERR_NO_SUCH_DOMAIN;
1895         }
1896
1897         /* TODO: - return real IP address
1898          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
1899          */
1900         dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1901                                  lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1902         W_ERROR_HAVE_NO_MEMORY(dcname);
1903
1904         *r->out.dcname = dcname;
1905         return WERR_OK;
1906 }
1907
1908 struct dcesrv_netr_LogonControl_base_state {
1909         struct dcesrv_call_state *dce_call;
1910
1911         TALLOC_CTX *mem_ctx;
1912
1913         struct netr_LogonControl2Ex r;
1914
1915         struct {
1916                 struct netr_LogonControl *l;
1917                 struct netr_LogonControl2 *l2;
1918                 struct netr_LogonControl2Ex *l2ex;
1919         } _r;
1920 };
1921
1922 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
1923
1924 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
1925 {
1926         struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
1927         struct auth_session_info *session_info =
1928                 dcesrv_call_session_info(state->dce_call);
1929         struct imessaging_context *imsg_ctx =
1930                 dcesrv_imessaging_context(state->dce_call->conn);
1931         enum security_user_level security_level;
1932         struct dcerpc_binding_handle *irpc_handle;
1933         struct tevent_req *subreq;
1934         bool ok;
1935
1936         /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
1937
1938         if (state->_r.l != NULL) {
1939                 /*
1940                  * netr_LogonControl
1941                  */
1942                 if (state->r.in.level == 0x00000002) {
1943                         return WERR_NOT_SUPPORTED;
1944                 } else if (state->r.in.level != 0x00000001) {
1945                         return WERR_INVALID_LEVEL;
1946                 }
1947
1948                 switch (state->r.in.function_code) {
1949                 case NETLOGON_CONTROL_QUERY:
1950                 case NETLOGON_CONTROL_REPLICATE:
1951                 case NETLOGON_CONTROL_SYNCHRONIZE:
1952                 case NETLOGON_CONTROL_PDC_REPLICATE:
1953                 case NETLOGON_CONTROL_BREAKPOINT:
1954                 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
1955                 case NETLOGON_CONTROL_TRUNCATE_LOG:
1956                         break;
1957                 default:
1958                         return WERR_NOT_SUPPORTED;
1959                 }
1960         }
1961
1962         if (state->r.in.level < 0x00000001) {
1963                 return WERR_INVALID_LEVEL;
1964         }
1965
1966         if (state->r.in.level > 0x00000004) {
1967                 return WERR_INVALID_LEVEL;
1968         }
1969
1970         if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
1971                 struct netr_NETLOGON_INFO_1 *info1 = NULL;
1972                 struct netr_NETLOGON_INFO_3 *info3 = NULL;
1973
1974                 switch (state->r.in.level) {
1975                 case 0x00000001:
1976                         info1 = talloc_zero(state->mem_ctx,
1977                                             struct netr_NETLOGON_INFO_1);
1978                         if (info1 == NULL) {
1979                                 return WERR_NOT_ENOUGH_MEMORY;
1980                         }
1981                         state->r.out.query->info1 = info1;
1982                         return WERR_OK;
1983
1984                 case 0x00000003:
1985                         info3 = talloc_zero(state->mem_ctx,
1986                                             struct netr_NETLOGON_INFO_3);
1987                         if (info3 == NULL) {
1988                                 return WERR_NOT_ENOUGH_MEMORY;
1989                         }
1990                         state->r.out.query->info3 = info3;
1991                         return WERR_OK;
1992
1993                 default:
1994                         return WERR_INVALID_PARAMETER;
1995                 }
1996         }
1997
1998         /*
1999          * Some validations are done before the access check
2000          * and some after the access check
2001          */
2002         security_level = security_session_user_level(session_info, NULL);
2003         if (security_level < SECURITY_ADMINISTRATOR) {
2004                 return WERR_ACCESS_DENIED;
2005         }
2006
2007         if (state->_r.l2 != NULL) {
2008                 /*
2009                  * netr_LogonControl2
2010                  */
2011                 if (state->r.in.level == 0x00000004) {
2012                         return WERR_INVALID_LEVEL;
2013                 }
2014         }
2015
2016         switch (state->r.in.level) {
2017         case 0x00000001:
2018                 break;
2019
2020         case 0x00000002:
2021                 switch (state->r.in.function_code) {
2022                 case NETLOGON_CONTROL_REDISCOVER:
2023                 case NETLOGON_CONTROL_TC_QUERY:
2024                 case NETLOGON_CONTROL_TC_VERIFY:
2025                         break;
2026                 default:
2027                         return WERR_INVALID_PARAMETER;
2028                 }
2029
2030                 break;
2031
2032         case 0x00000003:
2033                 break;
2034
2035         case 0x00000004:
2036                 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
2037                         return WERR_INVALID_PARAMETER;
2038                 }
2039
2040                 break;
2041
2042         default:
2043                 return WERR_INVALID_LEVEL;
2044         }
2045
2046         switch (state->r.in.function_code) {
2047         case NETLOGON_CONTROL_REDISCOVER:
2048         case NETLOGON_CONTROL_TC_QUERY:
2049         case NETLOGON_CONTROL_TC_VERIFY:
2050                 if (state->r.in.level != 2) {
2051                         return WERR_INVALID_PARAMETER;
2052                 }
2053
2054                 if (state->r.in.data == NULL) {
2055                         return WERR_INVALID_PARAMETER;
2056                 }
2057
2058                 if (state->r.in.data->domain == NULL) {
2059                         return WERR_INVALID_PARAMETER;
2060                 }
2061
2062                 break;
2063
2064         case NETLOGON_CONTROL_CHANGE_PASSWORD:
2065                 if (state->r.in.level != 1) {
2066                         return WERR_INVALID_PARAMETER;
2067                 }
2068
2069                 if (state->r.in.data == NULL) {
2070                         return WERR_INVALID_PARAMETER;
2071                 }
2072
2073                 if (state->r.in.data->domain == NULL) {
2074                         return WERR_INVALID_PARAMETER;
2075                 }
2076
2077                 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
2078                                                  state->r.in.data->domain);
2079                 if (!ok) {
2080                         struct ldb_context *sam_ctx;
2081
2082                         sam_ctx = dcesrv_samdb_connect_as_system(state,
2083                                                                  state->dce_call);
2084                         if (sam_ctx == NULL) {
2085                                 return WERR_DS_UNAVAILABLE;
2086                         }
2087
2088                         /*
2089                          * Secrets for trusted domains can only be triggered on
2090                          * the PDC.
2091                          */
2092                         ok = samdb_is_pdc(sam_ctx);
2093                         TALLOC_FREE(sam_ctx);
2094                         if (!ok) {
2095                                 return WERR_INVALID_DOMAIN_ROLE;
2096                         }
2097                 }
2098
2099                 break;
2100         default:
2101                 return WERR_NOT_SUPPORTED;
2102         }
2103
2104         irpc_handle = irpc_binding_handle_by_name(state,
2105                                                   imsg_ctx,
2106                                                   "winbind_server",
2107                                                   &ndr_table_winbind);
2108         if (irpc_handle == NULL) {
2109                 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
2110                 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2111                 return WERR_SERVICE_NOT_FOUND;
2112         }
2113
2114         /*
2115          * 60 seconds timeout should be enough
2116          */
2117         dcerpc_binding_handle_set_timeout(irpc_handle, 60);
2118
2119         subreq = dcerpc_winbind_LogonControl_send(state,
2120                                                   state->dce_call->event_ctx,
2121                                                   irpc_handle,
2122                                                   state->r.in.function_code,
2123                                                   state->r.in.level,
2124                                                   state->r.in.data,
2125                                                   state->r.out.query);
2126         if (subreq == NULL) {
2127                 return WERR_NOT_ENOUGH_MEMORY;
2128         }
2129         state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2130         tevent_req_set_callback(subreq,
2131                                 dcesrv_netr_LogonControl_base_done,
2132                                 state);
2133
2134         return WERR_OK;
2135 }
2136
2137 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
2138 {
2139         struct dcesrv_netr_LogonControl_base_state *state =
2140                 tevent_req_callback_data(subreq,
2141                 struct dcesrv_netr_LogonControl_base_state);
2142         NTSTATUS status;
2143
2144         status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
2145                                                   &state->r.out.result);
2146         TALLOC_FREE(subreq);
2147         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
2148                 state->r.out.result = WERR_TIMEOUT;
2149         } else if (!NT_STATUS_IS_OK(status)) {
2150                 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2151                 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
2152                          nt_errstr(status)));
2153         }
2154
2155         if (state->_r.l2ex != NULL) {
2156                 struct netr_LogonControl2Ex *r = state->_r.l2ex;
2157                 r->out.result = state->r.out.result;
2158         } else if (state->_r.l2 != NULL) {
2159                 struct netr_LogonControl2 *r = state->_r.l2;
2160                 r->out.result = state->r.out.result;
2161         } else if (state->_r.l != NULL) {
2162                 struct netr_LogonControl *r = state->_r.l;
2163                 r->out.result = state->r.out.result;
2164         }
2165
2166         status = dcesrv_reply(state->dce_call);
2167         if (!NT_STATUS_IS_OK(status)) {
2168                 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2169         }
2170 }
2171
2172 /*
2173   netr_LogonControl
2174 */
2175 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2176                        struct netr_LogonControl *r)
2177 {
2178         struct dcesrv_netr_LogonControl_base_state *state;
2179         WERROR werr;
2180
2181         state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
2182         if (state == NULL) {
2183                 return WERR_NOT_ENOUGH_MEMORY;
2184         }
2185
2186         state->dce_call = dce_call;
2187         state->mem_ctx = mem_ctx;
2188
2189         state->r.in.logon_server = r->in.logon_server;
2190         state->r.in.function_code = r->in.function_code;
2191         state->r.in.level = r->in.level;
2192         state->r.in.data = NULL;
2193         state->r.out.query = r->out.query;
2194
2195         state->_r.l = r;
2196
2197         werr = dcesrv_netr_LogonControl_base_call(state);
2198
2199         if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
2200                 return werr;
2201         }
2202
2203         return werr;
2204 }
2205
2206 /*
2207   netr_LogonControl2
2208 */
2209 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2210                        struct netr_LogonControl2 *r)
2211 {
2212         struct dcesrv_netr_LogonControl_base_state *state;
2213         WERROR werr;
2214
2215         state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
2216         if (state == NULL) {
2217                 return WERR_NOT_ENOUGH_MEMORY;
2218         }
2219
2220         state->dce_call = dce_call;
2221         state->mem_ctx = mem_ctx;
2222
2223         state->r.in.logon_server = r->in.logon_server;
2224         state->r.in.function_code = r->in.function_code;
2225         state->r.in.level = r->in.level;
2226         state->r.in.data = r->in.data;
2227         state->r.out.query = r->out.query;
2228
2229         state->_r.l2 = r;
2230
2231         werr = dcesrv_netr_LogonControl_base_call(state);
2232
2233         if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
2234                 return werr;
2235         }
2236
2237         return werr;
2238 }
2239
2240 /*
2241   netr_LogonControl2Ex
2242 */
2243 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2244                        struct netr_LogonControl2Ex *r)
2245 {
2246         struct dcesrv_netr_LogonControl_base_state *state;
2247         WERROR werr;
2248
2249         state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
2250         if (state == NULL) {
2251                 return WERR_NOT_ENOUGH_MEMORY;
2252         }
2253
2254         state->dce_call = dce_call;
2255         state->mem_ctx = mem_ctx;
2256
2257         state->r = *r;
2258         state->_r.l2ex = r;
2259
2260         werr = dcesrv_netr_LogonControl_base_call(state);
2261
2262         if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
2263                 return werr;
2264         }
2265
2266         return werr;
2267 }
2268
2269 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2270                                          struct ldb_context *sam_ctx,
2271                                          struct netr_DomainTrustList *trusts,
2272                                          uint32_t trust_flags);
2273
2274 /*
2275   netr_GetAnyDCName
2276 */
2277 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2278                        struct netr_GetAnyDCName *r)
2279 {
2280         struct netr_DomainTrustList *trusts;
2281         struct ldb_context *sam_ctx;
2282         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2283         uint32_t i;
2284         WERROR werr;
2285
2286         *r->out.dcname = NULL;
2287
2288         if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
2289                 /* if the domainname parameter wasn't set assume our domain */
2290                 r->in.domainname = lpcfg_workgroup(lp_ctx);
2291         }
2292
2293         sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2294         if (sam_ctx == NULL) {
2295                 return WERR_DS_UNAVAILABLE;
2296         }
2297
2298         if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
2299                 /* well we asked for a DC of our own domain */
2300                 if (samdb_is_pdc(sam_ctx)) {
2301                         /* we are the PDC of the specified domain */
2302                         return WERR_NO_SUCH_DOMAIN;
2303                 }
2304
2305                 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
2306                                                 lpcfg_netbios_name(lp_ctx));
2307                 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
2308
2309                 return WERR_OK;
2310         }
2311
2312         /* Okay, now we have to consider the trusted domains */
2313
2314         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2315         W_ERROR_HAVE_NO_MEMORY(trusts);
2316
2317         trusts->count = 0;
2318
2319         werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
2320                                           NETR_TRUST_FLAG_INBOUND
2321                                           | NETR_TRUST_FLAG_OUTBOUND);
2322         W_ERROR_NOT_OK_RETURN(werr);
2323
2324         for (i = 0; i < trusts->count; i++) {
2325                 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
2326                         /* FIXME: Here we need to find a DC for the specified
2327                          * trusted domain. */
2328
2329                         /* return WERR_OK; */
2330                         return WERR_NO_SUCH_DOMAIN;
2331                 }
2332         }
2333
2334         return WERR_NO_SUCH_DOMAIN;
2335 }
2336
2337
2338 /*
2339   netr_DatabaseRedo
2340 */
2341 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2342                        struct netr_DatabaseRedo *r)
2343 {
2344         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2345 }
2346
2347
2348 /*
2349   netr_NetrEnumerateTrustedDomains
2350 */
2351 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2352                        struct netr_NetrEnumerateTrustedDomains *r)
2353 {
2354         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2355 }
2356
2357
2358 /*
2359   netr_LogonGetCapabilities
2360 */
2361 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2362                        struct netr_LogonGetCapabilities *r)
2363 {
2364         struct netlogon_creds_CredentialState *creds;
2365         NTSTATUS status;
2366
2367         status = dcesrv_netr_creds_server_step_check(dce_call,
2368                                                      mem_ctx,
2369                                                      r->in.computer_name,
2370                                                      r->in.credential,
2371                                                      r->out.return_authenticator,
2372                                                      &creds);
2373         if (!NT_STATUS_IS_OK(status)) {
2374                 DEBUG(0,(__location__ " Bad credentials - error\n"));
2375         }
2376         NT_STATUS_NOT_OK_RETURN(status);
2377
2378         if (r->in.query_level != 1) {
2379                 return NT_STATUS_NOT_SUPPORTED;
2380         }
2381
2382         r->out.capabilities->server_capabilities = creds->negotiate_flags;
2383
2384         return NT_STATUS_OK;
2385 }
2386
2387
2388 /*
2389   netr_NETRLOGONSETSERVICEBITS
2390 */
2391 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2392                        struct netr_NETRLOGONSETSERVICEBITS *r)
2393 {
2394         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2395 }
2396
2397
2398 /*
2399   netr_LogonGetTrustRid
2400 */
2401 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2402                        struct netr_LogonGetTrustRid *r)
2403 {
2404         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2405 }
2406
2407
2408 /*
2409   netr_NETRLOGONCOMPUTESERVERDIGEST
2410 */
2411 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2412                        struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
2413 {
2414         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2415 }
2416
2417
2418 /*
2419   netr_NETRLOGONCOMPUTECLIENTDIGEST
2420 */
2421 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2422                        struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
2423 {
2424         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2425 }
2426
2427
2428
2429 /*
2430   netr_DsRGetSiteName
2431 */
2432 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2433                                   struct netr_DsRGetSiteName *r)
2434 {
2435         struct ldb_context *sam_ctx;
2436
2437         sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2438         if (sam_ctx == NULL) {
2439                 return WERR_DS_UNAVAILABLE;
2440         }
2441
2442         /*
2443          * We assume to be a DC when we get called over NETLOGON. Hence we
2444          * get our site name always by using "samdb_server_site_name()"
2445          * and not "samdb_client_site_name()".
2446          */
2447         *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
2448         W_ERROR_HAVE_NO_MEMORY(*r->out.site);
2449
2450         return WERR_OK;
2451 }
2452
2453
2454 /*
2455   fill in a netr_OneDomainInfo from our own domain/forest
2456 */
2457 static NTSTATUS fill_our_one_domain_info(TALLOC_CTX *mem_ctx,
2458                                 const struct lsa_TrustDomainInfoInfoEx *our_tdo,
2459                                 struct GUID domain_guid,
2460                                 struct netr_OneDomainInfo *info,
2461                                 bool is_trust_list)
2462 {
2463         ZERO_STRUCTP(info);
2464
2465         if (is_trust_list) {
2466                 struct netr_trust_extension *te = NULL;
2467                 struct netr_trust_extension_info *tei = NULL;
2468
2469                 /* w2k8 only fills this on trusted domains */
2470                 te = talloc_zero(mem_ctx, struct netr_trust_extension);
2471                 if (te == NULL) {
2472                         return NT_STATUS_NO_MEMORY;
2473                 }
2474                 tei = &te->info;
2475                 tei->flags |= NETR_TRUST_FLAG_PRIMARY;
2476
2477                 /*
2478                  * We're always within a native forest
2479                  */
2480                 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2481                 tei->flags |= NETR_TRUST_FLAG_NATIVE;
2482
2483                 /* For now we assume we're always the tree root */
2484                 tei->flags |= NETR_TRUST_FLAG_TREEROOT;
2485                 tei->parent_index = 0;
2486
2487                 tei->trust_type = our_tdo->trust_type;
2488                 /*
2489                  * This needs to be 0 instead of our_tdo->trust_attributes
2490                  * It means LSA_TRUST_ATTRIBUTE_WITHIN_FOREST won't
2491                  * be set, while NETR_TRUST_FLAG_IN_FOREST is set above.
2492                  */
2493                 tei->trust_attributes = 0;
2494
2495                 info->trust_extension.info = te;
2496         }
2497
2498         if (is_trust_list) {
2499                 info->dns_domainname.string = our_tdo->domain_name.string;
2500
2501                 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2502                 info->dns_forestname.string = NULL;
2503         } else {
2504                 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.",
2505                                                 our_tdo->domain_name.string);
2506                 if (info->dns_domainname.string == NULL) {
2507                         return NT_STATUS_NO_MEMORY;
2508                 }
2509
2510                 info->dns_forestname.string = info->dns_domainname.string;
2511         }
2512
2513         info->domainname.string = our_tdo->netbios_name.string;
2514         info->domain_sid = our_tdo->sid;
2515         info->domain_guid = domain_guid;
2516
2517         return NT_STATUS_OK;
2518 }
2519
2520 /*
2521   fill in a netr_OneDomainInfo from a trust tdo
2522 */
2523 static NTSTATUS fill_trust_one_domain_info(TALLOC_CTX *mem_ctx,
2524                                 struct GUID domain_guid,
2525                                 const struct lsa_TrustDomainInfoInfoEx *tdo,
2526                                 struct netr_OneDomainInfo *info)
2527 {
2528         struct netr_trust_extension *te = NULL;
2529         struct netr_trust_extension_info *tei = NULL;
2530
2531         ZERO_STRUCTP(info);
2532
2533         /* w2k8 only fills this on trusted domains */
2534         te = talloc_zero(mem_ctx, struct netr_trust_extension);
2535         if (te == NULL) {
2536                 return NT_STATUS_NO_MEMORY;
2537         }
2538         tei = &te->info;
2539
2540         if (tdo->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2541                 tei->flags |= NETR_TRUST_FLAG_INBOUND;
2542         }
2543         if (tdo->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2544                 tei->flags |= NETR_TRUST_FLAG_OUTBOUND;
2545         }
2546         if (tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
2547                 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2548         }
2549
2550         /*
2551          * TODO: once we support multiple domains within our forest,
2552          * we need to fill this correct (or let the caller do it
2553          * for all domains marked with NETR_TRUST_FLAG_IN_FOREST).
2554          */
2555         tei->parent_index = 0;
2556
2557         tei->trust_type = tdo->trust_type;
2558         tei->trust_attributes = tdo->trust_attributes;
2559
2560         info->trust_extension.info = te;
2561
2562         info->domainname.string = tdo->netbios_name.string;
2563         if (tdo->trust_type != LSA_TRUST_TYPE_DOWNLEVEL) {
2564                 info->dns_domainname.string = tdo->domain_name.string;
2565         } else {
2566                 info->dns_domainname.string = NULL;
2567         }
2568         info->domain_sid = tdo->sid;
2569         info->domain_guid = domain_guid;
2570
2571         /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2572         info->dns_forestname.string = NULL;
2573
2574         return NT_STATUS_OK;
2575 }
2576
2577 /*
2578   netr_LogonGetDomainInfo
2579   this is called as part of the ADS domain logon procedure.
2580
2581   It has an important role in convaying details about the client, such
2582   as Operating System, Version, Service Pack etc.
2583 */
2584 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
2585         TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
2586 {
2587         struct netlogon_creds_CredentialState *creds;
2588         const char * const trusts_attrs[] = {
2589                 "securityIdentifier",
2590                 "flatName",
2591                 "trustPartner",
2592                 "trustAttributes",
2593                 "trustDirection",
2594                 "trustType",
2595                 NULL
2596         };
2597         const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
2598                 "msDS-SupportedEncryptionTypes", NULL };
2599         const char *sam_account_name, *old_dns_hostname;
2600         struct ldb_context *sam_ctx;
2601         const struct GUID *our_domain_guid = NULL;
2602         struct lsa_TrustDomainInfoInfoEx *our_tdo = NULL;
2603         struct ldb_message **res1, *new_msg;
2604         struct ldb_result *trusts_res = NULL;
2605         struct ldb_dn *workstation_dn;
2606         struct netr_DomainInformation *domain_info;
2607         struct netr_LsaPolicyInformation *lsa_policy_info;
2608         struct auth_session_info *workstation_session_info = NULL;
2609         uint32_t default_supported_enc_types = 0xFFFFFFFF;
2610         bool update_dns_hostname = true;
2611         int ret, i;
2612         NTSTATUS status;
2613
2614         status = dcesrv_netr_creds_server_step_check(dce_call,
2615                                                      mem_ctx,
2616                                                      r->in.computer_name,
2617                                                      r->in.credential,
2618                                                      r->out.return_authenticator,
2619                                                      &creds);
2620         if (!NT_STATUS_IS_OK(status)) {
2621                 char* local  = NULL;
2622                 char* remote = NULL;
2623                 TALLOC_CTX *frame = talloc_stackframe();
2624                 remote = tsocket_address_string(dce_call->conn->remote_address,
2625                                                 frame);
2626                 local  = tsocket_address_string(dce_call->conn->local_address,
2627                                                 frame);
2628                 DBG_ERR(("Bad credentials - "
2629                          "computer[%s] remote[%s] local[%s]\n"),
2630                         log_escape(frame, r->in.computer_name),
2631                         remote,
2632                         local);
2633                 talloc_free(frame);
2634         }
2635         NT_STATUS_NOT_OK_RETURN(status);
2636
2637         /* We want to avoid connecting as system. */
2638         sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2639         if (sam_ctx == NULL) {
2640                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2641         }
2642
2643         switch (r->in.level) {
2644         case 1: /* Domain information */
2645
2646                 if (r->in.query->workstation_info == NULL) {
2647                         return NT_STATUS_INVALID_PARAMETER;
2648                 }
2649
2650                 /* Prepares the workstation DN */
2651                 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2652                                                 dom_sid_string(mem_ctx, creds->sid));
2653                 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
2654
2655                 /* Get the workstation's session info from the database. */
2656                 status = authsam_get_session_info_principal(mem_ctx,
2657                                                             dce_call->conn->dce_ctx->lp_ctx,
2658                                                             sam_ctx,
2659                                                             NULL, /* principal */
2660                                                             workstation_dn,
2661                                                             0, /* session_info_flags */
2662                                                             &workstation_session_info);
2663                 if (!NT_STATUS_IS_OK(status)) {
2664                         return status;
2665                 }
2666
2667                 /*
2668                  * Reconnect to samdb as the workstation, now that we have its
2669                  * session info. We do this so the database update can be
2670                  * attributed to the workstation account in the audit logs --
2671                  * otherwise it might be incorrectly attributed to
2672                  * SID_NT_ANONYMOUS.
2673                  */
2674                 sam_ctx = dcesrv_samdb_connect_session_info(mem_ctx,
2675                                                             dce_call,
2676                                                             workstation_session_info,
2677                                                             workstation_session_info);
2678                 if (sam_ctx == NULL) {
2679                         return NT_STATUS_INVALID_SYSTEM_SERVICE;
2680                 }
2681
2682                 /* Lookup for attributes in workstation object */
2683                 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
2684                                       attrs2);
2685                 if (ret != 1) {
2686                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2687                 }
2688
2689                 /* Gets the sam account name which is checked against the DNS
2690                  * hostname parameter. */
2691                 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
2692                                                                "sAMAccountName",
2693                                                                NULL);
2694                 if (sam_account_name == NULL) {
2695                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2696                 }
2697
2698                 if (r->in.query->workstation_info->dns_hostname == NULL) {
2699                         update_dns_hostname = false;
2700                 }
2701
2702                 /* Gets the old DNS hostname */
2703                 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
2704                                                                "dNSHostName",
2705                                                                NULL);
2706
2707                 /*
2708                  * Updates the DNS hostname when the client wishes that the
2709                  * server should handle this for him
2710                  * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
2711                  * See MS-NRPC section 3.5.4.3.9
2712                  */
2713                 if ((r->in.query->workstation_info->workstation_flags
2714                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2715                         update_dns_hostname = false;
2716                 }
2717
2718                 /* Gets host information and put them into our directory */
2719
2720                 new_msg = ldb_msg_new(mem_ctx);
2721                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
2722
2723                 new_msg->dn = workstation_dn;
2724
2725                 /* Sets the OS name */
2726
2727                 if (r->in.query->workstation_info->os_name.string == NULL) {
2728                         return NT_STATUS_INVALID_PARAMETER;
2729                 }
2730
2731                 ret = ldb_msg_add_string(new_msg, "operatingSystem",
2732                                          r->in.query->workstation_info->os_name.string);
2733                 if (ret != LDB_SUCCESS) {
2734                         return NT_STATUS_NO_MEMORY;
2735                 }
2736
2737                 /*
2738                  * Sets information from "os_version". On an empty structure
2739                  * the values are cleared.
2740                  */
2741                 if (r->in.query->workstation_info->os_version.os != NULL) {
2742                         struct netr_OsVersionInfoEx *os_version;
2743                         const char *os_version_str;
2744
2745                         os_version = &r->in.query->workstation_info->os_version.os->os;
2746
2747                         if (os_version->CSDVersion == NULL) {
2748                                 return NT_STATUS_INVALID_PARAMETER;
2749                         }
2750
2751                         os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
2752                                                          os_version->MajorVersion,
2753                                                          os_version->MinorVersion,
2754                                                          os_version->BuildNumber);
2755                         NT_STATUS_HAVE_NO_MEMORY(os_version_str);
2756
2757                         if (strlen(os_version->CSDVersion) != 0) {
2758                                 ret = ldb_msg_add_string(new_msg,
2759                                                          "operatingSystemServicePack",
2760                                                          os_version->CSDVersion);
2761                         } else {
2762                                 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2763                                                            "operatingSystemServicePack");
2764                         }
2765                         if (ret != LDB_SUCCESS) {
2766                                 return NT_STATUS_NO_MEMORY;
2767                         }
2768
2769                         ret = ldb_msg_add_string(new_msg,
2770                                                  "operatingSystemVersion",
2771                                                  os_version_str);
2772                         if (ret != LDB_SUCCESS) {
2773                                 return NT_STATUS_NO_MEMORY;
2774                         }
2775                 } else {
2776                         ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2777                                                    "operatingSystemServicePack");
2778                         if (ret != LDB_SUCCESS) {
2779                                 return NT_STATUS_NO_MEMORY;
2780                         }
2781
2782                         ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2783                                                    "operatingSystemVersion");
2784                         if (ret != LDB_SUCCESS) {
2785                                 return NT_STATUS_NO_MEMORY;
2786                         }
2787                 }
2788
2789                 /*
2790                  * If the boolean "update_dns_hostname" remained true, then we
2791                  * are fine to start the update.
2792                  */
2793                 if (update_dns_hostname) {
2794                         ret = ldb_msg_add_string(new_msg,
2795                                                  "dNSHostname",
2796                                                  r->in.query->workstation_info->dns_hostname);
2797                         if (ret != LDB_SUCCESS) {
2798                                 return NT_STATUS_NO_MEMORY;
2799                         }
2800
2801                         /* This manual "servicePrincipalName" generation is
2802                          * still needed! Since the update in the samldb LDB
2803                          * module does only work if the entries already exist
2804                          * which isn't always the case. */
2805                         ret = ldb_msg_add_string(new_msg,
2806                                                  "servicePrincipalName",
2807                                                  talloc_asprintf(new_msg, "HOST/%s",
2808                                                  r->in.computer_name));
2809                         if (ret != LDB_SUCCESS) {
2810                                 return NT_STATUS_NO_MEMORY;
2811                         }
2812
2813                         ret = ldb_msg_add_string(new_msg,
2814                                                  "servicePrincipalName",
2815                                                  talloc_asprintf(new_msg, "HOST/%s",
2816                                                  r->in.query->workstation_info->dns_hostname));
2817                         if (ret != LDB_SUCCESS) {
2818                                 return NT_STATUS_NO_MEMORY;
2819                         }
2820                 }
2821
2822                 if (dsdb_replace(sam_ctx, new_msg, DSDB_FLAG_FORCE_ALLOW_VALIDATED_DNS_HOSTNAME_SPN_WRITE) != LDB_SUCCESS) {
2823                         DEBUG(3,("Impossible to update samdb: %s\n",
2824                                 ldb_errstring(sam_ctx)));
2825                 }
2826
2827                 talloc_free(new_msg);
2828
2829                 /* Writes back the domain information */
2830
2831                 our_domain_guid = samdb_domain_guid(sam_ctx);
2832                 if (our_domain_guid == NULL) {
2833                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2834                 }
2835
2836                 status = dsdb_trust_local_tdo_info(mem_ctx, sam_ctx, &our_tdo);
2837                 if (!NT_STATUS_IS_OK(status)) {
2838                         return status;
2839                 }
2840
2841                 status = dsdb_trust_search_tdos(sam_ctx,
2842                                                 NULL, /* exclude */
2843                                                 trusts_attrs,
2844                                                 mem_ctx,
2845                                                 &trusts_res);
2846                 if (!NT_STATUS_IS_OK(status)) {
2847                         return status;
2848                 }
2849
2850                 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
2851                 NT_STATUS_HAVE_NO_MEMORY(domain_info);
2852
2853                 ZERO_STRUCTP(domain_info);
2854
2855                 /* Informations about the local and trusted domains */
2856
2857                 status = fill_our_one_domain_info(mem_ctx,
2858                                                   our_tdo,
2859                                                   *our_domain_guid,
2860                                                   &domain_info->primary_domain,
2861                                                   false);
2862                 if (!NT_STATUS_IS_OK(status)) {
2863                         return status;
2864                 }
2865
2866                 domain_info->trusted_domain_count = trusts_res->count + 1;
2867                 domain_info->trusted_domains = talloc_zero_array(mem_ctx,
2868                         struct netr_OneDomainInfo,
2869                         domain_info->trusted_domain_count);
2870                 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
2871
2872                 for (i=0; i < trusts_res->count; i++) {
2873                         struct netr_OneDomainInfo *o =
2874                                 &domain_info->trusted_domains[i];
2875                         /* we can't know the guid of trusts outside our forest */
2876                         struct GUID trust_domain_guid = GUID_zero();
2877                         struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
2878
2879                         status = dsdb_trust_parse_tdo_info(mem_ctx,
2880                                                            trusts_res->msgs[i],
2881                                                            &tdo);
2882                         if (!NT_STATUS_IS_OK(status)) {
2883                                 return status;
2884                         }
2885
2886                         status = fill_trust_one_domain_info(mem_ctx,
2887                                                             trust_domain_guid,
2888                                                             tdo,
2889                                                             o);
2890                         if (!NT_STATUS_IS_OK(status)) {
2891                                 return status;
2892                         }
2893                 }
2894
2895                 status = fill_our_one_domain_info(mem_ctx,
2896                                                   our_tdo,
2897                                                   *our_domain_guid,
2898                                                   &domain_info->trusted_domains[i],
2899                                                   true);
2900                 if (!NT_STATUS_IS_OK(status)) {
2901                         return status;
2902                 }
2903
2904                 /* Sets the supported encryption types */
2905                 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
2906                         "msDS-SupportedEncryptionTypes",
2907                         default_supported_enc_types);
2908
2909                 /* Other host domain information */
2910
2911                 lsa_policy_info = talloc(mem_ctx,
2912                         struct netr_LsaPolicyInformation);
2913                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2914                 ZERO_STRUCTP(lsa_policy_info);
2915
2916                 domain_info->lsa_policy = *lsa_policy_info;
2917
2918                 /* The DNS hostname is only returned back when there is a chance
2919                  * for a change. */
2920                 if ((r->in.query->workstation_info->workstation_flags
2921                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2922                         domain_info->dns_hostname.string = old_dns_hostname;
2923                 } else {
2924                         domain_info->dns_hostname.string = NULL;
2925                 }
2926
2927                 domain_info->workstation_flags =
2928                         r->in.query->workstation_info->workstation_flags & (
2929                         NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
2930
2931                 r->out.info->domain_info = domain_info;
2932         break;
2933         case 2: /* LSA policy information - not used at the moment */
2934                 lsa_policy_info = talloc(mem_ctx,
2935                         struct netr_LsaPolicyInformation);
2936                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2937                 ZERO_STRUCTP(lsa_policy_info);
2938
2939                 r->out.info->lsa_policy_info = lsa_policy_info;
2940         break;
2941         default:
2942                 return NT_STATUS_INVALID_LEVEL;
2943         break;
2944         }
2945
2946         return NT_STATUS_OK;
2947 }
2948
2949
2950 /*
2951   netr_ServerPasswordGet
2952 */
2953 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2954                        struct netr_ServerPasswordGet *r)
2955 {
2956         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2957 }
2958
2959 static bool sam_rodc_access_check(struct ldb_context *sam_ctx,
2960                                   TALLOC_CTX *mem_ctx,
2961                                   struct dom_sid *user_sid,
2962                                   struct ldb_dn *obj_dn)
2963 {
2964         const char *rodc_attrs[] = { "msDS-NeverRevealGroup",
2965                                      "msDS-RevealOnDemandGroup",
2966                                      "userAccountControl",
2967                                      NULL };
2968         const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL };
2969         struct ldb_dn *rodc_dn;
2970         int ret;
2971         struct ldb_result *rodc_res = NULL, *obj_res = NULL;
2972         WERROR werr;
2973
2974         rodc_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2975                                  dom_sid_string(mem_ctx, user_sid));
2976         if (!ldb_dn_validate(rodc_dn)) goto denied;
2977
2978         /*
2979          * do the two searches we need
2980          * We need DSDB_SEARCH_SHOW_EXTENDED_DN as we get a SID list
2981          * out of the extended DNs
2982          */
2983         ret = dsdb_search_dn(sam_ctx, mem_ctx, &rodc_res, rodc_dn, rodc_attrs,
2984                              DSDB_SEARCH_SHOW_EXTENDED_DN);
2985         if (ret != LDB_SUCCESS || rodc_res->count != 1) goto denied;
2986
2987         ret = dsdb_search_dn(sam_ctx, mem_ctx, &obj_res, obj_dn, obj_attrs, 0);
2988         if (ret != LDB_SUCCESS || obj_res->count != 1) goto denied;
2989
2990         werr = samdb_confirm_rodc_allowed_to_repl_to(sam_ctx,
2991                                                      user_sid,
2992                                                      rodc_res->msgs[0],
2993                                                      obj_res->msgs[0]);
2994
2995         if (W_ERROR_IS_OK(werr)) {
2996                 goto allowed;
2997         }
2998 denied:
2999         return false;
3000 allowed:
3001         return true;
3002
3003 }
3004
3005 /*
3006   netr_NetrLogonSendToSam
3007 */
3008 static NTSTATUS dcesrv_netr_NetrLogonSendToSam(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3009                                                struct netr_NetrLogonSendToSam *r)
3010 {
3011         struct netlogon_creds_CredentialState *creds;
3012         struct ldb_context *sam_ctx;
3013         NTSTATUS nt_status;
3014         DATA_BLOB decrypted_blob;
3015         enum ndr_err_code ndr_err;
3016         struct netr_SendToSamBase base_msg = { 0 };
3017
3018         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3019                                                         mem_ctx,
3020                                                         r->in.computer_name,
3021                                                         r->in.credential,
3022                                                         r->out.return_authenticator,
3023                                                         &creds);
3024
3025         NT_STATUS_NOT_OK_RETURN(nt_status);
3026
3027         switch (creds->secure_channel_type) {
3028         case SEC_CHAN_BDC:
3029         case SEC_CHAN_RODC:
3030                 break;
3031         case SEC_CHAN_WKSTA:
3032         case SEC_CHAN_DNS_DOMAIN:
3033         case SEC_CHAN_DOMAIN:
3034         case SEC_CHAN_NULL:
3035                 return NT_STATUS_INVALID_PARAMETER;
3036         default:
3037                 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
3038                           creds->secure_channel_type));
3039                 return NT_STATUS_INVALID_PARAMETER;
3040         }
3041
3042         sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
3043         if (sam_ctx == NULL) {
3044                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
3045         }
3046
3047         /* Buffer is meant to be 16-bit aligned */
3048         if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
3049                 nt_status = netlogon_creds_aes_decrypt(creds,
3050                                                        r->in.opaque_buffer,
3051                                                        r->in.buffer_len);
3052         } else {
3053                 nt_status = netlogon_creds_arcfour_crypt(creds,
3054                                                          r->in.opaque_buffer,
3055                                                          r->in.buffer_len);
3056         }
3057         if (!NT_STATUS_IS_OK(nt_status)) {
3058                 return nt_status;
3059         }
3060
3061         decrypted_blob.data = r->in.opaque_buffer;
3062         decrypted_blob.length = r->in.buffer_len;
3063
3064         ndr_err = ndr_pull_struct_blob(&decrypted_blob, mem_ctx, &base_msg,
3065                                        (ndr_pull_flags_fn_t)ndr_pull_netr_SendToSamBase);
3066
3067         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3068                 /* We only partially implement SendToSam */
3069                 return NT_STATUS_NOT_IMPLEMENTED;
3070         }
3071
3072         /* Now 'send' to SAM */
3073         switch (base_msg.message_type) {
3074         case SendToSamResetBadPasswordCount:
3075         {
3076                 struct ldb_message *msg = ldb_msg_new(mem_ctx);
3077                 struct ldb_dn *dn = NULL;
3078                 int ret = 0;
3079
3080
3081                 ret = ldb_transaction_start(sam_ctx);
3082                 if (ret != LDB_SUCCESS) {
3083                         return NT_STATUS_INTERNAL_ERROR;
3084                 }
3085
3086                 ret = dsdb_find_dn_by_guid(sam_ctx,
3087                                            mem_ctx,
3088                                            &base_msg.message.reset_bad_password.guid,
3089                                            0,
3090                                            &dn);
3091                 if (ret != LDB_SUCCESS) {
3092                         ldb_transaction_cancel(sam_ctx);
3093                         return NT_STATUS_INVALID_PARAMETER;
3094                 }
3095
3096                 if (creds->secure_channel_type == SEC_CHAN_RODC &&
3097                     !sam_rodc_access_check(sam_ctx, mem_ctx, creds->sid, dn)) {
3098                         DEBUG(1, ("Client asked to reset bad password on "
3099                                   "an arbitrary user: %s\n",
3100                                   ldb_dn_get_linearized(dn)));
3101                         ldb_transaction_cancel(sam_ctx);
3102                         return NT_STATUS_INVALID_PARAMETER;
3103                 }
3104
3105                 msg->dn = dn;
3106
3107                 ret = samdb_msg_add_int(sam_ctx, mem_ctx, msg, "badPwdCount", 0);
3108                 if (ret != LDB_SUCCESS) {
3109                         ldb_transaction_cancel(sam_ctx);
3110                         return NT_STATUS_INVALID_PARAMETER;
3111                 }
3112
3113                 ret = dsdb_replace(sam_ctx, msg, 0);
3114                 if (ret != LDB_SUCCESS) {
3115                         ldb_transaction_cancel(sam_ctx);
3116                         return NT_STATUS_INVALID_PARAMETER;
3117                 }
3118
3119                 ret = ldb_transaction_commit(sam_ctx);
3120                 if (ret != LDB_SUCCESS) {
3121                         ldb_transaction_cancel(sam_ctx);
3122                         return NT_STATUS_INTERNAL_ERROR;
3123                 }
3124
3125                 break;
3126         }
3127         default:
3128                 return NT_STATUS_NOT_IMPLEMENTED;
3129         }
3130
3131         return NT_STATUS_OK;
3132 }
3133
3134 struct dcesrv_netr_DsRGetDCName_base_state {
3135         struct dcesrv_call_state *dce_call;
3136         TALLOC_CTX *mem_ctx;
3137
3138         struct netr_DsRGetDCNameEx2 r;
3139         const char *client_site;
3140
3141         struct {
3142                 struct netr_DsRGetDCName *dc;
3143                 struct netr_DsRGetDCNameEx *dcex;
3144                 struct netr_DsRGetDCNameEx2 *dcex2;
3145         } _r;
3146 };
3147
3148 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq);
3149
3150 /* Returns a nonzero value if multiple bits in 'val' are set. */
3151 static bool multiple_bits_set(uint32_t val)
3152 {
3153         /*
3154          * Subtracting one from an integer has the effect of flipping all the
3155          * bits from the least significant bit up to and including the least
3156          * significant '1' bit. For example,
3157          *
3158          *   0b101000 - 1
3159          * = 0b100111
3160          *       ====
3161          *
3162          * If 'val' is zero, all the bits will be flipped and thus the bitwise
3163          * AND of 'val' with 'val - 1' will be zero.
3164          *
3165          * If the integer is nonzero, the least significant '1' bit will be
3166          * ANDed with a '0' bit and so will be reset in the final result, but
3167          * all other '1' bits will remain set. In other words, the effect of
3168          * this expression is to mask off the least significant bit that is
3169          * set. Therefore iff the result of 'val & (val - 1)' is non-zero, 'val'
3170          * must contain multiple set bits.
3171          */
3172         return val & (val - 1);
3173 }
3174
3175 static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName_base_state *state)
3176 {
3177         struct dcesrv_call_state *dce_call = state->dce_call;
3178         struct imessaging_context *imsg_ctx =
3179                 dcesrv_imessaging_context(dce_call->conn);
3180         TALLOC_CTX *mem_ctx = state->mem_ctx;
3181         struct netr_DsRGetDCNameEx2 *r = &state->r;
3182         struct ldb_context *sam_ctx;
3183         struct netr_DsRGetDCNameInfo *info;
3184         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3185         const struct tsocket_address *local_address;
3186         char *local_addr = NULL;
3187         const struct tsocket_address *remote_address;
3188         char *remote_addr = NULL;
3189         const char *server_site_name;
3190         char *guid_str;
3191         struct netlogon_samlogon_response response;
3192         NTSTATUS status;
3193         const char *dc_name = NULL;
3194         const char *domain_name = NULL;
3195         const char *pdc_ip;
3196         bool different_domain = true;
3197         bool force_remote_lookup = false;
3198         uint32_t valid_flags;
3199         uint32_t this_dc_valid_flags;
3200         int dc_level;
3201
3202         ZERO_STRUCTP(r->out.info);
3203
3204         sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
3205         if (sam_ctx == NULL) {
3206                 return WERR_DS_UNAVAILABLE;
3207         }
3208
3209         local_address = dcesrv_connection_get_local_address(dce_call->conn);
3210         if (tsocket_address_is_inet(local_address, "ip")) {
3211                 local_addr = tsocket_address_inet_addr_string(local_address, state);
3212                 W_ERROR_HAVE_NO_MEMORY(local_addr);
3213         }
3214
3215         remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
3216         if (tsocket_address_is_inet(remote_address, "ip")) {
3217                 remote_addr = tsocket_address_inet_addr_string(remote_address, state);
3218                 W_ERROR_HAVE_NO_MEMORY(remote_addr);
3219         }
3220
3221         /* "server_unc" is ignored by w2k3 */
3222
3223         /*
3224          * With the following flags:
3225          * DS_FORCE_REDISCOVERY (Flag A)
3226          * DS_DIRECTORY_SERVICE_REQUIRED (Flag B)
3227          * DS_DIRECTORY_SERVICE_PREFERRED (Flag C)
3228          * DS_GC_SERVER_REQUIRED (Flag D)
3229          * DS_PDC_REQUIRED (Flag E)
3230          * DS_BACKGROUND_ONLY (Flag F)
3231          * DS_IP_REQUIRED (Flag G)
3232          * DS_KDC_REQUIRED (Flag H)
3233          * DS_TIMESERV_REQUIRED (Flag I)
3234          * DS_WRITABLE_REQUIRED (Flag J)
3235          * DS_GOOD_TIMESERV_PREFERRED (Flag K)
3236          * DS_AVOID_SELF (Flag L)
3237          * DS_ONLY_LDAP_NEEDED (Flag M)
3238          * DS_IS_FLAT_NAME (Flag N)
3239          * DS_IS_DNS_NAME (Flag O)
3240          * DS_TRY_NEXTCLOSEST_SITE (Flag P)
3241          * DS_DIRECTORY_SERVICE_6_REQUIRED  (Flag Q)
3242          * DS_WEB_SERVICE_REQUIRED (Flag T)
3243          * DS_DIRECTORY_SERVICE_8_REQUIRED  (Flag U)
3244          * DS_DIRECTORY_SERVICE_9_REQUIRED  (Flag V)
3245          * DS_DIRECTORY_SERVICE_10_REQUIRED (Flag W)
3246          * DS_RETURN_DNS_NAME (Flag R)
3247          * DS_RETURN_FLAT_NAME (Flag S)
3248          *
3249          * MS-NRPC 3.5.4.3.1 says:
3250          * ...
3251          * On receiving this call, the server MUST perform the following Flags
3252          * parameter validations:
3253          * - Flags D, E, and H MUST NOT be combined with each other.
3254          * - Flag N MUST NOT be combined with the O flag.
3255          * - Flag R MUST NOT be combined with the S flag.
3256          * - Flags B, Q, U, V, and W MUST NOT be combined with each other.
3257          * - Flag K MUST NOT be combined with any of the flags: B, C, D, E, or H.
3258          * - Flag P MUST NOT be set when the SiteName parameter is provided.
3259          * The server MUST return ERROR_INVALID_FLAGS for any of the previously
3260          * mentioned conflicting combinations.
3261          * ...
3262          */
3263
3264         valid_flags = DSGETDC_VALID_FLAGS;
3265
3266         if (r->in.flags & ~valid_flags) {
3267                 /*
3268                  * TODO: add tests to prove this (maybe based on the
3269                  * msDS-Behavior-Version levels of dc, domain and/or forest
3270                  */
3271                 return WERR_INVALID_FLAGS;
3272         }
3273
3274         /* Flags D, E, and H MUST NOT be combined with each other. */
3275 #define _DEH (DS_GC_SERVER_REQUIRED|DS_PDC_REQUIRED|DS_KDC_REQUIRED)
3276         if (multiple_bits_set(r->in.flags & _DEH)) {
3277                 return WERR_INVALID_FLAGS;
3278         }
3279
3280         /* Flag N MUST NOT be combined with the O flag. */
3281         if (r->in.flags & DS_IS_FLAT_NAME &&
3282             r->in.flags & DS_IS_DNS_NAME) {
3283                 return WERR_INVALID_FLAGS;
3284         }
3285
3286         /* Flag R MUST NOT be combined with the S flag. */
3287         if (r->in.flags & DS_RETURN_DNS_NAME &&
3288             r->in.flags & DS_RETURN_FLAT_NAME) {
3289                 return WERR_INVALID_FLAGS;
3290         }
3291
3292         /* Flags B, Q, U, V, and W MUST NOT be combined with each other */
3293 #define _BQUVW ( \
3294         DS_DIRECTORY_SERVICE_REQUIRED | \
3295         DS_DIRECTORY_SERVICE_6_REQUIRED | \
3296         DS_DIRECTORY_SERVICE_8_REQUIRED | \
3297         DS_DIRECTORY_SERVICE_9_REQUIRED | \
3298         DS_DIRECTORY_SERVICE_10_REQUIRED | \
3299 0)
3300         if (multiple_bits_set(r->in.flags & _BQUVW)) {
3301                 return WERR_INVALID_FLAGS;
3302         }
3303
3304         /*
3305          * Flag K MUST NOT be combined with any of the flags:
3306          * B, C, D, E, or H.
3307          */
3308         if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
3309             r->in.flags &
3310             (DS_DIRECTORY_SERVICE_REQUIRED |
3311              DS_DIRECTORY_SERVICE_PREFERRED |
3312              DS_GC_SERVER_REQUIRED |
3313              DS_PDC_REQUIRED |
3314              DS_KDC_REQUIRED)) {
3315                 return WERR_INVALID_FLAGS;
3316         }
3317
3318         /* Flag P MUST NOT be set when the SiteName parameter is provided. */
3319         if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
3320             r->in.site_name) {
3321                 return WERR_INVALID_FLAGS;
3322         }
3323
3324         /*
3325          * If we send an all-zero GUID, we should ignore it as winbind actually
3326          * checks it with a DNS query. Windows also appears to ignore it.
3327          */
3328         if (r->in.domain_guid != NULL && GUID_all_zero(r->in.domain_guid)) {
3329                 r->in.domain_guid = NULL;
3330         }
3331
3332         /* Attempt winbind search only if we suspect the domain is incorrect */
3333         if (r->in.domain_name != NULL && strcmp("", r->in.domain_name) != 0) {
3334                 if (r->in.flags & DS_IS_FLAT_NAME) {
3335                         if (strcasecmp_m(r->in.domain_name,
3336                                          lpcfg_sam_name(lp_ctx)) == 0) {
3337                                 different_domain = false;
3338                         }
3339                 } else if (r->in.flags & DS_IS_DNS_NAME) {
3340                         if (strcasecmp_m(r->in.domain_name,
3341                                          lpcfg_dnsdomain(lp_ctx)) == 0) {
3342                                 different_domain = false;
3343                         }
3344                 } else {
3345                         if (strcasecmp_m(r->in.domain_name,
3346                                          lpcfg_sam_name(lp_ctx)) == 0 ||
3347                             strcasecmp_m(r->in.domain_name,
3348                                          lpcfg_dnsdomain(lp_ctx)) == 0) {
3349                                 different_domain = false;
3350                         }
3351                 }
3352         } else {
3353                 /*
3354                  * We need to be able to handle empty domain names, where we
3355                  * revert to our domain by default.
3356                  */
3357                 different_domain = false;
3358         }
3359
3360         if (!different_domain) {
3361                 dc_level = dsdb_dc_functional_level(sam_ctx);
3362
3363                 /*
3364                  * Do not return a local response if we do not support the
3365                  * functional level or feature (eg web services)
3366                  */
3367                 this_dc_valid_flags = valid_flags;
3368
3369                 /* Samba does not implement this */
3370                 this_dc_valid_flags &= ~DS_WEB_SERVICE_REQUIRED;
3371
3372                 if (dc_level < DS_DOMAIN_FUNCTION_2012) {
3373                         this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_8_REQUIRED;
3374                 }
3375                 if (dc_level < DS_DOMAIN_FUNCTION_2012_R2) {
3376                         this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_9_REQUIRED;
3377                 }
3378                 if (dc_level < DS_DOMAIN_FUNCTION_2016) {
3379                         this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_10_REQUIRED;
3380                 }
3381                 if (r->in.flags & ~this_dc_valid_flags) {
3382                         DBG_INFO("Forcing remote lookup to find another DC "
3383                                  "in this domain %s with more features, "
3384                                  "as this Samba DC is Functional level %d but flags are 0x08%x\n",
3385                                  r->in.domain_name, dc_level, (unsigned int)r->in.flags);
3386                         force_remote_lookup = true;
3387                 }
3388         }
3389
3390         /* Proof server site parameter "site_name" if it was specified */
3391         server_site_name = samdb_server_site_name(sam_ctx, state);
3392         W_ERROR_HAVE_NO_MEMORY(server_site_name);
3393         if (force_remote_lookup
3394             || different_domain
3395             || (r->in.site_name != NULL &&
3396                 (strcasecmp_m(r->in.site_name,
3397                               server_site_name) != 0))) {
3398
3399                 struct dcerpc_binding_handle *irpc_handle = NULL;
3400                 struct tevent_req *subreq = NULL;
3401
3402                 /*
3403                  * Retrieve the client site to override the winbind response.
3404                  *
3405                  * DO NOT use Windows fallback for client site.
3406                  * In the case of multiple domains, this is plainly wrong.
3407                  *
3408                  * Note: It's possible that the client may belong to multiple
3409                  * subnets across domains. It's not clear what this would mean,
3410                  * but here we only return what this domain knows.
3411                  */
3412                 state->client_site = samdb_client_site_name(sam_ctx,
3413                                                             state,
3414                                                             remote_addr,
3415                                                             NULL,
3416                                                             false);
3417
3418                 irpc_handle = irpc_binding_handle_by_name(state,
3419                                                           imsg_ctx,
3420                                                           "winbind_server",
3421                                                           &ndr_table_winbind);
3422                 if (irpc_handle == NULL) {
3423                         DEBUG(0,("Failed to get binding_handle for "
3424                                  "winbind_server task\n"));
3425                         dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3426                         return WERR_SERVICE_NOT_FOUND;
3427                 }
3428
3429                 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3430
3431                 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3432
3433                 subreq = dcerpc_wbint_DsGetDcName_send(state,
3434                                                        dce_call->event_ctx,
3435                                                        irpc_handle,
3436                                                        r->in.domain_name,
3437                                                        r->in.domain_guid,
3438                                                        r->in.site_name,
3439                                                        r->in.flags,
3440                                                        r->out.info);
3441                 if (subreq == NULL) {
3442                         return WERR_NOT_ENOUGH_MEMORY;
3443                 }
3444
3445                 tevent_req_set_callback(subreq,
3446                                         dcesrv_netr_DsRGetDCName_base_done,
3447                                         state);
3448
3449                 return WERR_OK;
3450         }
3451
3452         guid_str = r->in.domain_guid != NULL ?
3453                  GUID_string(state, r->in.domain_guid) : NULL;
3454
3455         status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
3456                                                  r->in.domain_name,
3457                                                  r->in.domain_name,
3458                                                  NULL, guid_str,
3459                                                  r->in.client_account,
3460                                                  r->in.mask, remote_addr,
3461                                                  NETLOGON_NT_VERSION_5EX_WITH_IP,
3462                                                  lp_ctx, &response, true);
3463         if (!NT_STATUS_IS_OK(status)) {
3464                 return ntstatus_to_werror(status);
3465         }
3466
3467         /*
3468          * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
3469          * (O) flag when the returned forest name is in DNS format. This is here
3470          * always the case (see below).
3471          */
3472         response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
3473
3474         if (r->in.flags & DS_RETURN_DNS_NAME) {
3475                 dc_name = response.data.nt5_ex.pdc_dns_name;
3476                 domain_name = response.data.nt5_ex.dns_domain;
3477                 /*
3478                  * According to MS-NRPC 2.2.1.2.1 we should set the
3479                  * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
3480                  * the returned information is in DNS form.
3481                  */
3482                 response.data.nt5_ex.server_type |=
3483                         DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
3484         } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
3485                 dc_name = response.data.nt5_ex.pdc_name;
3486                 domain_name = response.data.nt5_ex.domain_name;
3487         } else {
3488
3489                 /*
3490                  * TODO: autodetect what we need to return
3491                  * based on the given arguments
3492                  */
3493                 dc_name = response.data.nt5_ex.pdc_name;
3494                 domain_name = response.data.nt5_ex.domain_name;
3495         }
3496
3497         if (!dc_name || !dc_name[0]) {
3498                 return WERR_NO_SUCH_DOMAIN;
3499         }
3500
3501         if (!domain_name || !domain_name[0]) {
3502                 return WERR_NO_SUCH_DOMAIN;
3503         }
3504
3505         info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
3506         W_ERROR_HAVE_NO_MEMORY(info);
3507         info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
3508                         dc_name[0] != '\\'? "\\\\":"",
3509                         talloc_strdup(mem_ctx, dc_name));
3510         W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
3511
3512         pdc_ip = local_addr;
3513         if (pdc_ip == NULL) {
3514                 pdc_ip = "127.0.0.1";
3515         }
3516         info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
3517         W_ERROR_HAVE_NO_MEMORY(info->dc_address);
3518         info->dc_address_type  = DS_ADDRESS_TYPE_INET;
3519         info->domain_guid      = response.data.nt5_ex.domain_uuid;
3520         info->domain_name      = domain_name;
3521         info->forest_name      = response.data.nt5_ex.forest;
3522         info->dc_flags         = response.data.nt5_ex.server_type;
3523         if (r->in.flags & DS_RETURN_DNS_NAME) {
3524                 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
3525                  * returned if we are returning info->dc_unc containing a FQDN.
3526                  * This attribute is called DomainControllerName in the specs,
3527                  * it seems that we decide to return FQDN or netbios depending on
3528                  * DS_RETURN_DNS_NAME.
3529                  */
3530                 info->dc_flags |= DS_DNS_CONTROLLER;
3531         }
3532         info->dc_site_name     = response.data.nt5_ex.server_site;
3533         info->client_site_name = response.data.nt5_ex.client_site;
3534
3535         *r->out.info = info;
3536
3537         return WERR_OK;
3538 }
3539
3540 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq)
3541 {
3542         struct dcesrv_netr_DsRGetDCName_base_state *state =
3543                 tevent_req_callback_data(subreq,
3544                 struct dcesrv_netr_DsRGetDCName_base_state);
3545         struct dcesrv_call_state *dce_call = state->dce_call;
3546         NTSTATUS result, status;
3547
3548         status = dcerpc_wbint_DsGetDcName_recv(subreq,
3549                                                state->mem_ctx,
3550                                                &result);
3551         TALLOC_FREE(subreq);
3552
3553         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3554                 state->r.out.result = WERR_TIMEOUT;
3555                 goto finished;
3556         }
3557
3558         if (!NT_STATUS_IS_OK(status)) {
3559                 DBG_ERR(__location__ ": IRPC callback failed %s\n",
3560                         nt_errstr(status));
3561                 state->r.out.result = WERR_GEN_FAILURE;
3562                 goto finished;
3563         }
3564
3565         if (!NT_STATUS_IS_OK(result)) {
3566                 DBG_NOTICE("DC location via winbind failed - %s\n",
3567                            nt_errstr(result));
3568                 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3569                 goto finished;
3570         }
3571
3572         if (state->r.out.info == NULL || state->r.out.info[0] == NULL) {
3573                 DBG_ERR("DC location via winbind returned no results\n");
3574                 state->r.out.result = WERR_GEN_FAILURE;
3575                 goto finished;
3576         }
3577
3578         if (state->r.out.info[0]->dc_unc == NULL) {
3579                 DBG_ERR("DC location via winbind returned no DC unc\n");
3580                 state->r.out.result = WERR_GEN_FAILURE;
3581                 goto finished;
3582         }
3583
3584         /*
3585          * Either the supplied site name is NULL (possibly via
3586          * TRY_NEXT_CLOSEST_SITE) or the resulting site name matches
3587          * the input match name.
3588          *
3589          * TODO: Currently this means that requests with NETBIOS domain
3590          * names can fail because they do not return the site name.
3591          */
3592         if (state->r.in.site_name == NULL ||
3593             strcasecmp_m("", state->r.in.site_name) == 0 ||
3594             (state->r.out.info[0]->dc_site_name != NULL &&
3595              strcasecmp_m(state->r.out.info[0]->dc_site_name,
3596                           state->r.in.site_name) == 0)) {
3597
3598                 state->r.out.info[0]->client_site_name =
3599                         talloc_move(state->mem_ctx, &state->client_site);
3600
3601                 /*
3602                  * Make sure to return our DC UNC with // prefix.
3603                  * Winbind currently doesn't send the leading slashes
3604                  * for some reason.
3605                  */
3606                 if (strlen(state->r.out.info[0]->dc_unc) > 2 &&
3607                     strncmp("\\\\", state->r.out.info[0]->dc_unc, 2) != 0) {
3608                         const char *dc_unc = NULL;
3609
3610                         dc_unc = talloc_asprintf(state->mem_ctx,
3611                                                  "\\\\%s",
3612                                                  state->r.out.info[0]->dc_unc);
3613                         state->r.out.info[0]->dc_unc = dc_unc;
3614                 }
3615
3616                 state->r.out.result = WERR_OK;
3617         } else {
3618                 state->r.out.info = NULL;
3619                 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3620         }
3621
3622 finished:
3623         if (state->_r.dcex2 != NULL) {
3624                 struct netr_DsRGetDCNameEx2 *r = state->_r.dcex2;
3625                 r->out.result = state->r.out.result;
3626         } else if (state->_r.dcex != NULL) {
3627                 struct netr_DsRGetDCNameEx *r = state->_r.dcex;
3628                 r->out.result = state->r.out.result;
3629         } else if (state->_r.dc != NULL) {
3630                 struct netr_DsRGetDCName *r = state->_r.dc;
3631                 r->out.result = state->r.out.result;
3632         }
3633
3634         TALLOC_FREE(state);
3635         status = dcesrv_reply(dce_call);
3636         if (!NT_STATUS_IS_OK(status)) {
3637                 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n",
3638                          nt_errstr(status)));
3639         }
3640 }
3641
3642 /*
3643   netr_DsRGetDCNameEx2
3644 */
3645 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
3646                                           TALLOC_CTX *mem_ctx,
3647                                           struct netr_DsRGetDCNameEx2 *r)
3648 {
3649         struct dcesrv_netr_DsRGetDCName_base_state *state;
3650
3651         state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3652         if (state == NULL) {
3653                 return WERR_NOT_ENOUGH_MEMORY;
3654         }
3655
3656         state->dce_call = dce_call;
3657         state->mem_ctx = mem_ctx;
3658
3659         state->r = *r;
3660         state->_r.dcex2 = r;
3661
3662         return dcesrv_netr_DsRGetDCName_base_call(state);
3663 }
3664
3665 /*
3666   netr_DsRGetDCNameEx
3667 */
3668 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3669                                   struct netr_DsRGetDCNameEx *r)
3670 {
3671         struct dcesrv_netr_DsRGetDCName_base_state *state;
3672
3673         state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3674         if (state == NULL) {
3675                 return WERR_NOT_ENOUGH_MEMORY;
3676         }
3677
3678         state->dce_call = dce_call;
3679         state->mem_ctx = mem_ctx;
3680
3681         state->r.in.server_unc = r->in.server_unc;
3682         state->r.in.client_account = NULL;
3683         state->r.in.mask = 0;
3684         state->r.in.domain_guid = r->in.domain_guid;
3685         state->r.in.domain_name = r->in.domain_name;
3686         state->r.in.site_name = r->in.site_name;
3687         state->r.in.flags = r->in.flags;
3688         state->r.out.info = r->out.info;
3689
3690         state->_r.dcex = r;
3691
3692         return dcesrv_netr_DsRGetDCName_base_call(state);
3693 }
3694
3695 /*
3696  * netr_DsRGetDCName
3697  *
3698  * This function is a predecessor to DsrGetDcNameEx2 according to [MS-NRPC].
3699  * Although it has a site-guid parameter, the documentation 3.5.4.3.3 DsrGetDcName
3700  * insists that it be ignored.
3701  */
3702 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3703                                        struct netr_DsRGetDCName *r)
3704 {
3705         struct dcesrv_netr_DsRGetDCName_base_state *state;
3706
3707         state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3708         if (state == NULL) {
3709                 return WERR_NOT_ENOUGH_MEMORY;
3710         }
3711
3712         state->dce_call = dce_call;
3713         state->mem_ctx = mem_ctx;
3714
3715         state->r.in.server_unc = r->in.server_unc;
3716         state->r.in.client_account = NULL;
3717         state->r.in.mask = 0;
3718         state->r.in.domain_name = r->in.domain_name;
3719         state->r.in.domain_guid = r->in.domain_guid;
3720
3721         state->r.in.site_name = NULL; /* this is correct, we should ignore site GUID */
3722         state->r.in.flags = r->in.flags;
3723         state->r.out.info = r->out.info;
3724
3725         state->_r.dc = r;
3726
3727         return dcesrv_netr_DsRGetDCName_base_call(state);
3728 }
3729 /*
3730   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
3731 */
3732 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3733                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
3734 {
3735         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3736 }
3737
3738
3739 /*
3740   netr_NetrEnumerateTrustedDomainsEx
3741 */
3742 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3743                        struct netr_NetrEnumerateTrustedDomainsEx *r)
3744 {
3745         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3746 }
3747
3748
3749 /*
3750   netr_DsRAddressToSitenamesExW
3751 */
3752 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3753                                                    struct netr_DsRAddressToSitenamesExW *r)
3754 {
3755         struct ldb_context *sam_ctx;
3756         struct netr_DsRAddressToSitenamesExWCtr *ctr;
3757         sa_family_t sin_family;
3758         struct sockaddr_in *addr;
3759 #ifdef HAVE_IPV6
3760         struct sockaddr_in6 *addr6;
3761         char addr_str[INET6_ADDRSTRLEN];
3762 #else
3763         char addr_str[INET_ADDRSTRLEN];
3764 #endif
3765         char *subnet_name;
3766         const char *res;
3767         uint32_t i;
3768
3769         sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
3770         if (sam_ctx == NULL) {
3771                 return WERR_DS_UNAVAILABLE;
3772         }
3773
3774         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
3775         W_ERROR_HAVE_NO_MEMORY(ctr);
3776
3777         *r->out.ctr = ctr;
3778
3779         ctr->count = r->in.count;
3780         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3781         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3782         ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
3783         W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
3784
3785         for (i=0; i<ctr->count; i++) {
3786                 ctr->sitename[i].string = NULL;
3787                 ctr->subnetname[i].string = NULL;
3788
3789                 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
3790                         continue;
3791                 }
3792                 /* The first two byte of the buffer are reserved for the
3793                  * "sin_family" but for now only the first one is used. */
3794                 sin_family = r->in.addresses[i].buffer[0];
3795
3796                 switch (sin_family) {
3797                 case AF_INET:
3798                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
3799                                 continue;
3800                         }
3801                         addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
3802                         res = inet_ntop(AF_INET, &addr->sin_addr,
3803                                         addr_str, sizeof(addr_str));
3804                         break;
3805 #ifdef HAVE_IPV6
3806                 case AF_INET6:
3807                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
3808                                 continue;
3809                         }
3810                         addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
3811                         res = inet_ntop(AF_INET6, &addr6->sin6_addr,
3812                                         addr_str, sizeof(addr_str));
3813                         break;
3814 #endif
3815                 default:
3816                         continue;
3817                 }
3818
3819                 if (res == NULL) {
3820                         continue;
3821                 }
3822
3823                 ctr->sitename[i].string   = samdb_client_site_name(sam_ctx,
3824                                                                    mem_ctx,
3825                                                                    addr_str,
3826                                                                    &subnet_name,
3827                                                                    true);
3828                 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
3829                 ctr->subnetname[i].string = subnet_name;
3830         }
3831
3832         return WERR_OK;
3833 }
3834
3835
3836 /*
3837   netr_DsRAddressToSitenamesW
3838 */
3839 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3840                        struct netr_DsRAddressToSitenamesW *r)
3841 {
3842         struct netr_DsRAddressToSitenamesExW r2;
3843         struct netr_DsRAddressToSitenamesWCtr *ctr;
3844         uint32_t i;
3845         WERROR werr;
3846
3847         ZERO_STRUCT(r2);
3848
3849         r2.in.server_name = r->in.server_name;
3850         r2.in.count = r->in.count;
3851         r2.in.addresses = r->in.addresses;
3852
3853         r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
3854         W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
3855
3856         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
3857         W_ERROR_HAVE_NO_MEMORY(ctr);
3858
3859         *r->out.ctr = ctr;
3860
3861         ctr->count = r->in.count;
3862         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3863         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3864
3865         werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
3866
3867         for (i=0; i<ctr->count; i++) {
3868                 ctr->sitename[i].string   = (*r2.out.ctr)->sitename[i].string;
3869         }
3870
3871         return werr;
3872 }
3873
3874
3875 /*
3876   netr_DsrGetDcSiteCoverageW
3877 */
3878 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3879                        struct netr_DsrGetDcSiteCoverageW *r)
3880 {
3881         struct ldb_context *sam_ctx;
3882         struct DcSitesCtr *ctr;
3883
3884         sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
3885         if (sam_ctx == NULL) {
3886                 return WERR_DS_UNAVAILABLE;
3887         }
3888
3889         ctr = talloc(mem_ctx, struct DcSitesCtr);
3890         W_ERROR_HAVE_NO_MEMORY(ctr);
3891
3892         *r->out.ctr = ctr;
3893
3894         /* For now only return our default site */
3895         ctr->num_sites = 1;
3896         ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
3897         W_ERROR_HAVE_NO_MEMORY(ctr->sites);
3898         ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
3899         W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
3900
3901         return WERR_OK;
3902 }
3903
3904
3905 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
3906                                          struct ldb_context *sam_ctx,
3907                                          struct netr_DomainTrustList *trusts,
3908                                          uint32_t trust_flags)
3909 {
3910         struct ldb_dn *system_dn;
3911         struct ldb_message **dom_res = NULL;
3912         const char *trust_attrs[] = { "flatname", "trustPartner",
3913                                       "securityIdentifier", "trustDirection",
3914                                       "trustType", "trustAttributes", NULL };
3915         uint32_t n;
3916         int i;
3917         int ret;
3918
3919         if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
3920                              NETR_TRUST_FLAG_OUTBOUND))) {
3921                 return WERR_INVALID_FLAGS;
3922         }
3923
3924         system_dn = samdb_search_dn(sam_ctx, mem_ctx,
3925                                     ldb_get_default_basedn(sam_ctx),
3926                                     "(&(objectClass=container)(cn=System))");
3927         if (!system_dn) {
3928                 return WERR_GEN_FAILURE;
3929         }
3930
3931         ret = gendb_search(sam_ctx, mem_ctx, system_dn,
3932                            &dom_res, trust_attrs,
3933                            "(objectclass=trustedDomain)");
3934
3935         for (i = 0; i < ret; i++) {
3936                 unsigned int trust_dir;
3937                 uint32_t flags = 0;
3938
3939                 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
3940                                                       "trustDirection", 0);
3941
3942                 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
3943                         flags |= NETR_TRUST_FLAG_INBOUND;
3944                 }
3945                 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
3946                         flags |= NETR_TRUST_FLAG_OUTBOUND;
3947                 }
3948
3949                 if (!(flags & trust_flags)) {
3950                         /* this trust direction was not requested */
3951                         continue;
3952                 }
3953
3954                 n = trusts->count;
3955                 trusts->array = talloc_realloc(trusts, trusts->array,
3956                                                struct netr_DomainTrust,
3957                                                n + 1);
3958                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3959
3960                 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
3961                 if (!trusts->array[n].netbios_name) {
3962                         DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
3963                                   "without flatname\n", 
3964                                   ldb_dn_get_linearized(dom_res[i]->dn)));
3965                 }
3966
3967                 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
3968
3969                 trusts->array[n].trust_flags = flags;
3970                 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
3971                     !(flags & NETR_TRUST_FLAG_TREEROOT)) {
3972                         /* TODO: find if we have parent in the list */
3973                         trusts->array[n].parent_index = 0;
3974                 }
3975
3976                 trusts->array[n].trust_type =
3977                                 ldb_msg_find_attr_as_uint(dom_res[i],
3978                                                   "trustType", 0);
3979                 trusts->array[n].trust_attributes =
3980                                 ldb_msg_find_attr_as_uint(dom_res[i],
3981                                                   "trustAttributes", 0);
3982
3983                 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
3984                     (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
3985                         struct dom_sid zero_sid;
3986                         ZERO_STRUCT(zero_sid);
3987                         trusts->array[n].sid =
3988                                 dom_sid_dup(trusts, &zero_sid);
3989                 } else {
3990                         trusts->array[n].sid =
3991                                 samdb_result_dom_sid(trusts, dom_res[i],
3992                                                      "securityIdentifier");
3993                 }
3994                 trusts->array[n].guid = GUID_zero();
3995
3996                 trusts->count = n + 1;
3997         }
3998
3999         talloc_free(dom_res);
4000         return WERR_OK;
4001 }
4002
4003 /*
4004   netr_DsrEnumerateDomainTrusts
4005 */
4006 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
4007                                                    TALLOC_CTX *mem_ctx,
4008                                                    struct netr_DsrEnumerateDomainTrusts *r)
4009 {
4010         struct netr_DomainTrustList *trusts;
4011         struct ldb_context *sam_ctx;
4012         int ret;
4013         struct ldb_message **dom_res;
4014         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
4015         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
4016         const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
4017         const char *p;
4018         WERROR werr;
4019
4020         if (r->in.trust_flags & 0xFFFFFE00) {
4021                 return WERR_INVALID_FLAGS;
4022         }
4023
4024         /* TODO: turn to hard check once we are sure this is 100% correct */
4025         if (!r->in.server_name) {
4026                 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
4027                           "But received NULL!\n", dnsdomain));
4028         } else {
4029                 p = strchr(r->in.server_name, '.');
4030                 if (!p) {
4031                         DEBUG(3, ("Invalid domain! Expected name in domain "
4032                                   "[%s]. But received [%s]!\n",
4033                                   dnsdomain, r->in.server_name));
4034                         p = r->in.server_name;
4035                 } else {
4036                         p++;
4037                 }
4038                 if (strcasecmp(p, dnsdomain)) {
4039                         DEBUG(3, ("Invalid domain! Expected name in domain "
4040                                   "[%s]. But received [%s]!\n",
4041                                   dnsdomain, r->in.server_name));
4042                 }
4043         }
4044
4045         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
4046         W_ERROR_HAVE_NO_MEMORY(trusts);
4047
4048         trusts->count = 0;
4049         r->out.trusts = trusts;
4050
4051         sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4052         if (sam_ctx == NULL) {
4053                 return WERR_GEN_FAILURE;
4054         }
4055
4056         if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
4057             (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
4058
4059                 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
4060                                                   trusts, r->in.trust_flags);
4061                 W_ERROR_NOT_OK_RETURN(werr);
4062         }
4063
4064         /* NOTE: we currently are always the root of the forest */
4065         if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
4066                 uint32_t n = trusts->count;
4067
4068                 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
4069                                       &dom_res, dom_attrs);
4070                 if (ret != 1) {
4071                         return WERR_GEN_FAILURE;
4072                 }
4073
4074                 trusts->count = n + 1;
4075                 trusts->array = talloc_realloc(trusts, trusts->array,
4076                                                struct netr_DomainTrust,
4077                                                trusts->count);
4078                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
4079
4080                 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
4081                 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
4082                 trusts->array[n].trust_flags =
4083                         NETR_TRUST_FLAG_NATIVE |
4084                         NETR_TRUST_FLAG_TREEROOT |
4085                         NETR_TRUST_FLAG_IN_FOREST |
4086                         NETR_TRUST_FLAG_PRIMARY;
4087                 /* we are always the root domain for now */
4088                 trusts->array[n].parent_index = 0;
4089                 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
4090                 trusts->array[n].trust_attributes = 0;
4091                 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
4092                                                             dom_res[0],
4093                                                             "objectSid");
4094                 trusts->array[n].guid = samdb_result_guid(dom_res[0],
4095                                                           "objectGUID");
4096                 talloc_free(dom_res);
4097         }
4098
4099         return WERR_OK;
4100 }
4101
4102
4103 /*
4104   netr_DsrDeregisterDNSHostRecords
4105 */
4106 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4107                        struct netr_DsrDeregisterDNSHostRecords *r)
4108 {
4109         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4110 }
4111
4112
4113 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4114                        struct netr_ServerGetTrustInfo *r);
4115
4116 /*
4117   netr_ServerTrustPasswordsGet
4118 */
4119 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4120                        struct netr_ServerTrustPasswordsGet *r)
4121 {
4122         struct netr_ServerGetTrustInfo r2 = {};
4123         struct netr_TrustInfo *_ti = NULL;
4124         NTSTATUS status;
4125
4126         r2.in.server_name = r->in.server_name;
4127         r2.in.account_name = r->in.account_name;
4128         r2.in.secure_channel_type = r->in.secure_channel_type;
4129         r2.in.computer_name = r->in.computer_name;
4130         r2.in.credential = r->in.credential;
4131
4132         r2.out.return_authenticator = r->out.return_authenticator;
4133         r2.out.new_owf_password = r->out.new_owf_password;
4134         r2.out.old_owf_password = r->out.old_owf_password;
4135         r2.out.trust_info = &_ti;
4136
4137         status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
4138
4139         r->out.return_authenticator = r2.out.return_authenticator;
4140         r->out.new_owf_password = r2.out.new_owf_password;
4141         r->out.old_owf_password = r2.out.old_owf_password;
4142
4143         return status;
4144 }
4145
4146 /*
4147   netr_DsRGetForestTrustInformation
4148 */
4149 struct dcesrv_netr_DsRGetForestTrustInformation_state {
4150         struct dcesrv_call_state *dce_call;
4151         TALLOC_CTX *mem_ctx;
4152         struct netr_DsRGetForestTrustInformation *r;
4153 };
4154
4155 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
4156
4157 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
4158                                                        TALLOC_CTX *mem_ctx,
4159                                                        struct netr_DsRGetForestTrustInformation *r)
4160 {
4161         struct auth_session_info *session_info =
4162                 dcesrv_call_session_info(dce_call);
4163         struct imessaging_context *imsg_ctx =
4164                 dcesrv_imessaging_context(dce_call->conn);
4165         enum security_user_level security_level;
4166         struct ldb_context *sam_ctx = NULL;
4167         struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
4168         struct dcerpc_binding_handle *irpc_handle = NULL;
4169         struct tevent_req *subreq = NULL;
4170         struct ldb_dn *domain_dn = NULL;
4171         struct ldb_dn *forest_dn = NULL;
4172         int cmp;
4173         int forest_level;
4174
4175         security_level = security_session_user_level(session_info, NULL);
4176         if (security_level < SECURITY_USER) {
4177                 return WERR_ACCESS_DENIED;
4178         }
4179
4180         if (r->in.flags & 0xFFFFFFFE) {
4181                 return WERR_INVALID_FLAGS;
4182         }
4183
4184         sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4185         if (sam_ctx == NULL) {
4186                 return WERR_GEN_FAILURE;
4187         }
4188
4189         domain_dn = ldb_get_default_basedn(sam_ctx);
4190         if (domain_dn == NULL) {
4191                 return WERR_GEN_FAILURE;
4192         }
4193
4194         forest_dn = ldb_get_root_basedn(sam_ctx);
4195         if (forest_dn == NULL) {
4196                 return WERR_GEN_FAILURE;
4197         }
4198
4199         cmp = ldb_dn_compare(domain_dn, forest_dn);
4200         if (cmp != 0) {
4201                 return WERR_NERR_ACFNOTLOADED;
4202         }
4203
4204         forest_level = dsdb_forest_functional_level(sam_ctx);
4205         if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4206                 return WERR_INVALID_FUNCTION;
4207         }
4208
4209         if (r->in.flags & DS_GFTI_UPDATE_TDO) {
4210                 if (!samdb_is_pdc(sam_ctx)) {
4211                         return WERR_NERR_NOTPRIMARY;
4212                 }
4213
4214                 if (r->in.trusted_domain_name == NULL) {
4215                         return WERR_INVALID_FLAGS;
4216                 }
4217         }
4218
4219         if (r->in.trusted_domain_name == NULL) {
4220                 NTSTATUS status;
4221
4222                 /*
4223                  * information about our own domain
4224                  */
4225                 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
4226                                                 r->out.forest_trust_info);
4227                 if (!NT_STATUS_IS_OK(status)) {
4228                         return ntstatus_to_werror(status);
4229                 }
4230
4231                 return WERR_OK;
4232         }
4233
4234         /*
4235          * Forward the request to winbindd
4236          */
4237
4238         state = talloc_zero(mem_ctx,
4239                         struct dcesrv_netr_DsRGetForestTrustInformation_state);
4240         if (state == NULL) {
4241                 return WERR_NOT_ENOUGH_MEMORY;
4242         }
4243         state->dce_call = dce_call;
4244         state->mem_ctx = mem_ctx;
4245         state->r = r;
4246
4247         irpc_handle = irpc_binding_handle_by_name(state,
4248                                                   imsg_ctx,
4249                                                   "winbind_server",
4250                                                   &ndr_table_winbind);
4251         if (irpc_handle == NULL) {
4252                 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
4253                 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4254                 return WERR_SERVICE_NOT_FOUND;
4255         }
4256
4257         /*
4258          * 60 seconds timeout should be enough
4259          */
4260         dcerpc_binding_handle_set_timeout(irpc_handle, 60);
4261
4262         subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
4263                                                 state->dce_call->event_ctx,
4264                                                 irpc_handle,
4265                                                 r->in.trusted_domain_name,
4266                                                 r->in.flags,
4267                                                 r->out.forest_trust_info);
4268         if (subreq == NULL) {
4269                 return WERR_NOT_ENOUGH_MEMORY;
4270         }
4271         state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
4272         tevent_req_set_callback(subreq,
4273                                 dcesrv_netr_DsRGetForestTrustInformation_done,
4274                                 state);
4275
4276         return WERR_OK;
4277 }
4278
4279 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
4280 {
4281         struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
4282                 tevent_req_callback_data(subreq,
4283                 struct dcesrv_netr_DsRGetForestTrustInformation_state);
4284         NTSTATUS status;
4285
4286         status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
4287                                                         state->mem_ctx,
4288                                                         &state->r->out.result);
4289         TALLOC_FREE(subreq);
4290         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
4291                 state->r->out.result = WERR_TIMEOUT;
4292         } else if (!NT_STATUS_IS_OK(status)) {
4293                 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4294                 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
4295                          nt_errstr(status)));
4296         }
4297
4298         status = dcesrv_reply(state->dce_call);
4299         if (!NT_STATUS_IS_OK(status)) {
4300                 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
4301         }
4302 }
4303
4304 /*
4305   netr_GetForestTrustInformation
4306 */
4307 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
4308                                                       TALLOC_CTX *mem_ctx,
4309                                                       struct netr_GetForestTrustInformation *r)
4310 {
4311         struct netlogon_creds_CredentialState *creds = NULL;
4312         struct ldb_context *sam_ctx = NULL;
4313         struct ldb_dn *domain_dn = NULL;
4314         struct ldb_dn *forest_dn = NULL;
4315         int cmp;
4316         int forest_level;
4317         NTSTATUS status;
4318
4319         status = dcesrv_netr_creds_server_step_check(dce_call,
4320                                                      mem_ctx,
4321                                                      r->in.computer_name,
4322                                                      r->in.credential,
4323                                                      r->out.return_authenticator,
4324                                                      &creds);
4325         if (!NT_STATUS_IS_OK(status)) {
4326                 return status;
4327         }
4328
4329         if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
4330             (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
4331                 return NT_STATUS_NOT_IMPLEMENTED;
4332         }
4333
4334         sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4335         if (sam_ctx == NULL) {
4336                 return NT_STATUS_INTERNAL_ERROR;
4337         }
4338
4339         /* TODO: check r->in.server_name is our name */
4340
4341         domain_dn = ldb_get_default_basedn(sam_ctx);
4342         if (domain_dn == NULL) {
4343                 return NT_STATUS_INTERNAL_ERROR;
4344         }
4345
4346         forest_dn = ldb_get_root_basedn(sam_ctx);
4347         if (forest_dn == NULL) {
4348                 return NT_STATUS_INTERNAL_ERROR;
4349         }
4350
4351         cmp = ldb_dn_compare(domain_dn, forest_dn);
4352         if (cmp != 0) {
4353                 return NT_STATUS_INVALID_DOMAIN_STATE;
4354         }
4355
4356         forest_level = dsdb_forest_functional_level(sam_ctx);
4357         if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4358                 return NT_STATUS_INVALID_DOMAIN_STATE;
4359         }
4360
4361         status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
4362                                              r->out.forest_trust_info);
4363         if (!NT_STATUS_IS_OK(status)) {
4364                 return status;
4365         }
4366
4367         return NT_STATUS_OK;
4368 }
4369
4370
4371 /*
4372   netr_ServerGetTrustInfo
4373 */
4374 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4375                        struct netr_ServerGetTrustInfo *r)
4376 {
4377         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
4378         struct netlogon_creds_CredentialState *creds = NULL;
4379         struct ldb_context *sam_ctx = NULL;
4380         const char * const attrs[] = {
4381                 "unicodePwd",
4382                 "sAMAccountName",
4383                 "userAccountControl",
4384                 NULL
4385         };
4386         struct ldb_message **res = NULL;
4387         struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
4388         NTSTATUS nt_status;
4389         int ret;
4390         const char *asid = NULL;
4391         uint32_t uac = 0;
4392         const char *aname = NULL;
4393         struct ldb_message *tdo_msg = NULL;
4394         const char * const tdo_attrs[] = {
4395                 "trustAuthIncoming",
4396                 "trustAttributes",
4397                 NULL
4398         };
4399         struct netr_TrustInfo *trust_info = NULL;
4400
4401         ZERO_STRUCTP(r->out.new_owf_password);
4402         ZERO_STRUCTP(r->out.old_owf_password);
4403
4404         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4405                                                         mem_ctx,
4406                                                         r->in.computer_name,
4407                                                         r->in.credential,
4408                                                         r->out.return_authenticator,
4409                                                         &creds);
4410         if (!NT_STATUS_IS_OK(nt_status)) {
4411                 return nt_status;
4412         }
4413
4414         /* TODO: check r->in.server_name is our name */
4415
4416         if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
4417                 return NT_STATUS_INVALID_PARAMETER;
4418         }
4419
4420         if (r->in.secure_channel_type != creds->secure_channel_type) {
4421                 return NT_STATUS_INVALID_PARAMETER;
4422         }
4423
4424         if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
4425                 return NT_STATUS_INVALID_PARAMETER;
4426         }
4427
4428         sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
4429         if (sam_ctx == NULL) {
4430                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
4431         }
4432
4433         asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
4434         if (asid == NULL) {
4435                 return NT_STATUS_NO_MEMORY;
4436         }
4437
4438         ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
4439                            "(&(objectClass=user)(objectSid=%s))",
4440                            asid);
4441         if (ret != 1) {
4442                 return NT_STATUS_ACCOUNT_DISABLED;
4443         }
4444
4445         switch (creds->secure_channel_type) {
4446         case SEC_CHAN_DNS_DOMAIN:
4447         case SEC_CHAN_DOMAIN:
4448                 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
4449
4450                 if (uac & UF_ACCOUNTDISABLE) {
4451                         return NT_STATUS_ACCOUNT_DISABLED;
4452                 }
4453
4454                 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
4455                         return NT_STATUS_ACCOUNT_DISABLED;
4456                 }
4457
4458                 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
4459                 if (aname == NULL) {
4460                         return NT_STATUS_ACCOUNT_DISABLED;
4461                 }
4462
4463                 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
4464                                                 SEC_CHAN_DOMAIN, aname,
4465                                                 tdo_attrs, mem_ctx, &tdo_msg);
4466                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4467                         return NT_STATUS_ACCOUNT_DISABLED;
4468                 }
4469                 if (!NT_STATUS_IS_OK(nt_status)) {
4470                         return nt_status;
4471                 }
4472
4473                 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
4474                                                               &curNtHash,
4475                                                               &prevNtHash);
4476                 if (!NT_STATUS_IS_OK(nt_status)) {
4477                         return nt_status;
4478                 }
4479
4480                 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
4481                 if (trust_info == NULL) {
4482                         return NT_STATUS_NO_MEMORY;
4483                 }
4484
4485                 trust_info->count = 1;
4486                 trust_info->data = talloc_array(trust_info, uint32_t,
4487                                                 trust_info->count);
4488                 if (trust_info->data == NULL) {
4489                         return NT_STATUS_NO_MEMORY;
4490                 }
4491
4492                 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
4493                                                         "trustAttributes",
4494                                                         0);
4495                 break;
4496
4497         default:
4498                 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
4499                                                               res[0],
4500                                                               &curNtHash);
4501                 if (!NT_STATUS_IS_OK(nt_status)) {
4502                         return nt_status;
4503                 }
4504
4505                 prevNtHash = talloc(mem_ctx, struct samr_Password);
4506                 if (prevNtHash == NULL) {
4507                         return NT_STATUS_NO_MEMORY;
4508                 }
4509
4510                 E_md4hash("", prevNtHash->hash);
4511                 break;
4512         }
4513
4514         if (curNtHash != NULL) {
4515                 *r->out.new_owf_password = *curNtHash;
4516                 nt_status = netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
4517                 if (!NT_STATUS_IS_OK(nt_status)) {
4518                         return nt_status;
4519                 }
4520         }
4521         if (prevNtHash != NULL) {
4522                 *r->out.old_owf_password = *prevNtHash;
4523                 nt_status = netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
4524                 if (!NT_STATUS_IS_OK(nt_status)) {
4525                         return nt_status;
4526                 }
4527         }
4528
4529         if (trust_info != NULL) {
4530                 *r->out.trust_info = trust_info;
4531         }
4532
4533         return NT_STATUS_OK;
4534 }
4535
4536 /*
4537   netr_Unused47
4538 */
4539 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4540                                      struct netr_Unused47 *r)
4541 {
4542         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4543 }
4544
4545
4546 struct netr_dnsupdate_RODC_state {
4547         struct dcesrv_call_state *dce_call;
4548         struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
4549         struct dnsupdate_RODC *r2;
4550 };
4551
4552 /*
4553   called when the forwarded RODC dns update request is finished
4554  */
4555 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
4556 {
4557         struct netr_dnsupdate_RODC_state *st =
4558                 tevent_req_callback_data(subreq,
4559                                          struct netr_dnsupdate_RODC_state);
4560         NTSTATUS status;
4561
4562         status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
4563         TALLOC_FREE(subreq);
4564         if (!NT_STATUS_IS_OK(status)) {
4565                 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
4566                 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4567         }
4568
4569         st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
4570
4571         status = dcesrv_reply(st->dce_call);
4572         if (!NT_STATUS_IS_OK(status)) {
4573                 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
4574         }
4575 }
4576
4577 /*
4578   netr_DsrUpdateReadOnlyServerDnsRecords
4579 */
4580 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
4581                                                               TALLOC_CTX *mem_ctx,
4582                                                               struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
4583 {
4584         struct netlogon_creds_CredentialState *creds;
4585         NTSTATUS nt_status;
4586         struct dcerpc_binding_handle *binding_handle;
4587         struct netr_dnsupdate_RODC_state *st;
4588         struct tevent_req *subreq;
4589         struct imessaging_context *imsg_ctx =
4590                 dcesrv_imessaging_context(dce_call->conn);
4591
4592         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4593                                                         mem_ctx,
4594                                                         r->in.computer_name,
4595                                                         r->in.credential,
4596                                                         r->out.return_authenticator,
4597                                                         &creds);
4598         NT_STATUS_NOT_OK_RETURN(nt_status);
4599
4600         if (creds->secure_channel_type != SEC_CHAN_RODC) {
4601                 return NT_STATUS_ACCESS_DENIED;
4602         }
4603
4604         st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
4605         NT_STATUS_HAVE_NO_MEMORY(st);
4606
4607         st->dce_call = dce_call;
4608         st->r = r;
4609         st->r2 = talloc_zero(st, struct dnsupdate_RODC);
4610         NT_STATUS_HAVE_NO_MEMORY(st->r2);
4611
4612         st->r2->in.dom_sid = creds->sid;
4613         st->r2->in.site_name = r->in.site_name;
4614         st->r2->in.dns_ttl = r->in.dns_ttl;
4615         st->r2->in.dns_names = r->in.dns_names;
4616         st->r2->out.dns_names = r->out.dns_names;
4617
4618         binding_handle = irpc_binding_handle_by_name(st,
4619                                                      imsg_ctx,
4620                                                      "dnsupdate",
4621                                                      &ndr_table_irpc);
4622         if (binding_handle == NULL) {
4623                 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
4624                 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4625                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4626         }
4627
4628         /* forward the call */
4629         subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
4630                                               binding_handle, st->r2);
4631         NT_STATUS_HAVE_NO_MEMORY(subreq);
4632
4633         dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
4634
4635         /* setup the callback */
4636         tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
4637
4638         return NT_STATUS_OK;
4639 }
4640
4641
4642 /* include the generated boilerplate */
4643 #include "librpc/gen_ndr/ndr_netlogon_s.c"