s4:rpc_server/netlogon: netr_GetDcName should return WERR_DCNOTFOUND for invalid...
[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         if (!pipe_state) {
129                 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
130                 return NT_STATUS_ACCESS_DENIED;
131         }
132
133         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
134                                 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
135         if (sam_ctx == NULL) {
136                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
137         }
138
139         if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
140                 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
141                 const char *flatname;
142                 if (!encoded_account) {
143                         return NT_STATUS_NO_MEMORY;
144                 }
145
146                 /* Kill the trailing dot */
147                 if (encoded_account[strlen(encoded_account)-1] == '.') {
148                         encoded_account[strlen(encoded_account)-1] = '\0';
149                 }
150
151                 /* pull the user attributes */
152                 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
153                                            trust_dom_attrs,
154                                            "(&(trustPartner=%s)(objectclass=trustedDomain))",
155                                            encoded_account);
156
157                 if (num_records == 0) {
158                         DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
159                                  encoded_account));
160                         return NT_STATUS_ACCESS_DENIED;
161                 }
162
163                 if (num_records > 1) {
164                         DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
165                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
166                 }
167
168                 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
169                 if (!flatname) {
170                         /* No flatname for this trust - we can't proceed */
171                         return NT_STATUS_ACCESS_DENIED;
172                 }
173                 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
174
175                 if (!account_name) {
176                         return NT_STATUS_NO_MEMORY;
177                 }
178
179         } else {
180                 account_name = r->in.account_name;
181         }
182
183         /* pull the user attributes */
184         num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
185                                    "(&(sAMAccountName=%s)(objectclass=user))",
186                                    ldb_binary_encode_string(mem_ctx, account_name));
187
188         if (num_records == 0) {
189                 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
190                          r->in.account_name));
191                 return NT_STATUS_ACCESS_DENIED;
192         }
193
194         if (num_records > 1) {
195                 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
196                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
197         }
198
199         user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
200
201         if (user_account_control & UF_ACCOUNTDISABLE) {
202                 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
203                 return NT_STATUS_ACCESS_DENIED;
204         }
205
206         if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
207                 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
208                         DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
209                         return NT_STATUS_ACCESS_DENIED;
210                 }
211         } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
212                    r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
213                 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
214                         DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
215
216                         return NT_STATUS_ACCESS_DENIED;
217                 }
218         } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
219                 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
220                         DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
221                         return NT_STATUS_ACCESS_DENIED;
222                 }
223         } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
224                 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
225                         DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
226                         return NT_STATUS_ACCESS_DENIED;
227                 }
228         } else {
229                 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
230                           r->in.secure_channel_type));
231                 return NT_STATUS_ACCESS_DENIED;
232         }
233
234         *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
235                                                 "objectSid", 0);
236
237         mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
238         if (mach_pwd == NULL) {
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
1576         ZERO_STRUCTP(r->out.info);
1577
1578         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1579                                 dce_call->conn->auth_state.session_info, 0);
1580         if (sam_ctx == NULL) {
1581                 return WERR_DS_UNAVAILABLE;
1582         }
1583
1584         remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1585         if (tsocket_address_is_inet(remote_address, "ip")) {
1586                 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1587                 W_ERROR_HAVE_NO_MEMORY(addr);
1588         }
1589
1590         /* "server_unc" is ignored by w2k3 */
1591
1592         /* Proof server site parameter "site_name" if it was specified */
1593         server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1594         W_ERROR_HAVE_NO_MEMORY(server_site_name);
1595         if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1596                                                      server_site_name) != 0)) {
1597                 return WERR_NO_SUCH_DOMAIN;
1598         }
1599
1600         /* TODO: the flags are ignored for now */
1601
1602         guid_str = r->in.domain_guid != NULL ?
1603                  GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1604
1605         status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1606                                                  r->in.domain_name,
1607                                                  r->in.domain_name,
1608                                                  NULL, guid_str,
1609                                                  r->in.client_account,
1610                                                  r->in.mask, addr,
1611                                                  NETLOGON_NT_VERSION_5EX_WITH_IP,
1612                                                  lp_ctx, &response, true);
1613         if (!NT_STATUS_IS_OK(status)) {
1614                 return ntstatus_to_werror(status);
1615         }
1616
1617         info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1618         W_ERROR_HAVE_NO_MEMORY(info);
1619         info->dc_unc           = talloc_asprintf(mem_ctx, "\\\\%s",
1620                                                  response.data.nt5_ex.pdc_dns_name);
1621         W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1622         info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1623                                            response.data.nt5_ex.sockaddr.pdc_ip);
1624         W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1625         info->dc_address_type  = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1626         info->domain_guid      = response.data.nt5_ex.domain_uuid;
1627         info->domain_name      = response.data.nt5_ex.dns_domain;
1628         info->forest_name      = response.data.nt5_ex.forest;
1629         info->dc_flags         = response.data.nt5_ex.server_type;
1630         info->dc_site_name     = response.data.nt5_ex.server_site;
1631         info->client_site_name = response.data.nt5_ex.client_site;
1632
1633         *r->out.info = info;
1634
1635         return WERR_OK;
1636 }
1637
1638 /*
1639   netr_DsRGetDCNameEx
1640 */
1641 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1642                                   struct netr_DsRGetDCNameEx *r)
1643 {
1644         struct netr_DsRGetDCNameEx2 r2;
1645         WERROR werr;
1646
1647         ZERO_STRUCT(r2);
1648
1649         r2.in.server_unc = r->in.server_unc;
1650         r2.in.client_account = NULL;
1651         r2.in.mask = 0;
1652         r2.in.domain_guid = r->in.domain_guid;
1653         r2.in.domain_name = r->in.domain_name;
1654         r2.in.site_name = r->in.site_name;
1655         r2.in.flags = r->in.flags;
1656         r2.out.info = r->out.info;
1657
1658         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1659
1660         return werr;
1661 }
1662
1663 /*
1664   netr_DsRGetDCName
1665 */
1666 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1667                                 struct netr_DsRGetDCName *r)
1668 {
1669         struct netr_DsRGetDCNameEx2 r2;
1670         WERROR werr;
1671
1672         ZERO_STRUCT(r2);
1673
1674         r2.in.server_unc = r->in.server_unc;
1675         r2.in.client_account = NULL;
1676         r2.in.mask = 0;
1677         r2.in.domain_name = r->in.domain_name;
1678         r2.in.domain_guid = r->in.domain_guid;
1679
1680         r2.in.site_name = NULL; /* should fill in from site GUID */
1681         r2.in.flags = r->in.flags;
1682         r2.out.info = r->out.info;
1683
1684         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1685
1686         return werr;
1687 }
1688 /*
1689   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1690 */
1691 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1692                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1693 {
1694         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1695 }
1696
1697
1698 /*
1699   netr_NetrEnumerateTrustedDomainsEx
1700 */
1701 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1702                        struct netr_NetrEnumerateTrustedDomainsEx *r)
1703 {
1704         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1705 }
1706
1707
1708 /*
1709   netr_DsRAddressToSitenamesExW
1710 */
1711 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1712                                                    struct netr_DsRAddressToSitenamesExW *r)
1713 {
1714         struct ldb_context *sam_ctx;
1715         struct netr_DsRAddressToSitenamesExWCtr *ctr;
1716         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1717         sa_family_t sin_family;
1718         struct sockaddr_in *addr;
1719 #ifdef HAVE_IPV6
1720         struct sockaddr_in6 *addr6;
1721         char addr_str[INET6_ADDRSTRLEN];
1722 #else
1723         char addr_str[INET_ADDRSTRLEN];
1724 #endif
1725         char *subnet_name;
1726         const char *res;
1727         uint32_t i;
1728
1729         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1730                                 dce_call->conn->auth_state.session_info, 0);
1731         if (sam_ctx == NULL) {
1732                 return WERR_DS_UNAVAILABLE;
1733         }
1734
1735         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1736         W_ERROR_HAVE_NO_MEMORY(ctr);
1737
1738         *r->out.ctr = ctr;
1739
1740         ctr->count = r->in.count;
1741         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1742         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1743         ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1744         W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1745
1746         for (i=0; i<ctr->count; i++) {
1747                 ctr->sitename[i].string = NULL;
1748                 ctr->subnetname[i].string = NULL;
1749
1750                 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1751                         continue;
1752                 }
1753                 /* The first two byte of the buffer are reserved for the
1754                  * "sin_family" but for now only the first one is used. */
1755                 sin_family = r->in.addresses[i].buffer[0];
1756
1757                 switch (sin_family) {
1758                 case AF_INET:
1759                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1760                                 continue;
1761                         }
1762                         addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1763                         res = inet_ntop(AF_INET, &addr->sin_addr,
1764                                         addr_str, sizeof(addr_str));
1765                         break;
1766 #ifdef HAVE_IPV6
1767                 case AF_INET6:
1768                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1769                                 continue;
1770                         }
1771                         addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1772                         res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1773                                         addr_str, sizeof(addr_str));
1774                         break;
1775 #endif
1776                 default:
1777                         continue;
1778                 }
1779
1780                 if (res == NULL) {
1781                         continue;
1782                 }
1783
1784                 ctr->sitename[i].string   = samdb_client_site_name(sam_ctx,
1785                                                                    mem_ctx,
1786                                                                    addr_str,
1787                                                                    &subnet_name);
1788                 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1789                 ctr->subnetname[i].string = subnet_name;
1790         }
1791
1792         return WERR_OK;
1793 }
1794
1795
1796 /*
1797   netr_DsRAddressToSitenamesW
1798 */
1799 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1800                        struct netr_DsRAddressToSitenamesW *r)
1801 {
1802         struct netr_DsRAddressToSitenamesExW r2;
1803         struct netr_DsRAddressToSitenamesWCtr *ctr;
1804         uint32_t i;
1805         WERROR werr;
1806
1807         ZERO_STRUCT(r2);
1808
1809         r2.in.server_name = r->in.server_name;
1810         r2.in.count = r->in.count;
1811         r2.in.addresses = r->in.addresses;
1812
1813         r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
1814         W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
1815
1816         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
1817         W_ERROR_HAVE_NO_MEMORY(ctr);
1818
1819         *r->out.ctr = ctr;
1820
1821         ctr->count = r->in.count;
1822         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1823         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1824
1825         werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
1826
1827         for (i=0; i<ctr->count; i++) {
1828                 ctr->sitename[i].string   = (*r2.out.ctr)->sitename[i].string;
1829         }
1830
1831         return werr;
1832 }
1833
1834
1835 /*
1836   netr_DsrGetDcSiteCoverageW
1837 */
1838 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1839                        struct netr_DsrGetDcSiteCoverageW *r)
1840 {
1841         struct ldb_context *sam_ctx;
1842         struct DcSitesCtr *ctr;
1843         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1844
1845         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1846                                 dce_call->conn->auth_state.session_info, 0);
1847         if (sam_ctx == NULL) {
1848                 return WERR_DS_UNAVAILABLE;
1849         }
1850
1851         ctr = talloc(mem_ctx, struct DcSitesCtr);
1852         W_ERROR_HAVE_NO_MEMORY(ctr);
1853
1854         *r->out.ctr = ctr;
1855
1856         /* For now only return our default site */
1857         ctr->num_sites = 1;
1858         ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
1859         W_ERROR_HAVE_NO_MEMORY(ctr->sites);
1860         ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
1861         W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
1862
1863         return WERR_OK;
1864 }
1865
1866
1867 #define GET_CHECK_STR(dest, mem, msg, attr) \
1868 do {\
1869         const char *s; \
1870         s = ldb_msg_find_attr_as_string(msg, attr, NULL); \
1871         if (!s) { \
1872                 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1873                           "without flatname\n", \
1874                           ldb_dn_get_linearized(msg->dn))); \
1875                 continue; \
1876         } \
1877         dest = talloc_strdup(mem, s); \
1878         W_ERROR_HAVE_NO_MEMORY(dest); \
1879 } while(0)
1880
1881
1882 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1883                                          struct ldb_context *sam_ctx,
1884                                          struct netr_DomainTrustList *trusts,
1885                                          uint32_t trust_flags)
1886 {
1887         struct ldb_dn *system_dn;
1888         struct ldb_message **dom_res = NULL;
1889         const char *trust_attrs[] = { "flatname", "trustPartner",
1890                                       "securityIdentifier", "trustDirection",
1891                                       "trustType", "trustAttributes", NULL };
1892         uint32_t n;
1893         int i;
1894         int ret;
1895
1896         if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1897                              NETR_TRUST_FLAG_OUTBOUND))) {
1898                 return WERR_INVALID_FLAGS;
1899         }
1900
1901         system_dn = samdb_search_dn(sam_ctx, mem_ctx,
1902                                     ldb_get_default_basedn(sam_ctx),
1903                                     "(&(objectClass=container)(cn=System))");
1904         if (!system_dn) {
1905                 return WERR_GENERAL_FAILURE;
1906         }
1907
1908         ret = gendb_search(sam_ctx, mem_ctx, system_dn,
1909                            &dom_res, trust_attrs,
1910                            "(objectclass=trustedDomain)");
1911
1912         for (i = 0; i < ret; i++) {
1913                 unsigned int trust_dir;
1914                 uint32_t flags = 0;
1915
1916                 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
1917                                                       "trustDirection", 0);
1918
1919                 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
1920                         flags |= NETR_TRUST_FLAG_INBOUND;
1921                 }
1922                 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
1923                         flags |= NETR_TRUST_FLAG_OUTBOUND;
1924                 }
1925
1926                 if (!(flags & trust_flags)) {
1927                         /* this trust direction was not requested */
1928                         continue;
1929                 }
1930
1931                 n = trusts->count;
1932                 trusts->array = talloc_realloc(trusts, trusts->array,
1933                                                struct netr_DomainTrust,
1934                                                n + 1);
1935                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1936
1937                 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
1938                               dom_res[i], "flatname");
1939                 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
1940                               dom_res[i], "trustPartner");
1941
1942                 trusts->array[n].trust_flags = flags;
1943                 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
1944                     !(flags & NETR_TRUST_FLAG_TREEROOT)) {
1945                         /* TODO: find if we have parent in the list */
1946                         trusts->array[n].parent_index = 0;
1947                 }
1948
1949                 trusts->array[n].trust_type =
1950                                 ldb_msg_find_attr_as_uint(dom_res[i],
1951                                                   "trustType", 0);
1952                 trusts->array[n].trust_attributes =
1953                                 ldb_msg_find_attr_as_uint(dom_res[i],
1954                                                   "trustAttributes", 0);
1955
1956                 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
1957                     (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
1958                         struct dom_sid zero_sid;
1959                         ZERO_STRUCT(zero_sid);
1960                         trusts->array[n].sid =
1961                                 dom_sid_dup(trusts, &zero_sid);
1962                 } else {
1963                         trusts->array[n].sid =
1964                                 samdb_result_dom_sid(trusts, dom_res[i],
1965                                                      "securityIdentifier");
1966                 }
1967                 trusts->array[n].guid = GUID_zero();
1968
1969                 trusts->count = n + 1;
1970         }
1971
1972         talloc_free(dom_res);
1973         return WERR_OK;
1974 }
1975
1976 /*
1977   netr_DsrEnumerateDomainTrusts
1978 */
1979 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
1980                                                    TALLOC_CTX *mem_ctx,
1981                                                    struct netr_DsrEnumerateDomainTrusts *r)
1982 {
1983         struct netr_DomainTrustList *trusts;
1984         struct ldb_context *sam_ctx;
1985         int ret;
1986         struct ldb_message **dom_res;
1987         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1988         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1989         const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
1990         const char *p;
1991         WERROR werr;
1992
1993         if (r->in.trust_flags & 0xFFFFFE00) {
1994                 return WERR_INVALID_FLAGS;
1995         }
1996
1997         /* TODO: turn to hard check once we are sure this is 100% correct */
1998         if (!r->in.server_name) {
1999                 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2000                           "But received NULL!\n", dnsdomain));
2001         } else {
2002                 p = strchr(r->in.server_name, '.');
2003                 if (!p) {
2004                         DEBUG(3, ("Invalid domain! Expected name in domain "
2005                                   "[%s]. But received [%s]!\n",
2006                                   dnsdomain, r->in.server_name));
2007                         p = r->in.server_name;
2008                 } else {
2009                         p++;
2010                 }
2011                 if (strcasecmp(p, dnsdomain)) {
2012                         DEBUG(3, ("Invalid domain! Expected name in domain "
2013                                   "[%s]. But received [%s]!\n",
2014                                   dnsdomain, r->in.server_name));
2015                 }
2016         }
2017
2018         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2019         W_ERROR_HAVE_NO_MEMORY(trusts);
2020
2021         trusts->count = 0;
2022         r->out.trusts = trusts;
2023
2024         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2025                                 dce_call->conn->auth_state.session_info, 0);
2026         if (sam_ctx == NULL) {
2027                 return WERR_GENERAL_FAILURE;
2028         }
2029
2030         if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2031             (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2032
2033                 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2034                                                   trusts, r->in.trust_flags);
2035                 W_ERROR_NOT_OK_RETURN(werr);
2036         }
2037
2038         /* NOTE: we currently are always the root of the forest */
2039         if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2040                 uint32_t n = trusts->count;
2041
2042                 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2043                                       &dom_res, dom_attrs);
2044                 if (ret != 1) {
2045                         return WERR_GENERAL_FAILURE;
2046                 }
2047
2048                 trusts->count = n + 1;
2049                 trusts->array = talloc_realloc(trusts, trusts->array,
2050                                                struct netr_DomainTrust,
2051                                                trusts->count);
2052                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2053
2054                 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2055                 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2056                 trusts->array[n].trust_flags =
2057                         NETR_TRUST_FLAG_NATIVE |
2058                         NETR_TRUST_FLAG_TREEROOT |
2059                         NETR_TRUST_FLAG_IN_FOREST |
2060                         NETR_TRUST_FLAG_PRIMARY;
2061                 /* we are always the root domain for now */
2062                 trusts->array[n].parent_index = 0;
2063                 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2064                 trusts->array[n].trust_attributes = 0;
2065                 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2066                                                             dom_res[0],
2067                                                             "objectSid");
2068                 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2069                                                           "objectGUID");
2070                 talloc_free(dom_res);
2071         }
2072
2073         return WERR_OK;
2074 }
2075
2076
2077 /*
2078   netr_DsrDeregisterDNSHostRecords
2079 */
2080 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2081                        struct netr_DsrDeregisterDNSHostRecords *r)
2082 {
2083         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2084 }
2085
2086
2087 /*
2088   netr_ServerTrustPasswordsGet
2089 */
2090 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2091                        struct netr_ServerTrustPasswordsGet *r)
2092 {
2093         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2094 }
2095
2096
2097 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2098                                       struct ldb_context *sam_ctx,
2099                                       struct loadparm_context *lp_ctx,
2100                                       struct lsa_ForestTrustInformation *info)
2101 {
2102         struct lsa_ForestTrustDomainInfo *domain_info;
2103         struct lsa_ForestTrustRecord *e;
2104         struct ldb_message **dom_res;
2105         const char * const dom_attrs[] = { "objectSid", NULL };
2106         int ret;
2107
2108         /* we need to provide 2 entries:
2109          * 1. the Root Forest name
2110          * 2. the Domain Information
2111          */
2112
2113         info->count = 2;
2114         info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2115         W_ERROR_HAVE_NO_MEMORY(info->entries);
2116
2117         /* Forest root info */
2118         e = talloc(info, struct lsa_ForestTrustRecord);
2119         W_ERROR_HAVE_NO_MEMORY(e);
2120
2121         e->flags = 0;
2122         e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2123         e->time = 0; /* so far always 0 in trces. */
2124         e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2125                                                                        mem_ctx);
2126         W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2127
2128         info->entries[0] = e;
2129
2130         /* Domain info */
2131         e = talloc(info, struct lsa_ForestTrustRecord);
2132         W_ERROR_HAVE_NO_MEMORY(e);
2133
2134         /* get our own domain info */
2135         ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2136         if (ret != 1) {
2137                 return WERR_GENERAL_FAILURE;
2138         }
2139
2140         /* TODO: check if disabled and set flags accordingly */
2141         e->flags = 0;
2142         e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2143         e->time = 0; /* so far always 0 in traces. */
2144
2145         domain_info = &e->forest_trust_data.domain_info;
2146         domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2147                                                        "objectSid");
2148         domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2149         domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2150
2151         info->entries[1] = e;
2152
2153         talloc_free(dom_res);
2154
2155         return WERR_OK;
2156 }
2157
2158 /*
2159   netr_DsRGetForestTrustInformation
2160 */
2161 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2162                                                        TALLOC_CTX *mem_ctx,
2163                                                        struct netr_DsRGetForestTrustInformation *r)
2164 {
2165         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2166         struct lsa_ForestTrustInformation *info, **info_ptr;
2167         struct ldb_context *sam_ctx;
2168         WERROR werr;
2169
2170         if (r->in.flags & 0xFFFFFFFE) {
2171                 return WERR_INVALID_FLAGS;
2172         }
2173
2174         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2175                                 dce_call->conn->auth_state.session_info, 0);
2176         if (sam_ctx == NULL) {
2177                 return WERR_GENERAL_FAILURE;
2178         }
2179
2180         if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2181                 if (!samdb_is_pdc(sam_ctx)) {
2182                         return WERR_NERR_NOTPRIMARY;
2183                 }
2184
2185                 if (r->in.trusted_domain_name == NULL) {
2186                         return WERR_INVALID_FLAGS;
2187                 }
2188
2189                 /* TODO: establish an schannel connection with
2190                  * r->in.trusted_domain_name and perform a
2191                  * netr_GetForestTrustInformation call against it */
2192
2193                 /* for now return not implementd */
2194                 return WERR_CALL_NOT_IMPLEMENTED;
2195         }
2196
2197         /* TODO: check r->in.server_name is our name */
2198
2199         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2200         W_ERROR_HAVE_NO_MEMORY(info_ptr);
2201
2202         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2203         W_ERROR_HAVE_NO_MEMORY(info);
2204
2205         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2206         W_ERROR_NOT_OK_RETURN(werr);
2207
2208         *info_ptr = info;
2209         r->out.forest_trust_info = info_ptr;
2210
2211         return WERR_OK;
2212 }
2213
2214
2215 /*
2216   netr_GetForestTrustInformation
2217 */
2218 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2219                                                       TALLOC_CTX *mem_ctx,
2220                                                       struct netr_GetForestTrustInformation *r)
2221 {
2222         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2223         struct netlogon_creds_CredentialState *creds;
2224         struct lsa_ForestTrustInformation *info, **info_ptr;
2225         struct ldb_context *sam_ctx;
2226         NTSTATUS status;
2227         WERROR werr;
2228
2229         status = dcesrv_netr_creds_server_step_check(dce_call,
2230                                                      mem_ctx,
2231                                                      r->in.computer_name,
2232                                                      r->in.credential,
2233                                                      r->out.return_authenticator,
2234                                                      &creds);
2235         if (!NT_STATUS_IS_OK(status)) {
2236                 return status;
2237         }
2238
2239         if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2240             (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2241                 return NT_STATUS_NOT_IMPLEMENTED;
2242         }
2243
2244         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2245                                 dce_call->conn->auth_state.session_info, 0);
2246         if (sam_ctx == NULL) {
2247                 return NT_STATUS_UNSUCCESSFUL;
2248         }
2249
2250         /* TODO: check r->in.server_name is our name */
2251
2252         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2253         if (!info_ptr) {
2254                 return NT_STATUS_NO_MEMORY;
2255         }
2256         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2257         if (!info) {
2258                 return NT_STATUS_NO_MEMORY;
2259         }
2260
2261         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2262         if (!W_ERROR_IS_OK(werr)) {
2263                 return werror_to_ntstatus(werr);
2264         }
2265
2266         *info_ptr = info;
2267         r->out.forest_trust_info = info_ptr;
2268
2269         return NT_STATUS_OK;
2270 }
2271
2272
2273 /*
2274   netr_ServerGetTrustInfo
2275 */
2276 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2277                        struct netr_ServerGetTrustInfo *r)
2278 {
2279         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2280 }
2281
2282 /*
2283   netr_Unused47
2284 */
2285 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2286                                      struct netr_Unused47 *r)
2287 {
2288         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2289 }
2290
2291
2292 struct netr_dnsupdate_RODC_state {
2293         struct dcesrv_call_state *dce_call;
2294         struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2295         struct dnsupdate_RODC *r2;
2296 };
2297
2298 /*
2299   called when the forwarded RODC dns update request is finished
2300  */
2301 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2302 {
2303         struct netr_dnsupdate_RODC_state *st =
2304                 tevent_req_callback_data(subreq,
2305                                          struct netr_dnsupdate_RODC_state);
2306         NTSTATUS status;
2307
2308         status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2309         TALLOC_FREE(subreq);
2310         if (!NT_STATUS_IS_OK(status)) {
2311                 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2312                 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2313         }
2314
2315         st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2316
2317         status = dcesrv_reply(st->dce_call);
2318         if (!NT_STATUS_IS_OK(status)) {
2319                 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2320         }
2321 }
2322
2323 /*
2324   netr_DsrUpdateReadOnlyServerDnsRecords
2325 */
2326 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2327                                                               TALLOC_CTX *mem_ctx,
2328                                                               struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2329 {
2330         struct netlogon_creds_CredentialState *creds;
2331         NTSTATUS nt_status;
2332         struct dcerpc_binding_handle *binding_handle;
2333         struct netr_dnsupdate_RODC_state *st;
2334         struct tevent_req *subreq;
2335
2336         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2337                                                         mem_ctx,
2338                                                         r->in.computer_name,
2339                                                         r->in.credential,
2340                                                         r->out.return_authenticator,
2341                                                         &creds);
2342         NT_STATUS_NOT_OK_RETURN(nt_status);
2343
2344         if (creds->secure_channel_type != SEC_CHAN_RODC) {
2345                 return NT_STATUS_ACCESS_DENIED;
2346         }
2347
2348         st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2349         NT_STATUS_HAVE_NO_MEMORY(st);
2350
2351         st->dce_call = dce_call;
2352         st->r = r;
2353         st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2354         NT_STATUS_HAVE_NO_MEMORY(st->r2);
2355
2356         st->r2->in.dom_sid = creds->sid;
2357         st->r2->in.site_name = r->in.site_name;
2358         st->r2->in.dns_ttl = r->in.dns_ttl;
2359         st->r2->in.dns_names = r->in.dns_names;
2360         st->r2->out.dns_names = r->out.dns_names;
2361
2362         binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2363                                                      "dnsupdate", &ndr_table_irpc);
2364         if (binding_handle == NULL) {
2365                 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2366                 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2367                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2368         }
2369
2370         /* forward the call */
2371         subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2372                                               binding_handle, st->r2);
2373         NT_STATUS_HAVE_NO_MEMORY(subreq);
2374
2375         dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2376
2377         /* setup the callback */
2378         tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2379
2380         return NT_STATUS_OK;
2381 }
2382
2383
2384 /* include the generated boilerplate */
2385 #include "librpc/gen_ndr/ndr_netlogon_s.c"