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