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