s4:rpc_server/netlogon: netr_ServerAuthenticate3 should reject invalid sec_channel_ty...
[ddiss/samba.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
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_ACCESS_DENIED;
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_ACCESS_DENIED;
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_ACCESS_DENIED;
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_ACCESS_DENIED;
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_ACCESS_DENIED;
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_ACCESS_DENIED;
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_ACCESS_DENIED;
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_ACCESS_DENIED;
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[] = { "dNSHostName",
1300                 "msDS-SupportedEncryptionTypes", NULL };
1301         const char *temp_str, *temp_str2;
1302         const char *old_dns_hostname;
1303         struct ldb_context *sam_ctx;
1304         struct ldb_message **res1, **res2, **res3, *new_msg;
1305         struct ldb_dn *workstation_dn;
1306         struct netr_DomainInformation *domain_info;
1307         struct netr_LsaPolicyInformation *lsa_policy_info;
1308         struct netr_OsVersionInfoEx *os_version;
1309         uint32_t default_supported_enc_types = 0xFFFFFFFF;
1310         bool update_dns_hostname = true;
1311         int ret, ret3, i;
1312         NTSTATUS status;
1313
1314         status = dcesrv_netr_creds_server_step_check(dce_call,
1315                                                      mem_ctx,
1316                                                      r->in.computer_name,
1317                                                      r->in.credential,
1318                                                      r->out.return_authenticator,
1319                                                      &creds);
1320         if (!NT_STATUS_IS_OK(status)) {
1321                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1322         }
1323         NT_STATUS_NOT_OK_RETURN(status);
1324
1325         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1326                                 dce_call->conn->dce_ctx->lp_ctx,
1327                                 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1328         if (sam_ctx == NULL) {
1329                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1330         }
1331
1332         switch (r->in.level) {
1333         case 1: /* Domain information */
1334
1335                 if (r->in.query->workstation_info == NULL) {
1336                         return NT_STATUS_INVALID_PARAMETER;
1337                 }
1338
1339                 /*
1340                  * Checks that the computer name parameter without possible "$"
1341                  * matches as prefix with the DNS hostname in the workstation
1342                  * info structure.
1343                  */
1344                 temp_str = talloc_strndup(mem_ctx,
1345                                           r->in.computer_name,
1346                                           strcspn(r->in.computer_name, "$"));
1347                 NT_STATUS_HAVE_NO_MEMORY(temp_str);
1348                 temp_str2 = talloc_strndup(mem_ctx,
1349                                            r->in.query->workstation_info->dns_hostname,
1350                                            strcspn(r->in.query->workstation_info->dns_hostname, "."));
1351                 NT_STATUS_HAVE_NO_MEMORY(temp_str2);
1352                 if (strcasecmp(temp_str, temp_str2) != 0) {
1353                         update_dns_hostname = false;
1354                 }
1355
1356                 /* Prepare the workstation DN */
1357                 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1358                         dom_sid_string(mem_ctx, creds->sid));
1359                 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1360
1361                 /* Lookup for attributes in workstation object */
1362                 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
1363                         &res1, attrs2);
1364                 if (ret != 1) {
1365                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1366                 }
1367
1368                 /* Gets the old DNS hostname */
1369                 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0], "dNSHostName",
1370                         NULL);
1371
1372                 /*
1373                  * Updates the DNS hostname when the client wishes that the
1374                  * server should handle this for him
1375                  * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1376                  * obviously only checked when we do already have a
1377                  * "dNSHostName".
1378                  * See MS-NRPC section 3.5.4.3.9
1379                  */
1380                 if ((old_dns_hostname != NULL) &&
1381                     (r->in.query->workstation_info->workstation_flags
1382                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1383                         update_dns_hostname = false;
1384                 }
1385
1386                 /* Gets host informations and put them into our directory */
1387
1388                 new_msg = ldb_msg_new(mem_ctx);
1389                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1390
1391                 new_msg->dn = workstation_dn;
1392
1393                 /* Sets the OS name */
1394                 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1395                         "operatingSystem",
1396                         r->in.query->workstation_info->os_name.string);
1397
1398                 /*
1399                  * Sets informations from "os_version". On an empty structure
1400                  * the values are cleared.
1401                  */
1402                 if (r->in.query->workstation_info->os_version.os != NULL) {
1403                         os_version = &r->in.query->workstation_info->os_version.os->os;
1404
1405                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1406                                              "operatingSystemServicePack",
1407                                              os_version->CSDVersion);
1408
1409                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1410                                 "operatingSystemVersion",
1411                                 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1412                                         os_version->MajorVersion,
1413                                         os_version->MinorVersion,
1414                                         os_version->BuildNumber
1415                                 )
1416                         );
1417                 } else {
1418                         samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1419                                              "operatingSystemServicePack");
1420
1421                         samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1422                                              "operatingSystemVersion");
1423                 }
1424
1425                 /*
1426                  * If the boolean "update_dns_hostname" remained true, then we
1427                  * are fine to start the update.
1428                  */
1429                 if (update_dns_hostname) {
1430                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1431                                 "dNSHostname",
1432                         r->in.query->workstation_info->dns_hostname);
1433
1434                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1435                                 "servicePrincipalName",
1436                                 talloc_asprintf(mem_ctx, "HOST/%s",
1437                                 r->in.computer_name)
1438                         );
1439                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1440                                 "servicePrincipalName",
1441                                 talloc_asprintf(mem_ctx, "HOST/%s",
1442                                 r->in.query->workstation_info->dns_hostname)
1443                         );
1444                 }
1445
1446                 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1447                         DEBUG(3,("Impossible to update samdb: %s\n",
1448                                 ldb_errstring(sam_ctx)));
1449                 }
1450
1451                 talloc_free(new_msg);
1452
1453                 /* Writes back the domain information */
1454
1455                 /* We need to do two searches. The first will pull our primary
1456                    domain and the second will pull any trusted domains. Our
1457                    primary domain is also a "trusted" domain, so we need to
1458                    put the primary domain into the lists of returned trusts as
1459                    well. */
1460                 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1461                         &res2, attrs);
1462                 if (ret != 1) {
1463                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1464                 }
1465
1466                 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1467                         "(objectClass=trustedDomain)");
1468                 if (ret3 == -1) {
1469                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1470                 }
1471
1472                 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1473                 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1474
1475                 ZERO_STRUCTP(domain_info);
1476
1477                 /* Informations about the local and trusted domains */
1478
1479                 status = fill_one_domain_info(mem_ctx,
1480                         dce_call->conn->dce_ctx->lp_ctx,
1481                         sam_ctx, res2[0], &domain_info->primary_domain,
1482                         true, false);
1483                 NT_STATUS_NOT_OK_RETURN(status);
1484
1485                 domain_info->trusted_domain_count = ret3 + 1;
1486                 domain_info->trusted_domains = talloc_array(mem_ctx,
1487                         struct netr_OneDomainInfo,
1488                         domain_info->trusted_domain_count);
1489                 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1490
1491                 for (i=0;i<ret3;i++) {
1492                         status = fill_one_domain_info(mem_ctx,
1493                                 dce_call->conn->dce_ctx->lp_ctx,
1494                                 sam_ctx, res3[i],
1495                                 &domain_info->trusted_domains[i],
1496                                 false, true);
1497                         NT_STATUS_NOT_OK_RETURN(status);
1498                 }
1499
1500                 status = fill_one_domain_info(mem_ctx,
1501                         dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1502                         &domain_info->trusted_domains[i], true, true);
1503                 NT_STATUS_NOT_OK_RETURN(status);
1504
1505                 /* Sets the supported encryption types */
1506                 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1507                         "msDS-SupportedEncryptionTypes",
1508                         default_supported_enc_types);
1509
1510                 /* Other host domain informations */
1511
1512                 lsa_policy_info = talloc(mem_ctx,
1513                         struct netr_LsaPolicyInformation);
1514                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1515                 ZERO_STRUCTP(lsa_policy_info);
1516
1517                 domain_info->lsa_policy = *lsa_policy_info;
1518
1519                 /* The DNS hostname is only returned back when there is a chance
1520                  * for a change. */
1521                 if ((r->in.query->workstation_info->workstation_flags
1522                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1523                         domain_info->dns_hostname.string = old_dns_hostname;
1524                 } else {
1525                         domain_info->dns_hostname.string = NULL;
1526                 }
1527
1528                 domain_info->workstation_flags =
1529                         r->in.query->workstation_info->workstation_flags;
1530
1531                 r->out.info->domain_info = domain_info;
1532         break;
1533         case 2: /* LSA policy information - not used at the moment */
1534                 lsa_policy_info = talloc(mem_ctx,
1535                         struct netr_LsaPolicyInformation);
1536                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1537                 ZERO_STRUCTP(lsa_policy_info);
1538
1539                 r->out.info->lsa_policy_info = lsa_policy_info;
1540         break;
1541         default:
1542                 return NT_STATUS_INVALID_LEVEL;
1543         break;
1544         }
1545
1546         return NT_STATUS_OK;
1547 }
1548
1549
1550
1551 /*
1552   netr_ServerPasswordGet
1553 */
1554 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1555                        struct netr_ServerPasswordGet *r)
1556 {
1557         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1558 }
1559
1560
1561 /*
1562   netr_NETRLOGONSENDTOSAM
1563 */
1564 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1565                        struct netr_NETRLOGONSENDTOSAM *r)
1566 {
1567         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1568 }
1569
1570
1571 /*
1572   netr_DsRGetDCNameEx2
1573 */
1574 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1575                                           TALLOC_CTX *mem_ctx,
1576                                           struct netr_DsRGetDCNameEx2 *r)
1577 {
1578         struct ldb_context *sam_ctx;
1579         struct netr_DsRGetDCNameInfo *info;
1580         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1581         const struct tsocket_address *remote_address;
1582         char *addr = NULL;
1583         const char *server_site_name;
1584         char *guid_str;
1585         struct netlogon_samlogon_response response;
1586         NTSTATUS status;
1587         const char *dc_name = NULL;
1588         const char *domain_name = NULL;
1589
1590         ZERO_STRUCTP(r->out.info);
1591
1592         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1593                                 dce_call->conn->auth_state.session_info, 0);
1594         if (sam_ctx == NULL) {
1595                 return WERR_DS_UNAVAILABLE;
1596         }
1597
1598         remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1599         if (tsocket_address_is_inet(remote_address, "ip")) {
1600                 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1601                 W_ERROR_HAVE_NO_MEMORY(addr);
1602         }
1603
1604         /* "server_unc" is ignored by w2k3 */
1605
1606         if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1607                 return WERR_INVALID_FLAGS;
1608         }
1609
1610         if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1611             r->in.flags & DS_PDC_REQUIRED &&
1612             r->in.flags & DS_KDC_REQUIRED) {
1613                 return WERR_INVALID_FLAGS;
1614         }
1615         if (r->in.flags & DS_IS_FLAT_NAME &&
1616             r->in.flags & DS_IS_DNS_NAME) {
1617                 return WERR_INVALID_FLAGS;
1618         }
1619         if (r->in.flags & DS_RETURN_DNS_NAME &&
1620             r->in.flags & DS_RETURN_FLAT_NAME) {
1621                 return WERR_INVALID_FLAGS;
1622         }
1623         if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1624             r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1625                 return WERR_INVALID_FLAGS;
1626         }
1627
1628         if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1629             r->in.flags &
1630             (DS_DIRECTORY_SERVICE_REQUIRED |
1631              DS_DIRECTORY_SERVICE_PREFERRED |
1632              DS_GC_SERVER_REQUIRED |
1633              DS_PDC_REQUIRED |
1634              DS_KDC_REQUIRED)) {
1635                 return WERR_INVALID_FLAGS;
1636         }
1637
1638         if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1639             r->in.site_name) {
1640                 return WERR_INVALID_FLAGS;
1641         }
1642
1643         /* Proof server site parameter "site_name" if it was specified */
1644         server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1645         W_ERROR_HAVE_NO_MEMORY(server_site_name);
1646         if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1647                                                      server_site_name) != 0)) {
1648                 return WERR_NO_SUCH_DOMAIN;
1649         }
1650
1651         guid_str = r->in.domain_guid != NULL ?
1652                  GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1653
1654         status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1655                                                  r->in.domain_name,
1656                                                  r->in.domain_name,
1657                                                  NULL, guid_str,
1658                                                  r->in.client_account,
1659                                                  r->in.mask, addr,
1660                                                  NETLOGON_NT_VERSION_5EX_WITH_IP,
1661                                                  lp_ctx, &response, true);
1662         if (!NT_STATUS_IS_OK(status)) {
1663                 return ntstatus_to_werror(status);
1664         }
1665
1666         if (r->in.flags & DS_RETURN_DNS_NAME) {
1667                 dc_name = response.data.nt5_ex.pdc_dns_name;
1668                 domain_name = response.data.nt5_ex.dns_domain;
1669         } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1670                 dc_name = response.data.nt5_ex.pdc_name;
1671                 domain_name = response.data.nt5_ex.domain_name;
1672         } else {
1673
1674                 /*
1675                  * TODO: autodetect what we need to return
1676                  * based on the given arguments
1677                  */
1678                 dc_name = response.data.nt5_ex.pdc_name;
1679                 domain_name = response.data.nt5_ex.domain_name;
1680         }
1681
1682         if (!dc_name || !dc_name[0]) {
1683                 return WERR_NO_SUCH_DOMAIN;
1684         }
1685
1686         if (!domain_name || !domain_name[0]) {
1687                 return WERR_NO_SUCH_DOMAIN;
1688         }
1689
1690         info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1691         W_ERROR_HAVE_NO_MEMORY(info);
1692         info->dc_unc           = talloc_asprintf(mem_ctx, "\\\\%s", dc_name);
1693         W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1694         info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1695                                            response.data.nt5_ex.sockaddr.pdc_ip);
1696         W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1697         info->dc_address_type  = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1698         info->domain_guid      = response.data.nt5_ex.domain_uuid;
1699         info->domain_name      = domain_name;
1700         info->forest_name      = response.data.nt5_ex.forest;
1701         info->dc_flags         = response.data.nt5_ex.server_type;
1702         info->dc_site_name     = response.data.nt5_ex.server_site;
1703         info->client_site_name = response.data.nt5_ex.client_site;
1704
1705         *r->out.info = info;
1706
1707         return WERR_OK;
1708 }
1709
1710 /*
1711   netr_DsRGetDCNameEx
1712 */
1713 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1714                                   struct netr_DsRGetDCNameEx *r)
1715 {
1716         struct netr_DsRGetDCNameEx2 r2;
1717         WERROR werr;
1718
1719         ZERO_STRUCT(r2);
1720
1721         r2.in.server_unc = r->in.server_unc;
1722         r2.in.client_account = NULL;
1723         r2.in.mask = 0;
1724         r2.in.domain_guid = r->in.domain_guid;
1725         r2.in.domain_name = r->in.domain_name;
1726         r2.in.site_name = r->in.site_name;
1727         r2.in.flags = r->in.flags;
1728         r2.out.info = r->out.info;
1729
1730         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1731
1732         return werr;
1733 }
1734
1735 /*
1736   netr_DsRGetDCName
1737 */
1738 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1739                                 struct netr_DsRGetDCName *r)
1740 {
1741         struct netr_DsRGetDCNameEx2 r2;
1742         WERROR werr;
1743
1744         ZERO_STRUCT(r2);
1745
1746         r2.in.server_unc = r->in.server_unc;
1747         r2.in.client_account = NULL;
1748         r2.in.mask = 0;
1749         r2.in.domain_name = r->in.domain_name;
1750         r2.in.domain_guid = r->in.domain_guid;
1751
1752         r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1753         r2.in.flags = r->in.flags;
1754         r2.out.info = r->out.info;
1755
1756         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1757
1758         return werr;
1759 }
1760 /*
1761   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1762 */
1763 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1764                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1765 {
1766         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1767 }
1768
1769
1770 /*
1771   netr_NetrEnumerateTrustedDomainsEx
1772 */
1773 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1774                        struct netr_NetrEnumerateTrustedDomainsEx *r)
1775 {
1776         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1777 }
1778
1779
1780 /*
1781   netr_DsRAddressToSitenamesExW
1782 */
1783 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1784                                                    struct netr_DsRAddressToSitenamesExW *r)
1785 {
1786         struct ldb_context *sam_ctx;
1787         struct netr_DsRAddressToSitenamesExWCtr *ctr;
1788         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1789         sa_family_t sin_family;
1790         struct sockaddr_in *addr;
1791 #ifdef HAVE_IPV6
1792         struct sockaddr_in6 *addr6;
1793         char addr_str[INET6_ADDRSTRLEN];
1794 #else
1795         char addr_str[INET_ADDRSTRLEN];
1796 #endif
1797         char *subnet_name;
1798         const char *res;
1799         uint32_t i;
1800
1801         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1802                                 dce_call->conn->auth_state.session_info, 0);
1803         if (sam_ctx == NULL) {
1804                 return WERR_DS_UNAVAILABLE;
1805         }
1806
1807         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1808         W_ERROR_HAVE_NO_MEMORY(ctr);
1809
1810         *r->out.ctr = ctr;
1811
1812         ctr->count = r->in.count;
1813         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1814         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1815         ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1816         W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1817
1818         for (i=0; i<ctr->count; i++) {
1819                 ctr->sitename[i].string = NULL;
1820                 ctr->subnetname[i].string = NULL;
1821
1822                 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1823                         continue;
1824                 }
1825                 /* The first two byte of the buffer are reserved for the
1826                  * "sin_family" but for now only the first one is used. */
1827                 sin_family = r->in.addresses[i].buffer[0];
1828
1829                 switch (sin_family) {
1830                 case AF_INET:
1831                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1832                                 continue;
1833                         }
1834                         addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1835                         res = inet_ntop(AF_INET, &addr->sin_addr,
1836                                         addr_str, sizeof(addr_str));
1837                         break;
1838 #ifdef HAVE_IPV6
1839                 case AF_INET6:
1840                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1841                                 continue;
1842                         }
1843                         addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1844                         res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1845                                         addr_str, sizeof(addr_str));
1846                         break;
1847 #endif
1848                 default:
1849                         continue;
1850                 }
1851
1852                 if (res == NULL) {
1853                         continue;
1854                 }
1855
1856                 ctr->sitename[i].string   = samdb_client_site_name(sam_ctx,
1857                                                                    mem_ctx,
1858                                                                    addr_str,
1859                                                                    &subnet_name);
1860                 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1861                 ctr->subnetname[i].string = subnet_name;
1862         }
1863
1864         return WERR_OK;
1865 }
1866
1867
1868 /*
1869   netr_DsRAddressToSitenamesW
1870 */
1871 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1872                        struct netr_DsRAddressToSitenamesW *r)
1873 {
1874         struct netr_DsRAddressToSitenamesExW r2;
1875         struct netr_DsRAddressToSitenamesWCtr *ctr;
1876         uint32_t i;
1877         WERROR werr;
1878
1879         ZERO_STRUCT(r2);
1880
1881         r2.in.server_name = r->in.server_name;
1882         r2.in.count = r->in.count;
1883         r2.in.addresses = r->in.addresses;
1884
1885         r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
1886         W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
1887
1888         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
1889         W_ERROR_HAVE_NO_MEMORY(ctr);
1890
1891         *r->out.ctr = ctr;
1892
1893         ctr->count = r->in.count;
1894         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1895         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1896
1897         werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
1898
1899         for (i=0; i<ctr->count; i++) {
1900                 ctr->sitename[i].string   = (*r2.out.ctr)->sitename[i].string;
1901         }
1902
1903         return werr;
1904 }
1905
1906
1907 /*
1908   netr_DsrGetDcSiteCoverageW
1909 */
1910 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1911                        struct netr_DsrGetDcSiteCoverageW *r)
1912 {
1913         struct ldb_context *sam_ctx;
1914         struct DcSitesCtr *ctr;
1915         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1916
1917         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1918                                 dce_call->conn->auth_state.session_info, 0);
1919         if (sam_ctx == NULL) {
1920                 return WERR_DS_UNAVAILABLE;
1921         }
1922
1923         ctr = talloc(mem_ctx, struct DcSitesCtr);
1924         W_ERROR_HAVE_NO_MEMORY(ctr);
1925
1926         *r->out.ctr = ctr;
1927
1928         /* For now only return our default site */
1929         ctr->num_sites = 1;
1930         ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
1931         W_ERROR_HAVE_NO_MEMORY(ctr->sites);
1932         ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
1933         W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
1934
1935         return WERR_OK;
1936 }
1937
1938
1939 #define GET_CHECK_STR(dest, mem, msg, attr) \
1940 do {\
1941         const char *s; \
1942         s = ldb_msg_find_attr_as_string(msg, attr, NULL); \
1943         if (!s) { \
1944                 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1945                           "without flatname\n", \
1946                           ldb_dn_get_linearized(msg->dn))); \
1947                 continue; \
1948         } \
1949         dest = talloc_strdup(mem, s); \
1950         W_ERROR_HAVE_NO_MEMORY(dest); \
1951 } while(0)
1952
1953
1954 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1955                                          struct ldb_context *sam_ctx,
1956                                          struct netr_DomainTrustList *trusts,
1957                                          uint32_t trust_flags)
1958 {
1959         struct ldb_dn *system_dn;
1960         struct ldb_message **dom_res = NULL;
1961         const char *trust_attrs[] = { "flatname", "trustPartner",
1962                                       "securityIdentifier", "trustDirection",
1963                                       "trustType", "trustAttributes", NULL };
1964         uint32_t n;
1965         int i;
1966         int ret;
1967
1968         if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1969                              NETR_TRUST_FLAG_OUTBOUND))) {
1970                 return WERR_INVALID_FLAGS;
1971         }
1972
1973         system_dn = samdb_search_dn(sam_ctx, mem_ctx,
1974                                     ldb_get_default_basedn(sam_ctx),
1975                                     "(&(objectClass=container)(cn=System))");
1976         if (!system_dn) {
1977                 return WERR_GENERAL_FAILURE;
1978         }
1979
1980         ret = gendb_search(sam_ctx, mem_ctx, system_dn,
1981                            &dom_res, trust_attrs,
1982                            "(objectclass=trustedDomain)");
1983
1984         for (i = 0; i < ret; i++) {
1985                 unsigned int trust_dir;
1986                 uint32_t flags = 0;
1987
1988                 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
1989                                                       "trustDirection", 0);
1990
1991                 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
1992                         flags |= NETR_TRUST_FLAG_INBOUND;
1993                 }
1994                 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
1995                         flags |= NETR_TRUST_FLAG_OUTBOUND;
1996                 }
1997
1998                 if (!(flags & trust_flags)) {
1999                         /* this trust direction was not requested */
2000                         continue;
2001                 }
2002
2003                 n = trusts->count;
2004                 trusts->array = talloc_realloc(trusts, trusts->array,
2005                                                struct netr_DomainTrust,
2006                                                n + 1);
2007                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2008
2009                 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
2010                               dom_res[i], "flatname");
2011                 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
2012                               dom_res[i], "trustPartner");
2013
2014                 trusts->array[n].trust_flags = flags;
2015                 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2016                     !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2017                         /* TODO: find if we have parent in the list */
2018                         trusts->array[n].parent_index = 0;
2019                 }
2020
2021                 trusts->array[n].trust_type =
2022                                 ldb_msg_find_attr_as_uint(dom_res[i],
2023                                                   "trustType", 0);
2024                 trusts->array[n].trust_attributes =
2025                                 ldb_msg_find_attr_as_uint(dom_res[i],
2026                                                   "trustAttributes", 0);
2027
2028                 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2029                     (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2030                         struct dom_sid zero_sid;
2031                         ZERO_STRUCT(zero_sid);
2032                         trusts->array[n].sid =
2033                                 dom_sid_dup(trusts, &zero_sid);
2034                 } else {
2035                         trusts->array[n].sid =
2036                                 samdb_result_dom_sid(trusts, dom_res[i],
2037                                                      "securityIdentifier");
2038                 }
2039                 trusts->array[n].guid = GUID_zero();
2040
2041                 trusts->count = n + 1;
2042         }
2043
2044         talloc_free(dom_res);
2045         return WERR_OK;
2046 }
2047
2048 /*
2049   netr_DsrEnumerateDomainTrusts
2050 */
2051 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2052                                                    TALLOC_CTX *mem_ctx,
2053                                                    struct netr_DsrEnumerateDomainTrusts *r)
2054 {
2055         struct netr_DomainTrustList *trusts;
2056         struct ldb_context *sam_ctx;
2057         int ret;
2058         struct ldb_message **dom_res;
2059         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2060         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2061         const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2062         const char *p;
2063         WERROR werr;
2064
2065         if (r->in.trust_flags & 0xFFFFFE00) {
2066                 return WERR_INVALID_FLAGS;
2067         }
2068
2069         /* TODO: turn to hard check once we are sure this is 100% correct */
2070         if (!r->in.server_name) {
2071                 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2072                           "But received NULL!\n", dnsdomain));
2073         } else {
2074                 p = strchr(r->in.server_name, '.');
2075                 if (!p) {
2076                         DEBUG(3, ("Invalid domain! Expected name in domain "
2077                                   "[%s]. But received [%s]!\n",
2078                                   dnsdomain, r->in.server_name));
2079                         p = r->in.server_name;
2080                 } else {
2081                         p++;
2082                 }
2083                 if (strcasecmp(p, dnsdomain)) {
2084                         DEBUG(3, ("Invalid domain! Expected name in domain "
2085                                   "[%s]. But received [%s]!\n",
2086                                   dnsdomain, r->in.server_name));
2087                 }
2088         }
2089
2090         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2091         W_ERROR_HAVE_NO_MEMORY(trusts);
2092
2093         trusts->count = 0;
2094         r->out.trusts = trusts;
2095
2096         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2097                                 dce_call->conn->auth_state.session_info, 0);
2098         if (sam_ctx == NULL) {
2099                 return WERR_GENERAL_FAILURE;
2100         }
2101
2102         if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2103             (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2104
2105                 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2106                                                   trusts, r->in.trust_flags);
2107                 W_ERROR_NOT_OK_RETURN(werr);
2108         }
2109
2110         /* NOTE: we currently are always the root of the forest */
2111         if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2112                 uint32_t n = trusts->count;
2113
2114                 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2115                                       &dom_res, dom_attrs);
2116                 if (ret != 1) {
2117                         return WERR_GENERAL_FAILURE;
2118                 }
2119
2120                 trusts->count = n + 1;
2121                 trusts->array = talloc_realloc(trusts, trusts->array,
2122                                                struct netr_DomainTrust,
2123                                                trusts->count);
2124                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2125
2126                 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2127                 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2128                 trusts->array[n].trust_flags =
2129                         NETR_TRUST_FLAG_NATIVE |
2130                         NETR_TRUST_FLAG_TREEROOT |
2131                         NETR_TRUST_FLAG_IN_FOREST |
2132                         NETR_TRUST_FLAG_PRIMARY;
2133                 /* we are always the root domain for now */
2134                 trusts->array[n].parent_index = 0;
2135                 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2136                 trusts->array[n].trust_attributes = 0;
2137                 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2138                                                             dom_res[0],
2139                                                             "objectSid");
2140                 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2141                                                           "objectGUID");
2142                 talloc_free(dom_res);
2143         }
2144
2145         return WERR_OK;
2146 }
2147
2148
2149 /*
2150   netr_DsrDeregisterDNSHostRecords
2151 */
2152 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2153                        struct netr_DsrDeregisterDNSHostRecords *r)
2154 {
2155         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2156 }
2157
2158
2159 /*
2160   netr_ServerTrustPasswordsGet
2161 */
2162 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2163                        struct netr_ServerTrustPasswordsGet *r)
2164 {
2165         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2166 }
2167
2168
2169 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2170                                       struct ldb_context *sam_ctx,
2171                                       struct loadparm_context *lp_ctx,
2172                                       struct lsa_ForestTrustInformation *info)
2173 {
2174         struct lsa_ForestTrustDomainInfo *domain_info;
2175         struct lsa_ForestTrustRecord *e;
2176         struct ldb_message **dom_res;
2177         const char * const dom_attrs[] = { "objectSid", NULL };
2178         int ret;
2179
2180         /* we need to provide 2 entries:
2181          * 1. the Root Forest name
2182          * 2. the Domain Information
2183          */
2184
2185         info->count = 2;
2186         info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2187         W_ERROR_HAVE_NO_MEMORY(info->entries);
2188
2189         /* Forest root info */
2190         e = talloc(info, struct lsa_ForestTrustRecord);
2191         W_ERROR_HAVE_NO_MEMORY(e);
2192
2193         e->flags = 0;
2194         e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2195         e->time = 0; /* so far always 0 in trces. */
2196         e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2197                                                                        mem_ctx);
2198         W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2199
2200         info->entries[0] = e;
2201
2202         /* Domain info */
2203         e = talloc(info, struct lsa_ForestTrustRecord);
2204         W_ERROR_HAVE_NO_MEMORY(e);
2205
2206         /* get our own domain info */
2207         ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2208         if (ret != 1) {
2209                 return WERR_GENERAL_FAILURE;
2210         }
2211
2212         /* TODO: check if disabled and set flags accordingly */
2213         e->flags = 0;
2214         e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2215         e->time = 0; /* so far always 0 in traces. */
2216
2217         domain_info = &e->forest_trust_data.domain_info;
2218         domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2219                                                        "objectSid");
2220         domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2221         domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2222
2223         info->entries[1] = e;
2224
2225         talloc_free(dom_res);
2226
2227         return WERR_OK;
2228 }
2229
2230 /*
2231   netr_DsRGetForestTrustInformation
2232 */
2233 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2234                                                        TALLOC_CTX *mem_ctx,
2235                                                        struct netr_DsRGetForestTrustInformation *r)
2236 {
2237         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2238         struct lsa_ForestTrustInformation *info, **info_ptr;
2239         struct ldb_context *sam_ctx;
2240         WERROR werr;
2241
2242         if (r->in.flags & 0xFFFFFFFE) {
2243                 return WERR_INVALID_FLAGS;
2244         }
2245
2246         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2247                                 dce_call->conn->auth_state.session_info, 0);
2248         if (sam_ctx == NULL) {
2249                 return WERR_GENERAL_FAILURE;
2250         }
2251
2252         if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2253                 if (!samdb_is_pdc(sam_ctx)) {
2254                         return WERR_NERR_NOTPRIMARY;
2255                 }
2256
2257                 if (r->in.trusted_domain_name == NULL) {
2258                         return WERR_INVALID_FLAGS;
2259                 }
2260
2261                 /* TODO: establish an schannel connection with
2262                  * r->in.trusted_domain_name and perform a
2263                  * netr_GetForestTrustInformation call against it */
2264
2265                 /* for now return not implementd */
2266                 return WERR_CALL_NOT_IMPLEMENTED;
2267         }
2268
2269         /* TODO: check r->in.server_name is our name */
2270
2271         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2272         W_ERROR_HAVE_NO_MEMORY(info_ptr);
2273
2274         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2275         W_ERROR_HAVE_NO_MEMORY(info);
2276
2277         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2278         W_ERROR_NOT_OK_RETURN(werr);
2279
2280         *info_ptr = info;
2281         r->out.forest_trust_info = info_ptr;
2282
2283         return WERR_OK;
2284 }
2285
2286
2287 /*
2288   netr_GetForestTrustInformation
2289 */
2290 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2291                                                       TALLOC_CTX *mem_ctx,
2292                                                       struct netr_GetForestTrustInformation *r)
2293 {
2294         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2295         struct netlogon_creds_CredentialState *creds;
2296         struct lsa_ForestTrustInformation *info, **info_ptr;
2297         struct ldb_context *sam_ctx;
2298         NTSTATUS status;
2299         WERROR werr;
2300
2301         status = dcesrv_netr_creds_server_step_check(dce_call,
2302                                                      mem_ctx,
2303                                                      r->in.computer_name,
2304                                                      r->in.credential,
2305                                                      r->out.return_authenticator,
2306                                                      &creds);
2307         if (!NT_STATUS_IS_OK(status)) {
2308                 return status;
2309         }
2310
2311         if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2312             (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2313                 return NT_STATUS_NOT_IMPLEMENTED;
2314         }
2315
2316         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2317                                 dce_call->conn->auth_state.session_info, 0);
2318         if (sam_ctx == NULL) {
2319                 return NT_STATUS_UNSUCCESSFUL;
2320         }
2321
2322         /* TODO: check r->in.server_name is our name */
2323
2324         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2325         if (!info_ptr) {
2326                 return NT_STATUS_NO_MEMORY;
2327         }
2328         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2329         if (!info) {
2330                 return NT_STATUS_NO_MEMORY;
2331         }
2332
2333         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2334         if (!W_ERROR_IS_OK(werr)) {
2335                 return werror_to_ntstatus(werr);
2336         }
2337
2338         *info_ptr = info;
2339         r->out.forest_trust_info = info_ptr;
2340
2341         return NT_STATUS_OK;
2342 }
2343
2344
2345 /*
2346   netr_ServerGetTrustInfo
2347 */
2348 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2349                        struct netr_ServerGetTrustInfo *r)
2350 {
2351         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2352 }
2353
2354 /*
2355   netr_Unused47
2356 */
2357 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2358                                      struct netr_Unused47 *r)
2359 {
2360         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2361 }
2362
2363
2364 struct netr_dnsupdate_RODC_state {
2365         struct dcesrv_call_state *dce_call;
2366         struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2367         struct dnsupdate_RODC *r2;
2368 };
2369
2370 /*
2371   called when the forwarded RODC dns update request is finished
2372  */
2373 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2374 {
2375         struct netr_dnsupdate_RODC_state *st =
2376                 tevent_req_callback_data(subreq,
2377                                          struct netr_dnsupdate_RODC_state);
2378         NTSTATUS status;
2379
2380         status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2381         TALLOC_FREE(subreq);
2382         if (!NT_STATUS_IS_OK(status)) {
2383                 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2384                 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2385         }
2386
2387         st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2388
2389         status = dcesrv_reply(st->dce_call);
2390         if (!NT_STATUS_IS_OK(status)) {
2391                 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2392         }
2393 }
2394
2395 /*
2396   netr_DsrUpdateReadOnlyServerDnsRecords
2397 */
2398 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2399                                                               TALLOC_CTX *mem_ctx,
2400                                                               struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2401 {
2402         struct netlogon_creds_CredentialState *creds;
2403         NTSTATUS nt_status;
2404         struct dcerpc_binding_handle *binding_handle;
2405         struct netr_dnsupdate_RODC_state *st;
2406         struct tevent_req *subreq;
2407
2408         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2409                                                         mem_ctx,
2410                                                         r->in.computer_name,
2411                                                         r->in.credential,
2412                                                         r->out.return_authenticator,
2413                                                         &creds);
2414         NT_STATUS_NOT_OK_RETURN(nt_status);
2415
2416         if (creds->secure_channel_type != SEC_CHAN_RODC) {
2417                 return NT_STATUS_ACCESS_DENIED;
2418         }
2419
2420         st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2421         NT_STATUS_HAVE_NO_MEMORY(st);
2422
2423         st->dce_call = dce_call;
2424         st->r = r;
2425         st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2426         NT_STATUS_HAVE_NO_MEMORY(st->r2);
2427
2428         st->r2->in.dom_sid = creds->sid;
2429         st->r2->in.site_name = r->in.site_name;
2430         st->r2->in.dns_ttl = r->in.dns_ttl;
2431         st->r2->in.dns_names = r->in.dns_names;
2432         st->r2->out.dns_names = r->out.dns_names;
2433
2434         binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2435                                                      "dnsupdate", &ndr_table_irpc);
2436         if (binding_handle == NULL) {
2437                 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2438                 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2439                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2440         }
2441
2442         /* forward the call */
2443         subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2444                                               binding_handle, st->r2);
2445         NT_STATUS_HAVE_NO_MEMORY(subreq);
2446
2447         dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2448
2449         /* setup the callback */
2450         tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2451
2452         return NT_STATUS_OK;
2453 }
2454
2455
2456 /* include the generated boilerplate */
2457 #include "librpc/gen_ndr/ndr_netlogon_s.c"