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