s4:rpc_server/netlogon: initialize pointer to NULL in dcesrv_netr_LogonSamLogon_base()
[sharpe/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_SamBaseInfo *sam = NULL;
845         struct netr_SamInfo2 *sam2 = NULL;
846         struct netr_SamInfo3 *sam3 = NULL;
847         struct netr_SamInfo6 *sam6 = NULL;
848
849         *r->out.authoritative = 1;
850
851         user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
852         NT_STATUS_HAVE_NO_MEMORY(user_info);
853
854         netlogon_creds_decrypt_samlogon_logon(creds,
855                                               r->in.logon_level,
856                                               r->in.logon);
857
858         switch (r->in.logon_level) {
859         case NetlogonInteractiveInformation:
860         case NetlogonServiceInformation:
861         case NetlogonInteractiveTransitiveInformation:
862         case NetlogonServiceTransitiveInformation:
863
864                 /* TODO: we need to deny anonymous access here */
865                 nt_status = auth_context_create(mem_ctx,
866                                                 dce_call->event_ctx, dce_call->msg_ctx,
867                                                 dce_call->conn->dce_ctx->lp_ctx,
868                                                 &auth_context);
869                 NT_STATUS_NOT_OK_RETURN(nt_status);
870
871                 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
872                 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
873                 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
874                 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
875
876                 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
877                 user_info->password_state = AUTH_PASSWORD_HASH;
878
879                 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
880                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
881                 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
882
883                 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
884                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
885                 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
886
887                 break;
888         case NetlogonNetworkInformation:
889         case NetlogonNetworkTransitiveInformation:
890
891                 /* TODO: we need to deny anonymous access here */
892                 nt_status = auth_context_create(mem_ctx,
893                                                 dce_call->event_ctx, dce_call->msg_ctx,
894                                                 dce_call->conn->dce_ctx->lp_ctx,
895                                                 &auth_context);
896                 NT_STATUS_NOT_OK_RETURN(nt_status);
897
898                 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
899                 NT_STATUS_NOT_OK_RETURN(nt_status);
900
901                 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
902                 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
903                 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
904                 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
905
906                 user_info->password_state = AUTH_PASSWORD_RESPONSE;
907                 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
908                 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
909
910                 nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
911                                         user_info->client.account_name,
912                                         user_info->client.domain_name,
913                                         user_info->password.response.nt,
914                                         creds, workgroup);
915                 NT_STATUS_NOT_OK_RETURN(nt_status);
916
917                 break;
918
919
920         case NetlogonGenericInformation:
921         {
922                 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
923                         /* OK */
924                 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
925                         /* OK */
926                 } else {
927                         /* Using DES to verify kerberos tickets makes no sense */
928                         return NT_STATUS_INVALID_PARAMETER;
929                 }
930
931                 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
932                         NTSTATUS status;
933                         struct dcerpc_binding_handle *irpc_handle;
934                         struct kdc_check_generic_kerberos check;
935                         struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
936                         NT_STATUS_HAVE_NO_MEMORY(generic);
937                         *r->out.authoritative = 1;
938
939                         /* TODO: Describe and deal with these flags */
940                         *r->out.flags = 0;
941
942                         r->out.validation->generic = generic;
943
944                         irpc_handle = irpc_binding_handle_by_name(mem_ctx,
945                                                                   dce_call->msg_ctx,
946                                                                   "kdc_server",
947                                                                   &ndr_table_irpc);
948                         if (irpc_handle == NULL) {
949                                 return NT_STATUS_NO_LOGON_SERVERS;
950                         }
951
952                         check.in.generic_request =
953                                 data_blob_const(r->in.logon->generic->data,
954                                                 r->in.logon->generic->length);
955
956                         /*
957                          * TODO: make this async and avoid
958                          * dcerpc_binding_handle_set_sync_ev()
959                          */
960                         dcerpc_binding_handle_set_sync_ev(irpc_handle,
961                                                           dce_call->event_ctx);
962                         status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
963                                                                      mem_ctx,
964                                                                      &check);
965                         if (!NT_STATUS_IS_OK(status)) {
966                                 return status;
967                         }
968                         generic->length = check.out.generic_reply.length;
969                         generic->data = check.out.generic_reply.data;
970                         return NT_STATUS_OK;
971                 }
972
973                 /* Until we get an implemetnation of these other packages */
974                 return NT_STATUS_INVALID_PARAMETER;
975         }
976         default:
977                 return NT_STATUS_INVALID_PARAMETER;
978         }
979
980         nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
981         /* TODO: set *r->out.authoritative = 0 on specific errors */
982         NT_STATUS_NOT_OK_RETURN(nt_status);
983
984         switch (r->in.validation_level) {
985         case 2:
986                 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
987                 NT_STATUS_NOT_OK_RETURN(nt_status);
988
989                 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
990                 NT_STATUS_HAVE_NO_MEMORY(sam2);
991                 sam2->base = *sam;
992
993                 /* And put into the talloc tree */
994                 talloc_steal(sam2, sam);
995                 r->out.validation->sam2 = sam2;
996
997                 sam = &sam2->base;
998                 break;
999
1000         case 3:
1001                 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
1002                                                               user_info_dc,
1003                                                               &sam3);
1004                 NT_STATUS_NOT_OK_RETURN(nt_status);
1005
1006                 r->out.validation->sam3 = sam3;
1007
1008                 sam = &sam3->base;
1009                 break;
1010
1011         case 6:
1012                 if (dce_call->conn->auth_state.auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
1013                         return NT_STATUS_INVALID_PARAMETER;
1014                 }
1015
1016                 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
1017                                                            user_info_dc,
1018                                                            &sam3);
1019                 NT_STATUS_NOT_OK_RETURN(nt_status);
1020
1021                 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
1022                 NT_STATUS_HAVE_NO_MEMORY(sam6);
1023                 sam6->base = sam3->base;
1024                 sam = &sam6->base;
1025                 sam6->sidcount = sam3->sidcount;
1026                 sam6->sids = sam3->sids;
1027
1028                 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
1029                 sam6->principal_name.string = talloc_asprintf(
1030                         mem_ctx, "%s@%s", sam->account_name.string,
1031                         sam6->dns_domainname.string);
1032                 NT_STATUS_HAVE_NO_MEMORY(sam6->principal_name.string);
1033                 /* And put into the talloc tree */
1034                 talloc_steal(sam6, sam3);
1035
1036                 r->out.validation->sam6 = sam6;
1037                 break;
1038
1039         default:
1040                 return NT_STATUS_INVALID_INFO_CLASS;
1041         }
1042
1043         netlogon_creds_encrypt_samlogon_validation(creds,
1044                                                    r->in.validation_level,
1045                                                    r->out.validation);
1046
1047         /* TODO: Describe and deal with these flags */
1048         *r->out.flags = 0;
1049
1050         return NT_STATUS_OK;
1051 }
1052
1053 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1054                                      struct netr_LogonSamLogonEx *r)
1055 {
1056         NTSTATUS nt_status;
1057         struct netlogon_creds_CredentialState *creds;
1058
1059         *r->out.authoritative = 1;
1060
1061         nt_status = dcesrv_netr_LogonSamLogon_check(r);
1062         if (!NT_STATUS_IS_OK(nt_status)) {
1063                 return nt_status;
1064         }
1065
1066         nt_status = schannel_get_creds_state(mem_ctx,
1067                                              dce_call->conn->dce_ctx->lp_ctx,
1068                                              r->in.computer_name, &creds);
1069         if (!NT_STATUS_IS_OK(nt_status)) {
1070                 return nt_status;
1071         }
1072
1073         if (dce_call->conn->auth_state.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1074                 return NT_STATUS_ACCESS_DENIED;
1075         }
1076         return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
1077 }
1078
1079 /*
1080   netr_LogonSamLogonWithFlags
1081
1082 */
1083 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1084                                             struct netr_LogonSamLogonWithFlags *r)
1085 {
1086         NTSTATUS nt_status;
1087         struct netlogon_creds_CredentialState *creds;
1088         struct netr_LogonSamLogonEx r2;
1089
1090         struct netr_Authenticator *return_authenticator;
1091
1092         ZERO_STRUCT(r2);
1093
1094         r2.in.server_name       = r->in.server_name;
1095         r2.in.computer_name     = r->in.computer_name;
1096         r2.in.logon_level       = r->in.logon_level;
1097         r2.in.logon             = r->in.logon;
1098         r2.in.validation_level  = r->in.validation_level;
1099         r2.in.flags             = r->in.flags;
1100         r2.out.validation       = r->out.validation;
1101         r2.out.authoritative    = r->out.authoritative;
1102         r2.out.flags            = r->out.flags;
1103
1104         *r->out.authoritative = 1;
1105
1106         nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
1107         if (!NT_STATUS_IS_OK(nt_status)) {
1108                 return nt_status;
1109         }
1110
1111         return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
1112         NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
1113
1114         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1115                                                         mem_ctx,
1116                                                         r->in.computer_name,
1117                                                         r->in.credential, return_authenticator,
1118                                                         &creds);
1119         NT_STATUS_NOT_OK_RETURN(nt_status);
1120
1121         nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
1122
1123         r->out.return_authenticator     = return_authenticator;
1124
1125         return nt_status;
1126 }
1127
1128 /*
1129   netr_LogonSamLogon
1130 */
1131 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1132                                    struct netr_LogonSamLogon *r)
1133 {
1134         struct netr_LogonSamLogonWithFlags r2;
1135         uint32_t flags = 0;
1136         NTSTATUS status;
1137
1138         ZERO_STRUCT(r2);
1139
1140         r2.in.server_name = r->in.server_name;
1141         r2.in.computer_name = r->in.computer_name;
1142         r2.in.credential  = r->in.credential;
1143         r2.in.return_authenticator = r->in.return_authenticator;
1144         r2.in.logon_level = r->in.logon_level;
1145         r2.in.logon = r->in.logon;
1146         r2.in.validation_level = r->in.validation_level;
1147         r2.in.flags = &flags;
1148         r2.out.validation = r->out.validation;
1149         r2.out.authoritative = r->out.authoritative;
1150         r2.out.flags = &flags;
1151
1152         status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
1153
1154         r->out.return_authenticator = r2.out.return_authenticator;
1155
1156         return status;
1157 }
1158
1159
1160 /*
1161   netr_LogonSamLogoff
1162 */
1163 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1164                        struct netr_LogonSamLogoff *r)
1165 {
1166         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1167 }
1168
1169
1170
1171 /*
1172   netr_DatabaseDeltas
1173 */
1174 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1175                        struct netr_DatabaseDeltas *r)
1176 {
1177         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1178 }
1179
1180
1181 /*
1182   netr_DatabaseSync2
1183 */
1184 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1185                        struct netr_DatabaseSync2 *r)
1186 {
1187         /* win2k3 native mode returns  "NOT IMPLEMENTED" for this call */
1188         return NT_STATUS_NOT_IMPLEMENTED;
1189 }
1190
1191
1192 /*
1193   netr_DatabaseSync
1194 */
1195 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1196                        struct netr_DatabaseSync *r)
1197 {
1198         struct netr_DatabaseSync2 r2;
1199         NTSTATUS status;
1200
1201         ZERO_STRUCT(r2);
1202
1203         r2.in.logon_server = r->in.logon_server;
1204         r2.in.computername = r->in.computername;
1205         r2.in.credential = r->in.credential;
1206         r2.in.database_id = r->in.database_id;
1207         r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1208         r2.in.sync_context = r->in.sync_context;
1209         r2.out.sync_context = r->out.sync_context;
1210         r2.out.delta_enum_array = r->out.delta_enum_array;
1211         r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1212
1213         status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1214
1215         return status;
1216 }
1217
1218
1219 /*
1220   netr_AccountDeltas
1221 */
1222 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1223                        struct netr_AccountDeltas *r)
1224 {
1225         /* w2k3 returns "NOT IMPLEMENTED" for this call */
1226         return NT_STATUS_NOT_IMPLEMENTED;
1227 }
1228
1229
1230 /*
1231   netr_AccountSync
1232 */
1233 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1234                        struct netr_AccountSync *r)
1235 {
1236         /* w2k3 returns "NOT IMPLEMENTED" for this call */
1237         return NT_STATUS_NOT_IMPLEMENTED;
1238 }
1239
1240
1241 /*
1242   netr_GetDcName
1243 */
1244 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1245                        struct netr_GetDcName *r)
1246 {
1247         const char * const attrs[] = { NULL };
1248         struct ldb_context *sam_ctx;
1249         struct ldb_message **res;
1250         struct ldb_dn *domain_dn;
1251         int ret;
1252         const char *dcname;
1253
1254         /*
1255          * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1256          * that the domainname needs to be a valid netbios domain
1257          * name, if it is not NULL.
1258          */
1259         if (r->in.domainname) {
1260                 const char *dot = strchr(r->in.domainname, '.');
1261                 size_t len = strlen(r->in.domainname);
1262
1263                 if (dot || len > 15) {
1264                         return WERR_DCNOTFOUND;
1265                 }
1266
1267                 /*
1268                  * TODO: Should we also varify that only valid
1269                  *       netbios name characters are used?
1270                  */
1271         }
1272
1273         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1274                                 dce_call->conn->dce_ctx->lp_ctx,
1275                                 dce_call->conn->auth_state.session_info, 0);
1276         if (sam_ctx == NULL) {
1277                 return WERR_DS_UNAVAILABLE;
1278         }
1279
1280         domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1281                                        r->in.domainname);
1282         if (domain_dn == NULL) {
1283                 return WERR_NO_SUCH_DOMAIN;
1284         }
1285
1286         ret = gendb_search_dn(sam_ctx, mem_ctx,
1287                               domain_dn, &res, attrs);
1288         if (ret != 1) {
1289                 return WERR_NO_SUCH_DOMAIN;
1290         }
1291
1292         /* TODO: - return real IP address
1293          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
1294          */
1295         dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1296                                  lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1297         W_ERROR_HAVE_NO_MEMORY(dcname);
1298
1299         *r->out.dcname = dcname;
1300         return WERR_OK;
1301 }
1302
1303 struct dcesrv_netr_LogonControl_base_state {
1304         struct dcesrv_call_state *dce_call;
1305
1306         TALLOC_CTX *mem_ctx;
1307
1308         struct netr_LogonControl2Ex r;
1309
1310         struct {
1311                 struct netr_LogonControl *l;
1312                 struct netr_LogonControl2 *l2;
1313                 struct netr_LogonControl2Ex *l2ex;
1314         } _r;
1315 };
1316
1317 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
1318
1319 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
1320 {
1321         struct dcesrv_connection *conn = state->dce_call->conn;
1322         struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
1323         struct auth_session_info *session_info = conn->auth_state.session_info;
1324         enum security_user_level security_level;
1325         struct dcerpc_binding_handle *irpc_handle;
1326         struct tevent_req *subreq;
1327         bool ok;
1328
1329         /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
1330
1331         if (state->_r.l != NULL) {
1332                 /*
1333                  * netr_LogonControl
1334                  */
1335                 if (state->r.in.level == 0x00000002) {
1336                         return WERR_NOT_SUPPORTED;
1337                 } else if (state->r.in.level != 0x00000001) {
1338                         return WERR_INVALID_LEVEL;
1339                 }
1340
1341                 switch (state->r.in.function_code) {
1342                 case NETLOGON_CONTROL_QUERY:
1343                 case NETLOGON_CONTROL_REPLICATE:
1344                 case NETLOGON_CONTROL_SYNCHRONIZE:
1345                 case NETLOGON_CONTROL_PDC_REPLICATE:
1346                 case NETLOGON_CONTROL_BREAKPOINT:
1347                 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
1348                 case NETLOGON_CONTROL_TRUNCATE_LOG:
1349                         break;
1350                 default:
1351                         return WERR_NOT_SUPPORTED;
1352                 }
1353         }
1354
1355         if (state->r.in.level < 0x00000001) {
1356                 return WERR_INVALID_LEVEL;
1357         }
1358
1359         if (state->r.in.level > 0x00000004) {
1360                 return WERR_INVALID_LEVEL;
1361         }
1362
1363         if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
1364                 struct netr_NETLOGON_INFO_1 *info1 = NULL;
1365                 struct netr_NETLOGON_INFO_3 *info3 = NULL;
1366
1367                 switch (state->r.in.level) {
1368                 case 0x00000001:
1369                         info1 = talloc_zero(state->mem_ctx,
1370                                             struct netr_NETLOGON_INFO_1);
1371                         if (info1 == NULL) {
1372                                 return WERR_NOMEM;
1373                         }
1374                         state->r.out.query->info1 = info1;
1375                         return WERR_OK;
1376
1377                 case 0x00000003:
1378                         info3 = talloc_zero(state->mem_ctx,
1379                                             struct netr_NETLOGON_INFO_3);
1380                         if (info3 == NULL) {
1381                                 return WERR_NOMEM;
1382                         }
1383                         state->r.out.query->info3 = info3;
1384                         return WERR_OK;
1385
1386                 default:
1387                         return WERR_INVALID_PARAMETER;
1388                 }
1389         }
1390
1391         /*
1392          * Some validations are done before the access check
1393          * and some after the access check
1394          */
1395         security_level = security_session_user_level(session_info, NULL);
1396         if (security_level < SECURITY_ADMINISTRATOR) {
1397                 return WERR_ACCESS_DENIED;
1398         }
1399
1400         if (state->_r.l2 != NULL) {
1401                 /*
1402                  * netr_LogonControl2
1403                  */
1404                 if (state->r.in.level == 0x00000004) {
1405                         return WERR_INVALID_LEVEL;
1406                 }
1407         }
1408
1409         switch (state->r.in.level) {
1410         case 0x00000001:
1411                 break;
1412
1413         case 0x00000002:
1414                 switch (state->r.in.function_code) {
1415                 case NETLOGON_CONTROL_REDISCOVER:
1416                 case NETLOGON_CONTROL_TC_QUERY:
1417                 case NETLOGON_CONTROL_TC_VERIFY:
1418                         break;
1419                 default:
1420                         return WERR_INVALID_PARAMETER;
1421                 }
1422
1423                 break;
1424
1425         case 0x00000003:
1426                 break;
1427
1428         case 0x00000004:
1429                 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
1430                         return WERR_INVALID_PARAMETER;
1431                 }
1432
1433                 break;
1434
1435         default:
1436                 return WERR_INVALID_LEVEL;
1437         }
1438
1439         switch (state->r.in.function_code) {
1440         case NETLOGON_CONTROL_REDISCOVER:
1441         case NETLOGON_CONTROL_TC_QUERY:
1442         case NETLOGON_CONTROL_TC_VERIFY:
1443                 if (state->r.in.level != 2) {
1444                         return WERR_INVALID_PARAMETER;
1445                 }
1446
1447                 if (state->r.in.data == NULL) {
1448                         return WERR_INVALID_PARAMETER;
1449                 }
1450
1451                 if (state->r.in.data->domain == NULL) {
1452                         return WERR_INVALID_PARAMETER;
1453                 }
1454
1455                 break;
1456
1457         case NETLOGON_CONTROL_CHANGE_PASSWORD:
1458                 if (state->r.in.level != 1) {
1459                         return WERR_INVALID_PARAMETER;
1460                 }
1461
1462                 if (state->r.in.data == NULL) {
1463                         return WERR_INVALID_PARAMETER;
1464                 }
1465
1466                 if (state->r.in.data->domain == NULL) {
1467                         return WERR_INVALID_PARAMETER;
1468                 }
1469
1470                 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
1471                                                  state->r.in.data->domain);
1472                 if (!ok) {
1473                         struct ldb_context *sam_ctx;
1474
1475                         sam_ctx = samdb_connect(state, state->dce_call->event_ctx,
1476                                                 lp_ctx, system_session(lp_ctx), 0);
1477                         if (sam_ctx == NULL) {
1478                                 return WERR_DS_UNAVAILABLE;
1479                         }
1480
1481                         /*
1482                          * Secrets for trusted domains can only be triggered on
1483                          * the PDC.
1484                          */
1485                         ok = samdb_is_pdc(sam_ctx);
1486                         TALLOC_FREE(sam_ctx);
1487                         if (!ok) {
1488                                 return WERR_INVALID_DOMAIN_ROLE;
1489                         }
1490                 }
1491
1492                 break;
1493         default:
1494                 return WERR_NOT_SUPPORTED;
1495         }
1496
1497         irpc_handle = irpc_binding_handle_by_name(state,
1498                                                   state->dce_call->msg_ctx,
1499                                                   "winbind_server",
1500                                                   &ndr_table_winbind);
1501         if (irpc_handle == NULL) {
1502                 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
1503                 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1504                 return WERR_SERVICE_NOT_FOUND;
1505         }
1506
1507         /*
1508          * 60 seconds timeout should be enough
1509          */
1510         dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1511
1512         subreq = dcerpc_winbind_LogonControl_send(state,
1513                                                   state->dce_call->event_ctx,
1514                                                   irpc_handle,
1515                                                   state->r.in.function_code,
1516                                                   state->r.in.level,
1517                                                   state->r.in.data,
1518                                                   state->r.out.query);
1519         if (subreq == NULL) {
1520                 return WERR_NOMEM;
1521         }
1522         state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1523         tevent_req_set_callback(subreq,
1524                                 dcesrv_netr_LogonControl_base_done,
1525                                 state);
1526
1527         return WERR_OK;
1528 }
1529
1530 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
1531 {
1532         struct dcesrv_netr_LogonControl_base_state *state =
1533                 tevent_req_callback_data(subreq,
1534                 struct dcesrv_netr_LogonControl_base_state);
1535         NTSTATUS status;
1536
1537         status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
1538                                                   &state->r.out.result);
1539         TALLOC_FREE(subreq);
1540         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
1541                 state->r.out.result = WERR_TIMEOUT;
1542         } else if (!NT_STATUS_IS_OK(status)) {
1543                 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1544                 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
1545                          nt_errstr(status)));
1546         }
1547
1548         if (state->_r.l2ex != NULL) {
1549                 struct netr_LogonControl2Ex *r = state->_r.l2ex;
1550                 r->out.result = state->r.out.result;
1551         } else if (state->_r.l2 != NULL) {
1552                 struct netr_LogonControl2 *r = state->_r.l2;
1553                 r->out.result = state->r.out.result;
1554         } else if (state->_r.l != NULL) {
1555                 struct netr_LogonControl *r = state->_r.l;
1556                 r->out.result = state->r.out.result;
1557         }
1558
1559         status = dcesrv_reply(state->dce_call);
1560         if (!NT_STATUS_IS_OK(status)) {
1561                 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
1562         }
1563 }
1564
1565 /*
1566   netr_LogonControl
1567 */
1568 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1569                        struct netr_LogonControl *r)
1570 {
1571         struct dcesrv_netr_LogonControl_base_state *state;
1572         WERROR werr;
1573
1574         state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1575         if (state == NULL) {
1576                 return WERR_NOMEM;
1577         }
1578
1579         state->dce_call = dce_call;
1580         state->mem_ctx = mem_ctx;
1581
1582         state->r.in.logon_server = r->in.logon_server;
1583         state->r.in.function_code = r->in.function_code;
1584         state->r.in.level = r->in.level;
1585         state->r.in.data = NULL;
1586         state->r.out.query = r->out.query;
1587
1588         state->_r.l = r;
1589
1590         werr = dcesrv_netr_LogonControl_base_call(state);
1591
1592         if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1593                 return werr;
1594         }
1595
1596         return werr;
1597 }
1598
1599 /*
1600   netr_LogonControl2
1601 */
1602 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1603                        struct netr_LogonControl2 *r)
1604 {
1605         struct dcesrv_netr_LogonControl_base_state *state;
1606         WERROR werr;
1607
1608         state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1609         if (state == NULL) {
1610                 return WERR_NOMEM;
1611         }
1612
1613         state->dce_call = dce_call;
1614         state->mem_ctx = mem_ctx;
1615
1616         state->r.in.logon_server = r->in.logon_server;
1617         state->r.in.function_code = r->in.function_code;
1618         state->r.in.level = r->in.level;
1619         state->r.in.data = r->in.data;
1620         state->r.out.query = r->out.query;
1621
1622         state->_r.l2 = r;
1623
1624         werr = dcesrv_netr_LogonControl_base_call(state);
1625
1626         if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1627                 return werr;
1628         }
1629
1630         return werr;
1631 }
1632
1633 /*
1634   netr_LogonControl2Ex
1635 */
1636 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1637                        struct netr_LogonControl2Ex *r)
1638 {
1639         struct dcesrv_netr_LogonControl_base_state *state;
1640         WERROR werr;
1641
1642         state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1643         if (state == NULL) {
1644                 return WERR_NOMEM;
1645         }
1646
1647         state->dce_call = dce_call;
1648         state->mem_ctx = mem_ctx;
1649
1650         state->r = *r;
1651         state->_r.l2ex = r;
1652
1653         werr = dcesrv_netr_LogonControl_base_call(state);
1654
1655         if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1656                 return werr;
1657         }
1658
1659         return werr;
1660 }
1661
1662 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1663                                          struct ldb_context *sam_ctx,
1664                                          struct netr_DomainTrustList *trusts,
1665                                          uint32_t trust_flags);
1666
1667 /*
1668   netr_GetAnyDCName
1669 */
1670 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1671                        struct netr_GetAnyDCName *r)
1672 {
1673         struct netr_DomainTrustList *trusts;
1674         struct ldb_context *sam_ctx;
1675         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1676         uint32_t i;
1677         WERROR werr;
1678
1679         *r->out.dcname = NULL;
1680
1681         if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1682                 /* if the domainname parameter wasn't set assume our domain */
1683                 r->in.domainname = lpcfg_workgroup(lp_ctx);
1684         }
1685
1686         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1687                                 dce_call->conn->auth_state.session_info, 0);
1688         if (sam_ctx == NULL) {
1689                 return WERR_DS_UNAVAILABLE;
1690         }
1691
1692         if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1693                 /* well we asked for a DC of our own domain */
1694                 if (samdb_is_pdc(sam_ctx)) {
1695                         /* we are the PDC of the specified domain */
1696                         return WERR_NO_SUCH_DOMAIN;
1697                 }
1698
1699                 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1700                                                 lpcfg_netbios_name(lp_ctx));
1701                 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1702
1703                 return WERR_OK;
1704         }
1705
1706         /* Okay, now we have to consider the trusted domains */
1707
1708         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1709         W_ERROR_HAVE_NO_MEMORY(trusts);
1710
1711         trusts->count = 0;
1712
1713         werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1714                                           NETR_TRUST_FLAG_INBOUND
1715                                           | NETR_TRUST_FLAG_OUTBOUND);
1716         W_ERROR_NOT_OK_RETURN(werr);
1717
1718         for (i = 0; i < trusts->count; i++) {
1719                 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1720                         /* FIXME: Here we need to find a DC for the specified
1721                          * trusted domain. */
1722
1723                         /* return WERR_OK; */
1724                         return WERR_NO_SUCH_DOMAIN;
1725                 }
1726         }
1727
1728         return WERR_NO_SUCH_DOMAIN;
1729 }
1730
1731
1732 /*
1733   netr_DatabaseRedo
1734 */
1735 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1736                        struct netr_DatabaseRedo *r)
1737 {
1738         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1739 }
1740
1741
1742 /*
1743   netr_NetrEnumerateTrustedDomains
1744 */
1745 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1746                        struct netr_NetrEnumerateTrustedDomains *r)
1747 {
1748         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1749 }
1750
1751
1752 /*
1753   netr_LogonGetCapabilities
1754 */
1755 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1756                        struct netr_LogonGetCapabilities *r)
1757 {
1758         struct netlogon_creds_CredentialState *creds;
1759         NTSTATUS status;
1760
1761         status = dcesrv_netr_creds_server_step_check(dce_call,
1762                                                      mem_ctx,
1763                                                      r->in.computer_name,
1764                                                      r->in.credential,
1765                                                      r->out.return_authenticator,
1766                                                      &creds);
1767         if (!NT_STATUS_IS_OK(status)) {
1768                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1769         }
1770         NT_STATUS_NOT_OK_RETURN(status);
1771
1772         if (r->in.query_level != 1) {
1773                 return NT_STATUS_NOT_SUPPORTED;
1774         }
1775
1776         r->out.capabilities->server_capabilities = creds->negotiate_flags;
1777
1778         return NT_STATUS_OK;
1779 }
1780
1781
1782 /*
1783   netr_NETRLOGONSETSERVICEBITS
1784 */
1785 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1786                        struct netr_NETRLOGONSETSERVICEBITS *r)
1787 {
1788         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1789 }
1790
1791
1792 /*
1793   netr_LogonGetTrustRid
1794 */
1795 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1796                        struct netr_LogonGetTrustRid *r)
1797 {
1798         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1799 }
1800
1801
1802 /*
1803   netr_NETRLOGONCOMPUTESERVERDIGEST
1804 */
1805 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1806                        struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1807 {
1808         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1809 }
1810
1811
1812 /*
1813   netr_NETRLOGONCOMPUTECLIENTDIGEST
1814 */
1815 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1816                        struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1817 {
1818         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1819 }
1820
1821
1822
1823 /*
1824   netr_DsRGetSiteName
1825 */
1826 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1827                                   struct netr_DsRGetSiteName *r)
1828 {
1829         struct ldb_context *sam_ctx;
1830         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1831
1832         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1833                                 dce_call->conn->auth_state.session_info, 0);
1834         if (sam_ctx == NULL) {
1835                 return WERR_DS_UNAVAILABLE;
1836         }
1837
1838         /*
1839          * We assume to be a DC when we get called over NETLOGON. Hence we
1840          * get our site name always by using "samdb_server_site_name()"
1841          * and not "samdb_client_site_name()".
1842          */
1843         *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1844         W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1845
1846         return WERR_OK;
1847 }
1848
1849
1850 /*
1851   fill in a netr_OneDomainInfo from a ldb search result
1852 */
1853 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1854                                      struct loadparm_context *lp_ctx,
1855                                      struct ldb_context *sam_ctx,
1856                                      struct ldb_message *res,
1857                                      struct netr_OneDomainInfo *info,
1858                                      bool is_local, bool is_trust_list)
1859 {
1860         ZERO_STRUCTP(info);
1861
1862         if (is_trust_list) {
1863                 /* w2k8 only fills this on trusted domains */
1864                 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1865                 info->trust_extension.length = 16;
1866                 info->trust_extension.info->flags =
1867                         NETR_TRUST_FLAG_TREEROOT |
1868                         NETR_TRUST_FLAG_IN_FOREST |
1869                         NETR_TRUST_FLAG_PRIMARY |
1870                         NETR_TRUST_FLAG_NATIVE;
1871
1872                 info->trust_extension.info->parent_index = 0; /* should be index into array
1873                                                                  of parent */
1874                 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1875                 info->trust_extension.info->trust_attributes = 0; /*    TODO: base on ldb search? */
1876         }
1877
1878         if (is_trust_list) {
1879                 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1880                 info->dns_forestname.string = NULL;
1881         } else {
1882                 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1883                 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1884                 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1885                 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1886         }
1887
1888         if (is_local) {
1889                 info->domainname.string = lpcfg_workgroup(lp_ctx);
1890                 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1891                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1892                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1893         } else {
1894                 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1895                 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1896                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1897                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1898         }
1899         if (!is_trust_list) {
1900                 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1901         }
1902
1903         return NT_STATUS_OK;
1904 }
1905
1906 /*
1907   netr_LogonGetDomainInfo
1908   this is called as part of the ADS domain logon procedure.
1909
1910   It has an important role in convaying details about the client, such
1911   as Operating System, Version, Service Pack etc.
1912 */
1913 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1914         TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1915 {
1916         struct netlogon_creds_CredentialState *creds;
1917         const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1918                 "securityIdentifier", "trustPartner", NULL };
1919         const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1920                 "msDS-SupportedEncryptionTypes", NULL };
1921         const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1922         struct ldb_context *sam_ctx;
1923         struct ldb_message **res1, **res2, **res3, *new_msg;
1924         struct ldb_dn *workstation_dn;
1925         struct netr_DomainInformation *domain_info;
1926         struct netr_LsaPolicyInformation *lsa_policy_info;
1927         uint32_t default_supported_enc_types = 0xFFFFFFFF;
1928         bool update_dns_hostname = true;
1929         int ret, ret3, i;
1930         NTSTATUS status;
1931
1932         status = dcesrv_netr_creds_server_step_check(dce_call,
1933                                                      mem_ctx,
1934                                                      r->in.computer_name,
1935                                                      r->in.credential,
1936                                                      r->out.return_authenticator,
1937                                                      &creds);
1938         if (!NT_STATUS_IS_OK(status)) {
1939                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1940         }
1941         NT_STATUS_NOT_OK_RETURN(status);
1942
1943         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1944                                 dce_call->conn->dce_ctx->lp_ctx,
1945                                 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1946         if (sam_ctx == NULL) {
1947                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1948         }
1949
1950         switch (r->in.level) {
1951         case 1: /* Domain information */
1952
1953                 if (r->in.query->workstation_info == NULL) {
1954                         return NT_STATUS_INVALID_PARAMETER;
1955                 }
1956
1957                 /* Prepares the workstation DN */
1958                 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1959                                                 dom_sid_string(mem_ctx, creds->sid));
1960                 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1961
1962                 /* Lookup for attributes in workstation object */
1963                 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1964                                       attrs2);
1965                 if (ret != 1) {
1966                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1967                 }
1968
1969                 /* Gets the sam account name which is checked against the DNS
1970                  * hostname parameter. */
1971                 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1972                                                                "sAMAccountName",
1973                                                                NULL);
1974                 if (sam_account_name == NULL) {
1975                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1976                 }
1977
1978                 /*
1979                  * Checks that the sam account name without a possible "$"
1980                  * matches as prefix with the DNS hostname in the workstation
1981                  * info structure.
1982                  */
1983                 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1984                                          strcspn(sam_account_name, "$"));
1985                 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1986                 if (r->in.query->workstation_info->dns_hostname != NULL) {
1987                         prefix2 = talloc_strndup(mem_ctx,
1988                                                  r->in.query->workstation_info->dns_hostname,
1989                                                  strcspn(r->in.query->workstation_info->dns_hostname, "."));
1990                         NT_STATUS_HAVE_NO_MEMORY(prefix2);
1991
1992                         if (strcasecmp(prefix1, prefix2) != 0) {
1993                                 update_dns_hostname = false;
1994                         }
1995                 } else {
1996                         update_dns_hostname = false;
1997                 }
1998
1999                 /* Gets the old DNS hostname */
2000                 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
2001                                                                "dNSHostName",
2002                                                                NULL);
2003
2004                 /*
2005                  * Updates the DNS hostname when the client wishes that the
2006                  * server should handle this for him
2007                  * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
2008                  * obviously only checked when we do already have a
2009                  * "dNSHostName".
2010                  * See MS-NRPC section 3.5.4.3.9
2011                  */
2012                 if ((old_dns_hostname != NULL) &&
2013                     (r->in.query->workstation_info->workstation_flags
2014                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2015                         update_dns_hostname = false;
2016                 }
2017
2018                 /* Gets host information and put them into our directory */
2019
2020                 new_msg = ldb_msg_new(mem_ctx);
2021                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
2022
2023                 new_msg->dn = workstation_dn;
2024
2025                 /* Sets the OS name */
2026
2027                 if (r->in.query->workstation_info->os_name.string == NULL) {
2028                         return NT_STATUS_INVALID_PARAMETER;
2029                 }
2030
2031                 ret = ldb_msg_add_string(new_msg, "operatingSystem",
2032                                          r->in.query->workstation_info->os_name.string);
2033                 if (ret != LDB_SUCCESS) {
2034                         return NT_STATUS_NO_MEMORY;
2035                 }
2036
2037                 /*
2038                  * Sets information from "os_version". On an empty structure
2039                  * the values are cleared.
2040                  */
2041                 if (r->in.query->workstation_info->os_version.os != NULL) {
2042                         struct netr_OsVersionInfoEx *os_version;
2043                         const char *os_version_str;
2044
2045                         os_version = &r->in.query->workstation_info->os_version.os->os;
2046
2047                         if (os_version->CSDVersion == NULL) {
2048                                 return NT_STATUS_INVALID_PARAMETER;
2049                         }
2050
2051                         os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
2052                                                          os_version->MajorVersion,
2053                                                          os_version->MinorVersion,
2054                                                          os_version->BuildNumber);
2055                         NT_STATUS_HAVE_NO_MEMORY(os_version_str);
2056
2057                         ret = ldb_msg_add_string(new_msg,
2058                                                  "operatingSystemServicePack",
2059                                                  os_version->CSDVersion);
2060                         if (ret != LDB_SUCCESS) {
2061                                 return NT_STATUS_NO_MEMORY;
2062                         }
2063
2064                         ret = ldb_msg_add_string(new_msg,
2065                                                  "operatingSystemVersion",
2066                                                  os_version_str);
2067                         if (ret != LDB_SUCCESS) {
2068                                 return NT_STATUS_NO_MEMORY;
2069                         }
2070                 } else {
2071                         ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2072                                                    "operatingSystemServicePack");
2073                         if (ret != LDB_SUCCESS) {
2074                                 return NT_STATUS_NO_MEMORY;
2075                         }
2076
2077                         ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2078                                                    "operatingSystemVersion");
2079                         if (ret != LDB_SUCCESS) {
2080                                 return NT_STATUS_NO_MEMORY;
2081                         }
2082                 }
2083
2084                 /*
2085                  * If the boolean "update_dns_hostname" remained true, then we
2086                  * are fine to start the update.
2087                  */
2088                 if (update_dns_hostname) {
2089                         ret = ldb_msg_add_string(new_msg,
2090                                                  "dNSHostname",
2091                                                  r->in.query->workstation_info->dns_hostname);
2092                         if (ret != LDB_SUCCESS) {
2093                                 return NT_STATUS_NO_MEMORY;
2094                         }
2095
2096                         /* This manual "servicePrincipalName" generation is
2097                          * still needed! Since the update in the samldb LDB
2098                          * module does only work if the entries already exist
2099                          * which isn't always the case. */
2100                         ret = ldb_msg_add_string(new_msg,
2101                                                  "servicePrincipalName",
2102                                                  talloc_asprintf(new_msg, "HOST/%s",
2103                                                  r->in.computer_name));
2104                         if (ret != LDB_SUCCESS) {
2105                                 return NT_STATUS_NO_MEMORY;
2106                         }
2107
2108                         ret = ldb_msg_add_string(new_msg,
2109                                                  "servicePrincipalName",
2110                                                  talloc_asprintf(new_msg, "HOST/%s",
2111                                                  r->in.query->workstation_info->dns_hostname));
2112                         if (ret != LDB_SUCCESS) {
2113                                 return NT_STATUS_NO_MEMORY;
2114                         }
2115                 }
2116
2117                 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
2118                         DEBUG(3,("Impossible to update samdb: %s\n",
2119                                 ldb_errstring(sam_ctx)));
2120                 }
2121
2122                 talloc_free(new_msg);
2123
2124                 /* Writes back the domain information */
2125
2126                 /* We need to do two searches. The first will pull our primary
2127                    domain and the second will pull any trusted domains. Our
2128                    primary domain is also a "trusted" domain, so we need to
2129                    put the primary domain into the lists of returned trusts as
2130                    well. */
2131                 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
2132                         &res2, attrs);
2133                 if (ret != 1) {
2134                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2135                 }
2136
2137                 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
2138                         "(objectClass=trustedDomain)");
2139                 if (ret3 == -1) {
2140                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2141                 }
2142
2143                 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
2144                 NT_STATUS_HAVE_NO_MEMORY(domain_info);
2145
2146                 ZERO_STRUCTP(domain_info);
2147
2148                 /* Informations about the local and trusted domains */
2149
2150                 status = fill_one_domain_info(mem_ctx,
2151                         dce_call->conn->dce_ctx->lp_ctx,
2152                         sam_ctx, res2[0], &domain_info->primary_domain,
2153                         true, false);
2154                 NT_STATUS_NOT_OK_RETURN(status);
2155
2156                 domain_info->trusted_domain_count = ret3 + 1;
2157                 domain_info->trusted_domains = talloc_array(mem_ctx,
2158                         struct netr_OneDomainInfo,
2159                         domain_info->trusted_domain_count);
2160                 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
2161
2162                 for (i=0;i<ret3;i++) {
2163                         status = fill_one_domain_info(mem_ctx,
2164                                 dce_call->conn->dce_ctx->lp_ctx,
2165                                 sam_ctx, res3[i],
2166                                 &domain_info->trusted_domains[i],
2167                                 false, true);
2168                         NT_STATUS_NOT_OK_RETURN(status);
2169                 }
2170
2171                 status = fill_one_domain_info(mem_ctx,
2172                         dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
2173                         &domain_info->trusted_domains[i], true, true);
2174                 NT_STATUS_NOT_OK_RETURN(status);
2175
2176                 /* Sets the supported encryption types */
2177                 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
2178                         "msDS-SupportedEncryptionTypes",
2179                         default_supported_enc_types);
2180
2181                 /* Other host domain information */
2182
2183                 lsa_policy_info = talloc(mem_ctx,
2184                         struct netr_LsaPolicyInformation);
2185                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2186                 ZERO_STRUCTP(lsa_policy_info);
2187
2188                 domain_info->lsa_policy = *lsa_policy_info;
2189
2190                 /* The DNS hostname is only returned back when there is a chance
2191                  * for a change. */
2192                 if ((r->in.query->workstation_info->workstation_flags
2193                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2194                         domain_info->dns_hostname.string = old_dns_hostname;
2195                 } else {
2196                         domain_info->dns_hostname.string = NULL;
2197                 }
2198
2199                 domain_info->workstation_flags =
2200                         r->in.query->workstation_info->workstation_flags & (
2201                         NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
2202
2203                 r->out.info->domain_info = domain_info;
2204         break;
2205         case 2: /* LSA policy information - not used at the moment */
2206                 lsa_policy_info = talloc(mem_ctx,
2207                         struct netr_LsaPolicyInformation);
2208                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2209                 ZERO_STRUCTP(lsa_policy_info);
2210
2211                 r->out.info->lsa_policy_info = lsa_policy_info;
2212         break;
2213         default:
2214                 return NT_STATUS_INVALID_LEVEL;
2215         break;
2216         }
2217
2218         return NT_STATUS_OK;
2219 }
2220
2221
2222 /*
2223   netr_ServerPasswordGet
2224 */
2225 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2226                        struct netr_ServerPasswordGet *r)
2227 {
2228         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2229 }
2230
2231
2232 /*
2233   netr_NETRLOGONSENDTOSAM
2234 */
2235 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2236                        struct netr_NETRLOGONSENDTOSAM *r)
2237 {
2238         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2239 }
2240
2241
2242 /*
2243   netr_DsRGetDCNameEx2
2244 */
2245 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
2246                                           TALLOC_CTX *mem_ctx,
2247                                           struct netr_DsRGetDCNameEx2 *r)
2248 {
2249         struct ldb_context *sam_ctx;
2250         struct netr_DsRGetDCNameInfo *info;
2251         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2252         const struct tsocket_address *local_address;
2253         char *local_addr = NULL;
2254         const struct tsocket_address *remote_address;
2255         char *remote_addr = NULL;
2256         const char *server_site_name;
2257         char *guid_str;
2258         struct netlogon_samlogon_response response;
2259         NTSTATUS status;
2260         const char *dc_name = NULL;
2261         const char *domain_name = NULL;
2262         const char *pdc_ip;
2263
2264         ZERO_STRUCTP(r->out.info);
2265
2266         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2267                                 dce_call->conn->auth_state.session_info, 0);
2268         if (sam_ctx == NULL) {
2269                 return WERR_DS_UNAVAILABLE;
2270         }
2271
2272         local_address = dcesrv_connection_get_local_address(dce_call->conn);
2273         if (tsocket_address_is_inet(local_address, "ip")) {
2274                 local_addr = tsocket_address_inet_addr_string(local_address, mem_ctx);
2275                 W_ERROR_HAVE_NO_MEMORY(local_addr);
2276         }
2277
2278         remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
2279         if (tsocket_address_is_inet(remote_address, "ip")) {
2280                 remote_addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
2281                 W_ERROR_HAVE_NO_MEMORY(remote_addr);
2282         }
2283
2284         /* "server_unc" is ignored by w2k3 */
2285
2286         if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
2287                 return WERR_INVALID_FLAGS;
2288         }
2289
2290         if (r->in.flags & DS_GC_SERVER_REQUIRED &&
2291             r->in.flags & DS_PDC_REQUIRED &&
2292             r->in.flags & DS_KDC_REQUIRED) {
2293                 return WERR_INVALID_FLAGS;
2294         }
2295         if (r->in.flags & DS_IS_FLAT_NAME &&
2296             r->in.flags & DS_IS_DNS_NAME) {
2297                 return WERR_INVALID_FLAGS;
2298         }
2299         if (r->in.flags & DS_RETURN_DNS_NAME &&
2300             r->in.flags & DS_RETURN_FLAT_NAME) {
2301                 return WERR_INVALID_FLAGS;
2302         }
2303         if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
2304             r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
2305                 return WERR_INVALID_FLAGS;
2306         }
2307
2308         if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
2309             r->in.flags &
2310             (DS_DIRECTORY_SERVICE_REQUIRED |
2311              DS_DIRECTORY_SERVICE_PREFERRED |
2312              DS_GC_SERVER_REQUIRED |
2313              DS_PDC_REQUIRED |
2314              DS_KDC_REQUIRED)) {
2315                 return WERR_INVALID_FLAGS;
2316         }
2317
2318         if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
2319             r->in.site_name) {
2320                 return WERR_INVALID_FLAGS;
2321         }
2322
2323         /* Proof server site parameter "site_name" if it was specified */
2324         server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
2325         W_ERROR_HAVE_NO_MEMORY(server_site_name);
2326         if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
2327                                                      server_site_name) != 0)) {
2328                 return WERR_NO_SUCH_DOMAIN;
2329         }
2330
2331         guid_str = r->in.domain_guid != NULL ?
2332                  GUID_string(mem_ctx, r->in.domain_guid) : NULL;
2333
2334         status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
2335                                                  r->in.domain_name,
2336                                                  r->in.domain_name,
2337                                                  NULL, guid_str,
2338                                                  r->in.client_account,
2339                                                  r->in.mask, remote_addr,
2340                                                  NETLOGON_NT_VERSION_5EX_WITH_IP,
2341                                                  lp_ctx, &response, true);
2342         if (!NT_STATUS_IS_OK(status)) {
2343                 return ntstatus_to_werror(status);
2344         }
2345
2346         /*
2347          * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
2348          * (O) flag when the returned forest name is in DNS format. This is here
2349          * always the case (see below).
2350          */
2351         response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
2352
2353         if (r->in.flags & DS_RETURN_DNS_NAME) {
2354                 dc_name = response.data.nt5_ex.pdc_dns_name;
2355                 domain_name = response.data.nt5_ex.dns_domain;
2356                 /*
2357                  * According to MS-NRPC 2.2.1.2.1 we should set the
2358                  * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
2359                  * the returned information is in DNS form.
2360                  */
2361                 response.data.nt5_ex.server_type |=
2362                         DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
2363         } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
2364                 dc_name = response.data.nt5_ex.pdc_name;
2365                 domain_name = response.data.nt5_ex.domain_name;
2366         } else {
2367
2368                 /*
2369                  * TODO: autodetect what we need to return
2370                  * based on the given arguments
2371                  */
2372                 dc_name = response.data.nt5_ex.pdc_name;
2373                 domain_name = response.data.nt5_ex.domain_name;
2374         }
2375
2376         if (!dc_name || !dc_name[0]) {
2377                 return WERR_NO_SUCH_DOMAIN;
2378         }
2379
2380         if (!domain_name || !domain_name[0]) {
2381                 return WERR_NO_SUCH_DOMAIN;
2382         }
2383
2384         info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
2385         W_ERROR_HAVE_NO_MEMORY(info);
2386         info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
2387                         dc_name[0] != '\\'? "\\\\":"",
2388                         talloc_strdup(mem_ctx, dc_name));
2389         W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
2390
2391         pdc_ip = local_addr;
2392         if (pdc_ip == NULL) {
2393                 pdc_ip = "127.0.0.1";
2394         }
2395         info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
2396         W_ERROR_HAVE_NO_MEMORY(info->dc_address);
2397         info->dc_address_type  = DS_ADDRESS_TYPE_INET;
2398         info->domain_guid      = response.data.nt5_ex.domain_uuid;
2399         info->domain_name      = domain_name;
2400         info->forest_name      = response.data.nt5_ex.forest;
2401         info->dc_flags         = response.data.nt5_ex.server_type;
2402         if (r->in.flags & DS_RETURN_DNS_NAME) {
2403                 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
2404                  * returned if we are returning info->dc_unc containing a FQDN.
2405                  * This attribute is called DomainControllerName in the specs,
2406                  * it seems that we decide to return FQDN or netbios depending on
2407                  * DS_RETURN_DNS_NAME.
2408                  */
2409                 info->dc_flags |= DS_DNS_CONTROLLER;
2410         }
2411         info->dc_site_name     = response.data.nt5_ex.server_site;
2412         info->client_site_name = response.data.nt5_ex.client_site;
2413
2414         *r->out.info = info;
2415
2416         return WERR_OK;
2417 }
2418
2419 /*
2420   netr_DsRGetDCNameEx
2421 */
2422 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2423                                   struct netr_DsRGetDCNameEx *r)
2424 {
2425         struct netr_DsRGetDCNameEx2 r2;
2426         WERROR werr;
2427
2428         ZERO_STRUCT(r2);
2429
2430         r2.in.server_unc = r->in.server_unc;
2431         r2.in.client_account = NULL;
2432         r2.in.mask = 0;
2433         r2.in.domain_guid = r->in.domain_guid;
2434         r2.in.domain_name = r->in.domain_name;
2435         r2.in.site_name = r->in.site_name;
2436         r2.in.flags = r->in.flags;
2437         r2.out.info = r->out.info;
2438
2439         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2440
2441         return werr;
2442 }
2443
2444 /*
2445   netr_DsRGetDCName
2446 */
2447 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2448                                 struct netr_DsRGetDCName *r)
2449 {
2450         struct netr_DsRGetDCNameEx2 r2;
2451         WERROR werr;
2452
2453         ZERO_STRUCT(r2);
2454
2455         r2.in.server_unc = r->in.server_unc;
2456         r2.in.client_account = NULL;
2457         r2.in.mask = 0;
2458         r2.in.domain_name = r->in.domain_name;
2459         r2.in.domain_guid = r->in.domain_guid;
2460
2461         r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
2462         r2.in.flags = r->in.flags;
2463         r2.out.info = r->out.info;
2464
2465         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2466
2467         return werr;
2468 }
2469 /*
2470   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
2471 */
2472 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2473                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
2474 {
2475         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2476 }
2477
2478
2479 /*
2480   netr_NetrEnumerateTrustedDomainsEx
2481 */
2482 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2483                        struct netr_NetrEnumerateTrustedDomainsEx *r)
2484 {
2485         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2486 }
2487
2488
2489 /*
2490   netr_DsRAddressToSitenamesExW
2491 */
2492 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2493                                                    struct netr_DsRAddressToSitenamesExW *r)
2494 {
2495         struct ldb_context *sam_ctx;
2496         struct netr_DsRAddressToSitenamesExWCtr *ctr;
2497         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2498         sa_family_t sin_family;
2499         struct sockaddr_in *addr;
2500 #ifdef HAVE_IPV6
2501         struct sockaddr_in6 *addr6;
2502         char addr_str[INET6_ADDRSTRLEN];
2503 #else
2504         char addr_str[INET_ADDRSTRLEN];
2505 #endif
2506         char *subnet_name;
2507         const char *res;
2508         uint32_t i;
2509
2510         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2511                                 dce_call->conn->auth_state.session_info, 0);
2512         if (sam_ctx == NULL) {
2513                 return WERR_DS_UNAVAILABLE;
2514         }
2515
2516         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
2517         W_ERROR_HAVE_NO_MEMORY(ctr);
2518
2519         *r->out.ctr = ctr;
2520
2521         ctr->count = r->in.count;
2522         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2523         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2524         ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
2525         W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
2526
2527         for (i=0; i<ctr->count; i++) {
2528                 ctr->sitename[i].string = NULL;
2529                 ctr->subnetname[i].string = NULL;
2530
2531                 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2532                         continue;
2533                 }
2534                 /* The first two byte of the buffer are reserved for the
2535                  * "sin_family" but for now only the first one is used. */
2536                 sin_family = r->in.addresses[i].buffer[0];
2537
2538                 switch (sin_family) {
2539                 case AF_INET:
2540                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2541                                 continue;
2542                         }
2543                         addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2544                         res = inet_ntop(AF_INET, &addr->sin_addr,
2545                                         addr_str, sizeof(addr_str));
2546                         break;
2547 #ifdef HAVE_IPV6
2548                 case AF_INET6:
2549                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2550                                 continue;
2551                         }
2552                         addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2553                         res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2554                                         addr_str, sizeof(addr_str));
2555                         break;
2556 #endif
2557                 default:
2558                         continue;
2559                 }
2560
2561                 if (res == NULL) {
2562                         continue;
2563                 }
2564
2565                 ctr->sitename[i].string   = samdb_client_site_name(sam_ctx,
2566                                                                    mem_ctx,
2567                                                                    addr_str,
2568                                                                    &subnet_name);
2569                 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2570                 ctr->subnetname[i].string = subnet_name;
2571         }
2572
2573         return WERR_OK;
2574 }
2575
2576
2577 /*
2578   netr_DsRAddressToSitenamesW
2579 */
2580 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2581                        struct netr_DsRAddressToSitenamesW *r)
2582 {
2583         struct netr_DsRAddressToSitenamesExW r2;
2584         struct netr_DsRAddressToSitenamesWCtr *ctr;
2585         uint32_t i;
2586         WERROR werr;
2587
2588         ZERO_STRUCT(r2);
2589
2590         r2.in.server_name = r->in.server_name;
2591         r2.in.count = r->in.count;
2592         r2.in.addresses = r->in.addresses;
2593
2594         r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2595         W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2596
2597         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2598         W_ERROR_HAVE_NO_MEMORY(ctr);
2599
2600         *r->out.ctr = ctr;
2601
2602         ctr->count = r->in.count;
2603         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2604         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2605
2606         werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2607
2608         for (i=0; i<ctr->count; i++) {
2609                 ctr->sitename[i].string   = (*r2.out.ctr)->sitename[i].string;
2610         }
2611
2612         return werr;
2613 }
2614
2615
2616 /*
2617   netr_DsrGetDcSiteCoverageW
2618 */
2619 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2620                        struct netr_DsrGetDcSiteCoverageW *r)
2621 {
2622         struct ldb_context *sam_ctx;
2623         struct DcSitesCtr *ctr;
2624         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2625
2626         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2627                                 dce_call->conn->auth_state.session_info, 0);
2628         if (sam_ctx == NULL) {
2629                 return WERR_DS_UNAVAILABLE;
2630         }
2631
2632         ctr = talloc(mem_ctx, struct DcSitesCtr);
2633         W_ERROR_HAVE_NO_MEMORY(ctr);
2634
2635         *r->out.ctr = ctr;
2636
2637         /* For now only return our default site */
2638         ctr->num_sites = 1;
2639         ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2640         W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2641         ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2642         W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2643
2644         return WERR_OK;
2645 }
2646
2647
2648 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2649                                          struct ldb_context *sam_ctx,
2650                                          struct netr_DomainTrustList *trusts,
2651                                          uint32_t trust_flags)
2652 {
2653         struct ldb_dn *system_dn;
2654         struct ldb_message **dom_res = NULL;
2655         const char *trust_attrs[] = { "flatname", "trustPartner",
2656                                       "securityIdentifier", "trustDirection",
2657                                       "trustType", "trustAttributes", NULL };
2658         uint32_t n;
2659         int i;
2660         int ret;
2661
2662         if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2663                              NETR_TRUST_FLAG_OUTBOUND))) {
2664                 return WERR_INVALID_FLAGS;
2665         }
2666
2667         system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2668                                     ldb_get_default_basedn(sam_ctx),
2669                                     "(&(objectClass=container)(cn=System))");
2670         if (!system_dn) {
2671                 return WERR_GENERAL_FAILURE;
2672         }
2673
2674         ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2675                            &dom_res, trust_attrs,
2676                            "(objectclass=trustedDomain)");
2677
2678         for (i = 0; i < ret; i++) {
2679                 unsigned int trust_dir;
2680                 uint32_t flags = 0;
2681
2682                 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2683                                                       "trustDirection", 0);
2684
2685                 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2686                         flags |= NETR_TRUST_FLAG_INBOUND;
2687                 }
2688                 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2689                         flags |= NETR_TRUST_FLAG_OUTBOUND;
2690                 }
2691
2692                 if (!(flags & trust_flags)) {
2693                         /* this trust direction was not requested */
2694                         continue;
2695                 }
2696
2697                 n = trusts->count;
2698                 trusts->array = talloc_realloc(trusts, trusts->array,
2699                                                struct netr_DomainTrust,
2700                                                n + 1);
2701                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2702
2703                 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2704                 if (!trusts->array[n].netbios_name) {
2705                         DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2706                                   "without flatname\n", 
2707                                   ldb_dn_get_linearized(dom_res[i]->dn)));
2708                 }
2709
2710                 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2711
2712                 trusts->array[n].trust_flags = flags;
2713                 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2714                     !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2715                         /* TODO: find if we have parent in the list */
2716                         trusts->array[n].parent_index = 0;
2717                 }
2718
2719                 trusts->array[n].trust_type =
2720                                 ldb_msg_find_attr_as_uint(dom_res[i],
2721                                                   "trustType", 0);
2722                 trusts->array[n].trust_attributes =
2723                                 ldb_msg_find_attr_as_uint(dom_res[i],
2724                                                   "trustAttributes", 0);
2725
2726                 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
2727                     (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
2728                         struct dom_sid zero_sid;
2729                         ZERO_STRUCT(zero_sid);
2730                         trusts->array[n].sid =
2731                                 dom_sid_dup(trusts, &zero_sid);
2732                 } else {
2733                         trusts->array[n].sid =
2734                                 samdb_result_dom_sid(trusts, dom_res[i],
2735                                                      "securityIdentifier");
2736                 }
2737                 trusts->array[n].guid = GUID_zero();
2738
2739                 trusts->count = n + 1;
2740         }
2741
2742         talloc_free(dom_res);
2743         return WERR_OK;
2744 }
2745
2746 /*
2747   netr_DsrEnumerateDomainTrusts
2748 */
2749 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2750                                                    TALLOC_CTX *mem_ctx,
2751                                                    struct netr_DsrEnumerateDomainTrusts *r)
2752 {
2753         struct netr_DomainTrustList *trusts;
2754         struct ldb_context *sam_ctx;
2755         int ret;
2756         struct ldb_message **dom_res;
2757         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2758         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2759         const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2760         const char *p;
2761         WERROR werr;
2762
2763         if (r->in.trust_flags & 0xFFFFFE00) {
2764                 return WERR_INVALID_FLAGS;
2765         }
2766
2767         /* TODO: turn to hard check once we are sure this is 100% correct */
2768         if (!r->in.server_name) {
2769                 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2770                           "But received NULL!\n", dnsdomain));
2771         } else {
2772                 p = strchr(r->in.server_name, '.');
2773                 if (!p) {
2774                         DEBUG(3, ("Invalid domain! Expected name in domain "
2775                                   "[%s]. But received [%s]!\n",
2776                                   dnsdomain, r->in.server_name));
2777                         p = r->in.server_name;
2778                 } else {
2779                         p++;
2780                 }
2781                 if (strcasecmp(p, dnsdomain)) {
2782                         DEBUG(3, ("Invalid domain! Expected name in domain "
2783                                   "[%s]. But received [%s]!\n",
2784                                   dnsdomain, r->in.server_name));
2785                 }
2786         }
2787
2788         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2789         W_ERROR_HAVE_NO_MEMORY(trusts);
2790
2791         trusts->count = 0;
2792         r->out.trusts = trusts;
2793
2794         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2795                                 dce_call->conn->auth_state.session_info, 0);
2796         if (sam_ctx == NULL) {
2797                 return WERR_GENERAL_FAILURE;
2798         }
2799
2800         if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2801             (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2802
2803                 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2804                                                   trusts, r->in.trust_flags);
2805                 W_ERROR_NOT_OK_RETURN(werr);
2806         }
2807
2808         /* NOTE: we currently are always the root of the forest */
2809         if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2810                 uint32_t n = trusts->count;
2811
2812                 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2813                                       &dom_res, dom_attrs);
2814                 if (ret != 1) {
2815                         return WERR_GENERAL_FAILURE;
2816                 }
2817
2818                 trusts->count = n + 1;
2819                 trusts->array = talloc_realloc(trusts, trusts->array,
2820                                                struct netr_DomainTrust,
2821                                                trusts->count);
2822                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2823
2824                 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2825                 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2826                 trusts->array[n].trust_flags =
2827                         NETR_TRUST_FLAG_NATIVE |
2828                         NETR_TRUST_FLAG_TREEROOT |
2829                         NETR_TRUST_FLAG_IN_FOREST |
2830                         NETR_TRUST_FLAG_PRIMARY;
2831                 /* we are always the root domain for now */
2832                 trusts->array[n].parent_index = 0;
2833                 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
2834                 trusts->array[n].trust_attributes = 0;
2835                 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2836                                                             dom_res[0],
2837                                                             "objectSid");
2838                 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2839                                                           "objectGUID");
2840                 talloc_free(dom_res);
2841         }
2842
2843         return WERR_OK;
2844 }
2845
2846
2847 /*
2848   netr_DsrDeregisterDNSHostRecords
2849 */
2850 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2851                        struct netr_DsrDeregisterDNSHostRecords *r)
2852 {
2853         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2854 }
2855
2856
2857 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2858                        struct netr_ServerGetTrustInfo *r);
2859
2860 /*
2861   netr_ServerTrustPasswordsGet
2862 */
2863 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2864                        struct netr_ServerTrustPasswordsGet *r)
2865 {
2866         struct netr_ServerGetTrustInfo r2 = {};
2867         struct netr_TrustInfo *_ti = NULL;
2868         NTSTATUS status;
2869
2870         r2.in.server_name = r->in.server_name;
2871         r2.in.account_name = r->in.account_name;
2872         r2.in.secure_channel_type = r->in.secure_channel_type;
2873         r2.in.computer_name = r->in.computer_name;
2874         r2.in.credential = r->in.credential;
2875
2876         r2.out.return_authenticator = r->out.return_authenticator;
2877         r2.out.new_owf_password = r->out.new_owf_password;
2878         r2.out.old_owf_password = r->out.old_owf_password;
2879         r2.out.trust_info = &_ti;
2880
2881         status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
2882
2883         r->out.return_authenticator = r2.out.return_authenticator;
2884         r->out.new_owf_password = r2.out.new_owf_password;
2885         r->out.old_owf_password = r2.out.old_owf_password;
2886
2887         return status;
2888 }
2889
2890 /*
2891   netr_DsRGetForestTrustInformation
2892 */
2893 struct dcesrv_netr_DsRGetForestTrustInformation_state {
2894         struct dcesrv_call_state *dce_call;
2895         TALLOC_CTX *mem_ctx;
2896         struct netr_DsRGetForestTrustInformation *r;
2897 };
2898
2899 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
2900
2901 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2902                                                        TALLOC_CTX *mem_ctx,
2903                                                        struct netr_DsRGetForestTrustInformation *r)
2904 {
2905         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2906         struct dcesrv_connection *conn = dce_call->conn;
2907         struct auth_session_info *session_info = conn->auth_state.session_info;
2908         enum security_user_level security_level;
2909         struct ldb_context *sam_ctx = NULL;
2910         struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
2911         struct dcerpc_binding_handle *irpc_handle = NULL;
2912         struct tevent_req *subreq = NULL;
2913         struct ldb_dn *domain_dn = NULL;
2914         struct ldb_dn *forest_dn = NULL;
2915         int cmp;
2916         int forest_level;
2917
2918         security_level = security_session_user_level(session_info, NULL);
2919         if (security_level < SECURITY_USER) {
2920                 return WERR_ACCESS_DENIED;
2921         }
2922
2923         if (r->in.flags & 0xFFFFFFFE) {
2924                 return WERR_INVALID_FLAGS;
2925         }
2926
2927         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2928                                 dce_call->conn->auth_state.session_info, 0);
2929         if (sam_ctx == NULL) {
2930                 return WERR_GENERAL_FAILURE;
2931         }
2932
2933         domain_dn = ldb_get_default_basedn(sam_ctx);
2934         if (domain_dn == NULL) {
2935                 return WERR_GENERAL_FAILURE;
2936         }
2937
2938         forest_dn = ldb_get_root_basedn(sam_ctx);
2939         if (forest_dn == NULL) {
2940                 return WERR_GENERAL_FAILURE;
2941         }
2942
2943         cmp = ldb_dn_compare(domain_dn, forest_dn);
2944         if (cmp != 0) {
2945                 return WERR_NERR_ACFNOTLOADED;
2946         }
2947
2948         forest_level = dsdb_forest_functional_level(sam_ctx);
2949         if (forest_level < DS_DOMAIN_FUNCTION_2003) {
2950                 return WERR_INVALID_FUNCTION;
2951         }
2952
2953         if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2954                 if (!samdb_is_pdc(sam_ctx)) {
2955                         return WERR_NERR_NOTPRIMARY;
2956                 }
2957
2958                 if (r->in.trusted_domain_name == NULL) {
2959                         return WERR_INVALID_FLAGS;
2960                 }
2961         }
2962
2963         if (r->in.trusted_domain_name == NULL) {
2964                 NTSTATUS status;
2965
2966                 /*
2967                  * information about our own domain
2968                  */
2969                 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
2970                                                 r->out.forest_trust_info);
2971                 if (!NT_STATUS_IS_OK(status)) {
2972                         return ntstatus_to_werror(status);
2973                 }
2974
2975                 return WERR_OK;
2976         }
2977
2978         /*
2979          * Forward the request to winbindd
2980          */
2981
2982         state = talloc_zero(mem_ctx,
2983                         struct dcesrv_netr_DsRGetForestTrustInformation_state);
2984         if (state == NULL) {
2985                 return WERR_NOMEM;
2986         }
2987         state->dce_call = dce_call;
2988         state->mem_ctx = mem_ctx;
2989         state->r = r;
2990
2991         irpc_handle = irpc_binding_handle_by_name(state,
2992                                                   state->dce_call->msg_ctx,
2993                                                   "winbind_server",
2994                                                   &ndr_table_winbind);
2995         if (irpc_handle == NULL) {
2996                 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
2997                 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2998                 return WERR_SERVICE_NOT_FOUND;
2999         }
3000
3001         /*
3002          * 60 seconds timeout should be enough
3003          */
3004         dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3005
3006         subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
3007                                                 state->dce_call->event_ctx,
3008                                                 irpc_handle,
3009                                                 r->in.trusted_domain_name,
3010                                                 r->in.flags,
3011                                                 r->out.forest_trust_info);
3012         if (subreq == NULL) {
3013                 return WERR_NOMEM;
3014         }
3015         state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3016         tevent_req_set_callback(subreq,
3017                                 dcesrv_netr_DsRGetForestTrustInformation_done,
3018                                 state);
3019
3020         return WERR_OK;
3021 }
3022
3023 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
3024 {
3025         struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
3026                 tevent_req_callback_data(subreq,
3027                 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3028         NTSTATUS status;
3029
3030         status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
3031                                                         state->mem_ctx,
3032                                                         &state->r->out.result);
3033         TALLOC_FREE(subreq);
3034         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3035                 state->r->out.result = WERR_TIMEOUT;
3036         } else if (!NT_STATUS_IS_OK(status)) {
3037                 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3038                 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
3039                          nt_errstr(status)));
3040         }
3041
3042         status = dcesrv_reply(state->dce_call);
3043         if (!NT_STATUS_IS_OK(status)) {
3044                 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3045         }
3046 }
3047
3048 /*
3049   netr_GetForestTrustInformation
3050 */
3051 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
3052                                                       TALLOC_CTX *mem_ctx,
3053                                                       struct netr_GetForestTrustInformation *r)
3054 {
3055         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3056         struct netlogon_creds_CredentialState *creds = NULL;
3057         struct ldb_context *sam_ctx = NULL;
3058         struct ldb_dn *domain_dn = NULL;
3059         struct ldb_dn *forest_dn = NULL;
3060         int cmp;
3061         int forest_level;
3062         NTSTATUS status;
3063
3064         status = dcesrv_netr_creds_server_step_check(dce_call,
3065                                                      mem_ctx,
3066                                                      r->in.computer_name,
3067                                                      r->in.credential,
3068                                                      r->out.return_authenticator,
3069                                                      &creds);
3070         if (!NT_STATUS_IS_OK(status)) {
3071                 return status;
3072         }
3073
3074         if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
3075             (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
3076                 return NT_STATUS_NOT_IMPLEMENTED;
3077         }
3078
3079         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3080                                 dce_call->conn->auth_state.session_info, 0);
3081         if (sam_ctx == NULL) {
3082                 return NT_STATUS_INTERNAL_ERROR;
3083         }
3084
3085         /* TODO: check r->in.server_name is our name */
3086
3087         domain_dn = ldb_get_default_basedn(sam_ctx);
3088         if (domain_dn == NULL) {
3089                 return NT_STATUS_INTERNAL_ERROR;
3090         }
3091
3092         forest_dn = ldb_get_root_basedn(sam_ctx);
3093         if (forest_dn == NULL) {
3094                 return NT_STATUS_INTERNAL_ERROR;
3095         }
3096
3097         cmp = ldb_dn_compare(domain_dn, forest_dn);
3098         if (cmp != 0) {
3099                 return NT_STATUS_INVALID_DOMAIN_STATE;
3100         }
3101
3102         forest_level = dsdb_forest_functional_level(sam_ctx);
3103         if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3104                 return NT_STATUS_INVALID_DOMAIN_STATE;
3105         }
3106
3107         status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3108                                              r->out.forest_trust_info);
3109         if (!NT_STATUS_IS_OK(status)) {
3110                 return status;
3111         }
3112
3113         return NT_STATUS_OK;
3114 }
3115
3116
3117 /*
3118   netr_ServerGetTrustInfo
3119 */
3120 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3121                        struct netr_ServerGetTrustInfo *r)
3122 {
3123         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3124         struct netlogon_creds_CredentialState *creds = NULL;
3125         struct ldb_context *sam_ctx = NULL;
3126         const char * const attrs[] = {
3127                 "unicodePwd",
3128                 "sAMAccountName",
3129                 "userAccountControl",
3130                 NULL
3131         };
3132         struct ldb_message **res = NULL;
3133         struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
3134         NTSTATUS nt_status;
3135         int ret;
3136         const char *asid = NULL;
3137         uint32_t uac = 0;
3138         const char *aname = NULL;
3139         struct ldb_message *tdo_msg = NULL;
3140         const char * const tdo_attrs[] = {
3141                 "trustAuthIncoming",
3142                 "trustAttributes",
3143                 NULL
3144         };
3145         struct netr_TrustInfo *trust_info = NULL;
3146
3147         ZERO_STRUCTP(r->out.new_owf_password);
3148         ZERO_STRUCTP(r->out.old_owf_password);
3149
3150         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3151                                                         mem_ctx,
3152                                                         r->in.computer_name,
3153                                                         r->in.credential,
3154                                                         r->out.return_authenticator,
3155                                                         &creds);
3156         if (!NT_STATUS_IS_OK(nt_status)) {
3157                 return nt_status;
3158         }
3159
3160         /* TODO: check r->in.server_name is our name */
3161
3162         if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
3163                 return NT_STATUS_INVALID_PARAMETER;
3164         }
3165
3166         if (r->in.secure_channel_type != creds->secure_channel_type) {
3167                 return NT_STATUS_INVALID_PARAMETER;
3168         }
3169
3170         if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
3171                 return NT_STATUS_INVALID_PARAMETER;
3172         }
3173
3174         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
3175                                 lp_ctx, system_session(lp_ctx), 0);
3176         if (sam_ctx == NULL) {
3177                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
3178         }
3179
3180         asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
3181         if (asid == NULL) {
3182                 return NT_STATUS_NO_MEMORY;
3183         }
3184
3185         ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
3186                            "(&(objectClass=user)(objectSid=%s))",
3187                            asid);
3188         if (ret != 1) {
3189                 return NT_STATUS_ACCOUNT_DISABLED;
3190         }
3191
3192         switch (creds->secure_channel_type) {
3193         case SEC_CHAN_DNS_DOMAIN:
3194         case SEC_CHAN_DOMAIN:
3195                 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
3196
3197                 if (uac & UF_ACCOUNTDISABLE) {
3198                         return NT_STATUS_ACCOUNT_DISABLED;
3199                 }
3200
3201                 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
3202                         return NT_STATUS_ACCOUNT_DISABLED;
3203                 }
3204
3205                 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
3206                 if (aname == NULL) {
3207                         return NT_STATUS_ACCOUNT_DISABLED;
3208                 }
3209
3210                 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
3211                                                 SEC_CHAN_DOMAIN, aname,
3212                                                 tdo_attrs, mem_ctx, &tdo_msg);
3213                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3214                         return NT_STATUS_ACCOUNT_DISABLED;
3215                 }
3216                 if (!NT_STATUS_IS_OK(nt_status)) {
3217                         return nt_status;
3218                 }
3219
3220                 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
3221                                                               &curNtHash,
3222                                                               &prevNtHash);
3223                 if (!NT_STATUS_IS_OK(nt_status)) {
3224                         return nt_status;
3225                 }
3226
3227                 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
3228                 if (trust_info == NULL) {
3229                         return NT_STATUS_NO_MEMORY;
3230                 }
3231
3232                 trust_info->count = 1;
3233                 trust_info->data = talloc_array(trust_info, uint32_t,
3234                                                 trust_info->count);
3235                 if (trust_info->data == NULL) {
3236                         return NT_STATUS_NO_MEMORY;
3237                 }
3238
3239                 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
3240                                                         "trustAttributes",
3241                                                         0);
3242                 break;
3243
3244         default:
3245                 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
3246                                                               res[0],
3247                                                               NULL, &curNtHash);
3248                 if (!NT_STATUS_IS_OK(nt_status)) {
3249                         return nt_status;
3250                 }
3251
3252                 prevNtHash = talloc(mem_ctx, struct samr_Password);
3253                 if (prevNtHash == NULL) {
3254                         return NT_STATUS_NO_MEMORY;
3255                 }
3256
3257                 E_md4hash("", prevNtHash->hash);
3258                 break;
3259         }
3260
3261         if (curNtHash != NULL) {
3262                 *r->out.new_owf_password = *curNtHash;
3263                 netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
3264         }
3265         if (prevNtHash != NULL) {
3266                 *r->out.old_owf_password = *prevNtHash;
3267                 netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
3268         }
3269
3270         if (trust_info != NULL) {
3271                 *r->out.trust_info = trust_info;
3272         }
3273
3274         return NT_STATUS_OK;
3275 }
3276
3277 /*
3278   netr_Unused47
3279 */
3280 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3281                                      struct netr_Unused47 *r)
3282 {
3283         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3284 }
3285
3286
3287 struct netr_dnsupdate_RODC_state {
3288         struct dcesrv_call_state *dce_call;
3289         struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
3290         struct dnsupdate_RODC *r2;
3291 };
3292
3293 /*
3294   called when the forwarded RODC dns update request is finished
3295  */
3296 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
3297 {
3298         struct netr_dnsupdate_RODC_state *st =
3299                 tevent_req_callback_data(subreq,
3300                                          struct netr_dnsupdate_RODC_state);
3301         NTSTATUS status;
3302
3303         status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
3304         TALLOC_FREE(subreq);
3305         if (!NT_STATUS_IS_OK(status)) {
3306                 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
3307                 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3308         }
3309
3310         st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
3311
3312         status = dcesrv_reply(st->dce_call);
3313         if (!NT_STATUS_IS_OK(status)) {
3314                 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3315         }
3316 }
3317
3318 /*
3319   netr_DsrUpdateReadOnlyServerDnsRecords
3320 */
3321 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
3322                                                               TALLOC_CTX *mem_ctx,
3323                                                               struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
3324 {
3325         struct netlogon_creds_CredentialState *creds;
3326         NTSTATUS nt_status;
3327         struct dcerpc_binding_handle *binding_handle;
3328         struct netr_dnsupdate_RODC_state *st;
3329         struct tevent_req *subreq;
3330
3331         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3332                                                         mem_ctx,
3333                                                         r->in.computer_name,
3334                                                         r->in.credential,
3335                                                         r->out.return_authenticator,
3336                                                         &creds);
3337         NT_STATUS_NOT_OK_RETURN(nt_status);
3338
3339         if (creds->secure_channel_type != SEC_CHAN_RODC) {
3340                 return NT_STATUS_ACCESS_DENIED;
3341         }
3342
3343         st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
3344         NT_STATUS_HAVE_NO_MEMORY(st);
3345
3346         st->dce_call = dce_call;
3347         st->r = r;
3348         st->r2 = talloc_zero(st, struct dnsupdate_RODC);
3349         NT_STATUS_HAVE_NO_MEMORY(st->r2);
3350
3351         st->r2->in.dom_sid = creds->sid;
3352         st->r2->in.site_name = r->in.site_name;
3353         st->r2->in.dns_ttl = r->in.dns_ttl;
3354         st->r2->in.dns_names = r->in.dns_names;
3355         st->r2->out.dns_names = r->out.dns_names;
3356
3357         binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
3358                                                      "dnsupdate", &ndr_table_irpc);
3359         if (binding_handle == NULL) {
3360                 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
3361                 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3362                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3363         }
3364
3365         /* forward the call */
3366         subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
3367                                               binding_handle, st->r2);
3368         NT_STATUS_HAVE_NO_MEMORY(subreq);
3369
3370         dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3371
3372         /* setup the callback */
3373         tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
3374
3375         return NT_STATUS_OK;
3376 }
3377
3378
3379 /* include the generated boilerplate */
3380 #include "librpc/gen_ndr/ndr_netlogon_s.c"