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