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