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