samdb: Add flags argument to samdb_connect().
[nivanova/samba-autobuild/.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         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
944                                 dce_call->conn->dce_ctx->lp_ctx,
945                                 dce_call->conn->auth_state.session_info, 0);
946         if (sam_ctx == NULL) {
947                 return WERR_DS_UNAVAILABLE;
948         }
949
950         domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
951                                        r->in.domainname);
952         if (domain_dn == NULL) {
953                 return WERR_DS_UNAVAILABLE;
954         }
955
956         ret = gendb_search_dn(sam_ctx, mem_ctx,
957                               domain_dn, &res, attrs);
958         if (ret != 1) {
959                 return WERR_NO_SUCH_DOMAIN;
960         }
961
962         /* TODO: - return real IP address
963          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
964          */
965         dcname = talloc_asprintf(mem_ctx, "\\\\%s",
966                                  lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
967         W_ERROR_HAVE_NO_MEMORY(dcname);
968
969         *r->out.dcname = dcname;
970         return WERR_OK;
971 }
972
973
974 /*
975   netr_LogonControl2Ex
976 */
977 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
978                        struct netr_LogonControl2Ex *r)
979 {
980         return WERR_NOT_SUPPORTED;
981 }
982
983
984 /*
985   netr_LogonControl
986 */
987 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
988                        struct netr_LogonControl *r)
989 {
990         struct netr_LogonControl2Ex r2;
991         WERROR werr;
992
993         if (r->in.level == 0x00000001) {
994                 ZERO_STRUCT(r2);
995
996                 r2.in.logon_server = r->in.logon_server;
997                 r2.in.function_code = r->in.function_code;
998                 r2.in.level = r->in.level;
999                 r2.in.data = NULL;
1000                 r2.out.query = r->out.query;
1001
1002                 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1003         } else if (r->in.level == 0x00000002) {
1004                 werr = WERR_NOT_SUPPORTED;
1005         } else {
1006                 werr = WERR_UNKNOWN_LEVEL;
1007         }
1008
1009         return werr;
1010 }
1011
1012
1013 /*
1014   netr_LogonControl2
1015 */
1016 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1017                        struct netr_LogonControl2 *r)
1018 {
1019         struct netr_LogonControl2Ex r2;
1020         WERROR werr;
1021
1022         ZERO_STRUCT(r2);
1023
1024         r2.in.logon_server = r->in.logon_server;
1025         r2.in.function_code = r->in.function_code;
1026         r2.in.level = r->in.level;
1027         r2.in.data = r->in.data;
1028         r2.out.query = r->out.query;
1029
1030         werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1031
1032         return werr;
1033 }
1034
1035 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1036                                          struct ldb_context *sam_ctx,
1037                                          struct netr_DomainTrustList *trusts,
1038                                          uint32_t trust_flags);
1039
1040 /*
1041   netr_GetAnyDCName
1042 */
1043 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1044                        struct netr_GetAnyDCName *r)
1045 {
1046         struct netr_DomainTrustList *trusts;
1047         struct ldb_context *sam_ctx;
1048         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1049         uint32_t i;
1050         WERROR werr;
1051
1052         *r->out.dcname = NULL;
1053
1054         if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1055                 /* if the domainname parameter wasn't set assume our domain */
1056                 r->in.domainname = lpcfg_workgroup(lp_ctx);
1057         }
1058
1059         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1060                                 dce_call->conn->auth_state.session_info, 0);
1061         if (sam_ctx == NULL) {
1062                 return WERR_DS_UNAVAILABLE;
1063         }
1064
1065         if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1066                 /* well we asked for a DC of our own domain */
1067                 if (samdb_is_pdc(sam_ctx)) {
1068                         /* we are the PDC of the specified domain */
1069                         return WERR_NO_SUCH_DOMAIN;
1070                 }
1071
1072                 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1073                                                 lpcfg_netbios_name(lp_ctx));
1074                 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1075
1076                 return WERR_OK;
1077         }
1078
1079         /* Okay, now we have to consider the trusted domains */
1080
1081         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1082         W_ERROR_HAVE_NO_MEMORY(trusts);
1083
1084         trusts->count = 0;
1085
1086         werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1087                                           NETR_TRUST_FLAG_INBOUND
1088                                           | NETR_TRUST_FLAG_OUTBOUND);
1089         W_ERROR_NOT_OK_RETURN(werr);
1090
1091         for (i = 0; i < trusts->count; i++) {
1092                 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1093                         /* FIXME: Here we need to find a DC for the specified
1094                          * trusted domain. */
1095
1096                         /* return WERR_OK; */
1097                         return WERR_NO_SUCH_DOMAIN;
1098                 }
1099         }
1100
1101         return WERR_NO_SUCH_DOMAIN;
1102 }
1103
1104
1105 /*
1106   netr_DatabaseRedo
1107 */
1108 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1109                        struct netr_DatabaseRedo *r)
1110 {
1111         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1112 }
1113
1114
1115 /*
1116   netr_NetrEnumerateTrustedDomains
1117 */
1118 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1119                        struct netr_NetrEnumerateTrustedDomains *r)
1120 {
1121         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1122 }
1123
1124
1125 /*
1126   netr_LogonGetCapabilities
1127 */
1128 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1129                        struct netr_LogonGetCapabilities *r)
1130 {
1131         /* we don't support AES yet */
1132         return NT_STATUS_NOT_IMPLEMENTED;
1133 }
1134
1135
1136 /*
1137   netr_NETRLOGONSETSERVICEBITS
1138 */
1139 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1140                        struct netr_NETRLOGONSETSERVICEBITS *r)
1141 {
1142         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1143 }
1144
1145
1146 /*
1147   netr_LogonGetTrustRid
1148 */
1149 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1150                        struct netr_LogonGetTrustRid *r)
1151 {
1152         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1153 }
1154
1155
1156 /*
1157   netr_NETRLOGONCOMPUTESERVERDIGEST
1158 */
1159 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1160                        struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1161 {
1162         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1163 }
1164
1165
1166 /*
1167   netr_NETRLOGONCOMPUTECLIENTDIGEST
1168 */
1169 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1170                        struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1171 {
1172         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1173 }
1174
1175
1176
1177 /*
1178   netr_DsRGetSiteName
1179 */
1180 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1181                                   struct netr_DsRGetSiteName *r)
1182 {
1183         struct ldb_context *sam_ctx;
1184         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1185
1186         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1187                                 dce_call->conn->auth_state.session_info, 0);
1188         if (sam_ctx == NULL) {
1189                 return WERR_DS_UNAVAILABLE;
1190         }
1191
1192         *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1193         W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1194
1195         return WERR_OK;
1196 }
1197
1198
1199 /*
1200   fill in a netr_OneDomainInfo from a ldb search result
1201 */
1202 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1203                                      struct loadparm_context *lp_ctx,
1204                                      struct ldb_context *sam_ctx,
1205                                      struct ldb_message *res,
1206                                      struct netr_OneDomainInfo *info,
1207                                      bool is_local, bool is_trust_list)
1208 {
1209         ZERO_STRUCTP(info);
1210
1211         if (is_trust_list) {
1212                 /* w2k8 only fills this on trusted domains */
1213                 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1214                 info->trust_extension.length = 16;
1215                 info->trust_extension.info->flags =
1216                         NETR_TRUST_FLAG_TREEROOT |
1217                         NETR_TRUST_FLAG_IN_FOREST |
1218                         NETR_TRUST_FLAG_PRIMARY |
1219                         NETR_TRUST_FLAG_NATIVE;
1220
1221                 info->trust_extension.info->parent_index = 0; /* should be index into array
1222                                                                  of parent */
1223                 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1224                 info->trust_extension.info->trust_attributes = 0; /*    TODO: base on ldb search? */
1225         }
1226
1227         if (is_trust_list) {
1228                 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1229                 info->dns_forestname.string = NULL;
1230         } else {
1231                 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1232                 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1233                 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1234                 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1235         }
1236
1237         if (is_local) {
1238                 info->domainname.string = lpcfg_workgroup(lp_ctx);
1239                 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1240                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1241                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1242         } else {
1243                 info->domainname.string = samdb_result_string(res, "flatName", NULL);
1244                 info->dns_domainname.string = samdb_result_string(res, "trustPartner", NULL);
1245                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1246                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1247         }
1248         if (!is_trust_list) {
1249                 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1250         }
1251
1252         return NT_STATUS_OK;
1253 }
1254
1255 /*
1256   netr_LogonGetDomainInfo
1257   this is called as part of the ADS domain logon procedure.
1258
1259   It has an important role in convaying details about the client, such
1260   as Operating System, Version, Service Pack etc.
1261 */
1262 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1263         TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1264 {
1265         struct netlogon_creds_CredentialState *creds;
1266         const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1267                 "securityIdentifier", "trustPartner", NULL };
1268         const char * const attrs2[] = { "dNSHostName",
1269                 "msDS-SupportedEncryptionTypes", NULL };
1270         const char *temp_str, *temp_str2;
1271         const char *old_dns_hostname;
1272         struct ldb_context *sam_ctx;
1273         struct ldb_message **res1, **res2, **res3, *new_msg;
1274         struct ldb_dn *workstation_dn;
1275         struct netr_DomainInformation *domain_info;
1276         struct netr_LsaPolicyInformation *lsa_policy_info;
1277         struct netr_OsVersionInfoEx *os_version;
1278         uint32_t default_supported_enc_types = 0xFFFFFFFF;
1279         bool update_dns_hostname = true;
1280         int ret, ret3, i;
1281         NTSTATUS status;
1282
1283         status = dcesrv_netr_creds_server_step_check(dce_call,
1284                                                      mem_ctx,
1285                                                      r->in.computer_name,
1286                                                      r->in.credential,
1287                                                      r->out.return_authenticator,
1288                                                      &creds);
1289         if (!NT_STATUS_IS_OK(status)) {
1290                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1291         }
1292         NT_STATUS_NOT_OK_RETURN(status);
1293
1294         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1295                                 dce_call->conn->dce_ctx->lp_ctx,
1296                                 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1297         if (sam_ctx == NULL) {
1298                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1299         }
1300
1301         switch (r->in.level) {
1302         case 1: /* Domain information */
1303
1304                 if (r->in.query->workstation_info == NULL) {
1305                         return NT_STATUS_INVALID_PARAMETER;
1306                 }
1307
1308                 /*
1309                  * Checks that the computer name parameter without possible "$"
1310                  * matches as prefix with the DNS hostname in the workstation
1311                  * info structure.
1312                  */
1313                 temp_str = talloc_strndup(mem_ctx,
1314                                           r->in.computer_name,
1315                                           strcspn(r->in.computer_name, "$"));
1316                 NT_STATUS_HAVE_NO_MEMORY(temp_str);
1317                 temp_str2 = talloc_strndup(mem_ctx,
1318                                            r->in.query->workstation_info->dns_hostname,
1319                                            strcspn(r->in.query->workstation_info->dns_hostname, "."));
1320                 NT_STATUS_HAVE_NO_MEMORY(temp_str2);
1321                 if (strcasecmp(temp_str, temp_str2) != 0) {
1322                         update_dns_hostname = false;
1323                 }
1324
1325                 /* Prepare the workstation DN */
1326                 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1327                         dom_sid_string(mem_ctx, creds->sid));
1328                 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1329
1330                 /* Lookup for attributes in workstation object */
1331                 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
1332                         &res1, attrs2);
1333                 if (ret != 1) {
1334                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1335                 }
1336
1337                 /* Gets the old DNS hostname */
1338                 old_dns_hostname = samdb_result_string(res1[0], "dNSHostName",
1339                         NULL);
1340
1341                 /*
1342                  * Updates the DNS hostname when the client wishes that the
1343                  * server should handle this for him
1344                  * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1345                  * obviously only checked when we do already have a
1346                  * "dNSHostName".
1347                  * See MS-NRPC section 3.5.4.3.9
1348                  */
1349                 if ((old_dns_hostname != NULL) &&
1350                     (r->in.query->workstation_info->workstation_flags
1351                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1352                         update_dns_hostname = false;
1353                 }
1354
1355                 /* Gets host informations and put them into our directory */
1356
1357                 new_msg = ldb_msg_new(mem_ctx);
1358                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1359
1360                 new_msg->dn = workstation_dn;
1361
1362                 /* Sets the OS name */
1363                 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1364                         "operatingSystem",
1365                         r->in.query->workstation_info->os_name.string);
1366
1367                 /*
1368                  * Sets informations from "os_version". On an empty structure
1369                  * the values are cleared.
1370                  */
1371                 if (r->in.query->workstation_info->os_version.os != NULL) {
1372                         os_version = &r->in.query->workstation_info->os_version.os->os;
1373
1374                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1375                                              "operatingSystemServicePack",
1376                                              os_version->CSDVersion);
1377
1378                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1379                                 "operatingSystemVersion",
1380                                 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1381                                         os_version->MajorVersion,
1382                                         os_version->MinorVersion,
1383                                         os_version->BuildNumber
1384                                 )
1385                         );
1386                 } else {
1387                         samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1388                                              "operatingSystemServicePack");
1389
1390                         samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1391                                              "operatingSystemVersion");
1392                 }
1393
1394                 /*
1395                  * If the boolean "update_dns_hostname" remained true, then we
1396                  * are fine to start the update.
1397                  */
1398                 if (update_dns_hostname) {
1399                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1400                                 "dNSHostname",
1401                         r->in.query->workstation_info->dns_hostname);
1402
1403                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1404                                 "servicePrincipalName",
1405                                 talloc_asprintf(mem_ctx, "HOST/%s",
1406                                 r->in.computer_name)
1407                         );
1408                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1409                                 "servicePrincipalName",
1410                                 talloc_asprintf(mem_ctx, "HOST/%s",
1411                                 r->in.query->workstation_info->dns_hostname)
1412                         );
1413                 }
1414
1415                 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1416                         DEBUG(3,("Impossible to update samdb: %s\n",
1417                                 ldb_errstring(sam_ctx)));
1418                 }
1419
1420                 talloc_free(new_msg);
1421
1422                 /* Writes back the domain information */
1423
1424                 /* We need to do two searches. The first will pull our primary
1425                    domain and the second will pull any trusted domains. Our
1426                    primary domain is also a "trusted" domain, so we need to
1427                    put the primary domain into the lists of returned trusts as
1428                    well. */
1429                 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1430                         &res2, attrs);
1431                 if (ret != 1) {
1432                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1433                 }
1434
1435                 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1436                         "(objectClass=trustedDomain)");
1437                 if (ret3 == -1) {
1438                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1439                 }
1440
1441                 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1442                 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1443
1444                 ZERO_STRUCTP(domain_info);
1445
1446                 /* Informations about the local and trusted domains */
1447
1448                 status = fill_one_domain_info(mem_ctx,
1449                         dce_call->conn->dce_ctx->lp_ctx,
1450                         sam_ctx, res2[0], &domain_info->primary_domain,
1451                         true, false);
1452                 NT_STATUS_NOT_OK_RETURN(status);
1453
1454                 domain_info->trusted_domain_count = ret3 + 1;
1455                 domain_info->trusted_domains = talloc_array(mem_ctx,
1456                         struct netr_OneDomainInfo,
1457                         domain_info->trusted_domain_count);
1458                 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1459
1460                 for (i=0;i<ret3;i++) {
1461                         status = fill_one_domain_info(mem_ctx,
1462                                 dce_call->conn->dce_ctx->lp_ctx,
1463                                 sam_ctx, res3[i],
1464                                 &domain_info->trusted_domains[i],
1465                                 false, true);
1466                         NT_STATUS_NOT_OK_RETURN(status);
1467                 }
1468
1469                 status = fill_one_domain_info(mem_ctx,
1470                         dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1471                         &domain_info->trusted_domains[i], true, true);
1472                 NT_STATUS_NOT_OK_RETURN(status);
1473
1474                 /* Sets the supported encryption types */
1475                 domain_info->supported_enc_types = samdb_result_uint(res1[0],
1476                         "msDS-SupportedEncryptionTypes",
1477                         default_supported_enc_types);
1478
1479                 /* Other host domain informations */
1480
1481                 lsa_policy_info = talloc(mem_ctx,
1482                         struct netr_LsaPolicyInformation);
1483                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1484                 ZERO_STRUCTP(lsa_policy_info);
1485
1486                 domain_info->lsa_policy = *lsa_policy_info;
1487
1488                 /* The DNS hostname is only returned back when there is a chance
1489                  * for a change. */
1490                 if ((r->in.query->workstation_info->workstation_flags
1491                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1492                         domain_info->dns_hostname.string = old_dns_hostname;
1493                 } else {
1494                         domain_info->dns_hostname.string = NULL;
1495                 }
1496
1497                 domain_info->workstation_flags =
1498                         r->in.query->workstation_info->workstation_flags;
1499
1500                 r->out.info->domain_info = domain_info;
1501         break;
1502         case 2: /* LSA policy information - not used at the moment */
1503                 lsa_policy_info = talloc(mem_ctx,
1504                         struct netr_LsaPolicyInformation);
1505                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1506                 ZERO_STRUCTP(lsa_policy_info);
1507
1508                 r->out.info->lsa_policy_info = lsa_policy_info;
1509         break;
1510         default:
1511                 return NT_STATUS_INVALID_LEVEL;
1512         break;
1513         }
1514
1515         return NT_STATUS_OK;
1516 }
1517
1518
1519
1520 /*
1521   netr_ServerPasswordGet
1522 */
1523 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1524                        struct netr_ServerPasswordGet *r)
1525 {
1526         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1527 }
1528
1529
1530 /*
1531   netr_NETRLOGONSENDTOSAM
1532 */
1533 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1534                        struct netr_NETRLOGONSENDTOSAM *r)
1535 {
1536         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1537 }
1538
1539
1540 /*
1541   netr_DsRGetDCNameEx2
1542 */
1543 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1544                                           TALLOC_CTX *mem_ctx,
1545                                           struct netr_DsRGetDCNameEx2 *r)
1546 {
1547         struct ldb_context *sam_ctx;
1548         struct netr_DsRGetDCNameInfo *info;
1549         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1550         const struct tsocket_address *remote_address;
1551         char *addr = NULL;
1552         const char *server_site_name;
1553         char *guid_str;
1554         struct netlogon_samlogon_response response;
1555         NTSTATUS status;
1556
1557         ZERO_STRUCTP(r->out.info);
1558
1559         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1560                                 dce_call->conn->auth_state.session_info, 0);
1561         if (sam_ctx == NULL) {
1562                 return WERR_DS_UNAVAILABLE;
1563         }
1564
1565         remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1566         if (tsocket_address_is_inet(remote_address, "ip")) {
1567                 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1568                 W_ERROR_HAVE_NO_MEMORY(addr);
1569         }
1570
1571         /* "server_unc" is ignored by w2k3 */
1572
1573         /* Proof server site parameter "site_name" if it was specified */
1574         server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1575         W_ERROR_HAVE_NO_MEMORY(server_site_name);
1576         if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1577                                                      server_site_name) != 0)) {
1578                 return WERR_NO_SUCH_DOMAIN;
1579         }
1580
1581         /* TODO: the flags are ignored for now */
1582
1583         guid_str = r->in.domain_guid != NULL ?
1584                  GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1585
1586         status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1587                                                  r->in.domain_name,
1588                                                  r->in.domain_name,
1589                                                  NULL, guid_str,
1590                                                  r->in.client_account,
1591                                                  r->in.mask, addr,
1592                                                  NETLOGON_NT_VERSION_5EX_WITH_IP,
1593                                                  lp_ctx, &response, true);
1594         if (!NT_STATUS_IS_OK(status)) {
1595                 return ntstatus_to_werror(status);
1596         }
1597
1598         info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1599         W_ERROR_HAVE_NO_MEMORY(info);
1600         info->dc_unc           = talloc_asprintf(mem_ctx, "\\\\%s",
1601                                                  response.data.nt5_ex.pdc_dns_name);
1602         W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1603         info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1604                                            response.data.nt5_ex.sockaddr.pdc_ip);
1605         W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1606         info->dc_address_type  = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1607         info->domain_guid      = response.data.nt5_ex.domain_uuid;
1608         info->domain_name      = response.data.nt5_ex.dns_domain;
1609         info->forest_name      = response.data.nt5_ex.forest;
1610         info->dc_flags         = response.data.nt5_ex.server_type;
1611         info->dc_site_name     = response.data.nt5_ex.server_site;
1612         info->client_site_name = response.data.nt5_ex.client_site;
1613
1614         *r->out.info = info;
1615
1616         return WERR_OK;
1617 }
1618
1619 /*
1620   netr_DsRGetDCNameEx
1621 */
1622 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1623                                   struct netr_DsRGetDCNameEx *r)
1624 {
1625         struct netr_DsRGetDCNameEx2 r2;
1626         WERROR werr;
1627
1628         ZERO_STRUCT(r2);
1629
1630         r2.in.server_unc = r->in.server_unc;
1631         r2.in.client_account = NULL;
1632         r2.in.mask = 0;
1633         r2.in.domain_guid = r->in.domain_guid;
1634         r2.in.domain_name = r->in.domain_name;
1635         r2.in.site_name = r->in.site_name;
1636         r2.in.flags = r->in.flags;
1637         r2.out.info = r->out.info;
1638
1639         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1640
1641         return werr;
1642 }
1643
1644 /*
1645   netr_DsRGetDCName
1646 */
1647 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1648                                 struct netr_DsRGetDCName *r)
1649 {
1650         struct netr_DsRGetDCNameEx2 r2;
1651         WERROR werr;
1652
1653         ZERO_STRUCT(r2);
1654
1655         r2.in.server_unc = r->in.server_unc;
1656         r2.in.client_account = NULL;
1657         r2.in.mask = 0;
1658         r2.in.domain_name = r->in.domain_name;
1659         r2.in.domain_guid = r->in.domain_guid;
1660
1661         r2.in.site_name = NULL; /* should fill in from site GUID */
1662         r2.in.flags = r->in.flags;
1663         r2.out.info = r->out.info;
1664
1665         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1666
1667         return werr;
1668 }
1669 /*
1670   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1671 */
1672 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1673                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1674 {
1675         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1676 }
1677
1678
1679 /*
1680   netr_NetrEnumerateTrustedDomainsEx
1681 */
1682 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1683                        struct netr_NetrEnumerateTrustedDomainsEx *r)
1684 {
1685         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1686 }
1687
1688
1689 /*
1690   netr_DsRAddressToSitenamesExW
1691 */
1692 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1693                                                    struct netr_DsRAddressToSitenamesExW *r)
1694 {
1695         struct ldb_context *sam_ctx;
1696         struct netr_DsRAddressToSitenamesExWCtr *ctr;
1697         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1698         sa_family_t sin_family;
1699         struct sockaddr_in *addr;
1700 #ifdef HAVE_IPV6
1701         struct sockaddr_in6 *addr6;
1702         char addr_str[INET6_ADDRSTRLEN];
1703 #else
1704         char addr_str[INET_ADDRSTRLEN];
1705 #endif
1706         char *subnet_name;
1707         const char *res;
1708         uint32_t i;
1709
1710         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1711                                 dce_call->conn->auth_state.session_info, 0);
1712         if (sam_ctx == NULL) {
1713                 return WERR_DS_UNAVAILABLE;
1714         }
1715
1716         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1717         W_ERROR_HAVE_NO_MEMORY(ctr);
1718
1719         *r->out.ctr = ctr;
1720
1721         ctr->count = r->in.count;
1722         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1723         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1724         ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1725         W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1726
1727         for (i=0; i<ctr->count; i++) {
1728                 ctr->sitename[i].string = NULL;
1729                 ctr->subnetname[i].string = NULL;
1730
1731                 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1732                         continue;
1733                 }
1734                 /* The first two byte of the buffer are reserved for the
1735                  * "sin_family" but for now only the first one is used. */
1736                 sin_family = r->in.addresses[i].buffer[0];
1737
1738                 switch (sin_family) {
1739                 case AF_INET:
1740                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1741                                 continue;
1742                         }
1743                         addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1744                         res = inet_ntop(AF_INET, &addr->sin_addr,
1745                                         addr_str, sizeof(addr_str));
1746                         break;
1747 #ifdef HAVE_IPV6
1748                 case AF_INET6:
1749                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1750                                 continue;
1751                         }
1752                         addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1753                         res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1754                                         addr_str, sizeof(addr_str));
1755                         break;
1756 #endif
1757                 default:
1758                         continue;
1759                 }
1760
1761                 if (res == NULL) {
1762                         continue;
1763                 }
1764
1765                 ctr->sitename[i].string   = samdb_client_site_name(sam_ctx,
1766                                                                    mem_ctx,
1767                                                                    addr_str,
1768                                                                    &subnet_name);
1769                 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1770                 ctr->subnetname[i].string = subnet_name;
1771         }
1772
1773         return WERR_OK;
1774 }
1775
1776
1777 /*
1778   netr_DsRAddressToSitenamesW
1779 */
1780 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1781                        struct netr_DsRAddressToSitenamesW *r)
1782 {
1783         struct netr_DsRAddressToSitenamesExW r2;
1784         struct netr_DsRAddressToSitenamesWCtr *ctr;
1785         uint32_t i;
1786         WERROR werr;
1787
1788         ZERO_STRUCT(r2);
1789
1790         r2.in.server_name = r->in.server_name;
1791         r2.in.count = r->in.count;
1792         r2.in.addresses = r->in.addresses;
1793
1794         r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
1795         W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
1796
1797         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
1798         W_ERROR_HAVE_NO_MEMORY(ctr);
1799
1800         *r->out.ctr = ctr;
1801
1802         ctr->count = r->in.count;
1803         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1804         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1805
1806         werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
1807
1808         for (i=0; i<ctr->count; i++) {
1809                 ctr->sitename[i].string   = (*r2.out.ctr)->sitename[i].string;
1810         }
1811
1812         return werr;
1813 }
1814
1815
1816 /*
1817   netr_DsrGetDcSiteCoverageW
1818 */
1819 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1820                        struct netr_DsrGetDcSiteCoverageW *r)
1821 {
1822         struct ldb_context *sam_ctx;
1823         struct DcSitesCtr *ctr;
1824         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1825
1826         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1827                                 dce_call->conn->auth_state.session_info, 0);
1828         if (sam_ctx == NULL) {
1829                 return WERR_DS_UNAVAILABLE;
1830         }
1831
1832         ctr = talloc(mem_ctx, struct DcSitesCtr);
1833         W_ERROR_HAVE_NO_MEMORY(ctr);
1834
1835         *r->out.ctr = ctr;
1836
1837         /* For now only return our default site */
1838         ctr->num_sites = 1;
1839         ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
1840         W_ERROR_HAVE_NO_MEMORY(ctr->sites);
1841         ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
1842         W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
1843
1844         return WERR_OK;
1845 }
1846
1847
1848 #define GET_CHECK_STR(dest, mem, msg, attr) \
1849 do {\
1850         const char *s; \
1851         s = samdb_result_string(msg, attr, NULL); \
1852         if (!s) { \
1853                 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1854                           "without flatname\n", \
1855                           ldb_dn_get_linearized(msg->dn))); \
1856                 continue; \
1857         } \
1858         dest = talloc_strdup(mem, s); \
1859         W_ERROR_HAVE_NO_MEMORY(dest); \
1860 } while(0)
1861
1862
1863 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1864                                          struct ldb_context *sam_ctx,
1865                                          struct netr_DomainTrustList *trusts,
1866                                          uint32_t trust_flags)
1867 {
1868         struct ldb_dn *system_dn;
1869         struct ldb_message **dom_res = NULL;
1870         const char *trust_attrs[] = { "flatname", "trustPartner",
1871                                       "securityIdentifier", "trustDirection",
1872                                       "trustType", "trustAttributes", NULL };
1873         uint32_t n;
1874         int i;
1875         int ret;
1876
1877         if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1878                              NETR_TRUST_FLAG_OUTBOUND))) {
1879                 return WERR_INVALID_FLAGS;
1880         }
1881
1882         system_dn = samdb_search_dn(sam_ctx, mem_ctx,
1883                                     ldb_get_default_basedn(sam_ctx),
1884                                     "(&(objectClass=container)(cn=System))");
1885         if (!system_dn) {
1886                 return WERR_GENERAL_FAILURE;
1887         }
1888
1889         ret = gendb_search(sam_ctx, mem_ctx, system_dn,
1890                            &dom_res, trust_attrs,
1891                            "(objectclass=trustedDomain)");
1892
1893         for (i = 0; i < ret; i++) {
1894                 unsigned int trust_dir;
1895                 uint32_t flags = 0;
1896
1897                 trust_dir = samdb_result_uint(dom_res[i],
1898                                               "trustDirection", 0);
1899
1900                 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
1901                         flags |= NETR_TRUST_FLAG_INBOUND;
1902                 }
1903                 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
1904                         flags |= NETR_TRUST_FLAG_OUTBOUND;
1905                 }
1906
1907                 if (!(flags & trust_flags)) {
1908                         /* this trust direction was not requested */
1909                         continue;
1910                 }
1911
1912                 n = trusts->count;
1913                 trusts->array = talloc_realloc(trusts, trusts->array,
1914                                                struct netr_DomainTrust,
1915                                                n + 1);
1916                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1917
1918                 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
1919                               dom_res[i], "flatname");
1920                 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
1921                               dom_res[i], "trustPartner");
1922
1923                 trusts->array[n].trust_flags = flags;
1924                 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
1925                     !(flags & NETR_TRUST_FLAG_TREEROOT)) {
1926                         /* TODO: find if we have parent in the list */
1927                         trusts->array[n].parent_index = 0;
1928                 }
1929
1930                 trusts->array[n].trust_type =
1931                                 samdb_result_uint(dom_res[i],
1932                                                   "trustType", 0);
1933                 trusts->array[n].trust_attributes =
1934                                 samdb_result_uint(dom_res[i],
1935                                                   "trustAttributes", 0);
1936
1937                 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
1938                     (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
1939                         struct dom_sid zero_sid;
1940                         ZERO_STRUCT(zero_sid);
1941                         trusts->array[n].sid =
1942                                 dom_sid_dup(trusts, &zero_sid);
1943                 } else {
1944                         trusts->array[n].sid =
1945                                 samdb_result_dom_sid(trusts, dom_res[i],
1946                                                      "securityIdentifier");
1947                 }
1948                 trusts->array[n].guid = GUID_zero();
1949
1950                 trusts->count = n + 1;
1951         }
1952
1953         talloc_free(dom_res);
1954         return WERR_OK;
1955 }
1956
1957 /*
1958   netr_DsrEnumerateDomainTrusts
1959 */
1960 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
1961                                                    TALLOC_CTX *mem_ctx,
1962                                                    struct netr_DsrEnumerateDomainTrusts *r)
1963 {
1964         struct netr_DomainTrustList *trusts;
1965         struct ldb_context *sam_ctx;
1966         int ret;
1967         struct ldb_message **dom_res;
1968         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1969         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1970         const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
1971         const char *p;
1972         WERROR werr;
1973
1974         if (r->in.trust_flags & 0xFFFFFE00) {
1975                 return WERR_INVALID_FLAGS;
1976         }
1977
1978         /* TODO: turn to hard check once we are sure this is 100% correct */
1979         if (!r->in.server_name) {
1980                 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
1981                           "But received NULL!\n", dnsdomain));
1982         } else {
1983                 p = strchr(r->in.server_name, '.');
1984                 if (!p) {
1985                         DEBUG(3, ("Invalid domain! Expected name in domain "
1986                                   "[%s]. But received [%s]!\n",
1987                                   dnsdomain, r->in.server_name));
1988                         p = r->in.server_name;
1989                 } else {
1990                         p++;
1991                 }
1992                 if (strcasecmp(p, dnsdomain)) {
1993                         DEBUG(3, ("Invalid domain! Expected name in domain "
1994                                   "[%s]. But received [%s]!\n",
1995                                   dnsdomain, r->in.server_name));
1996                 }
1997         }
1998
1999         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2000         W_ERROR_HAVE_NO_MEMORY(trusts);
2001
2002         trusts->count = 0;
2003         r->out.trusts = trusts;
2004
2005         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2006                                 dce_call->conn->auth_state.session_info, 0);
2007         if (sam_ctx == NULL) {
2008                 return WERR_GENERAL_FAILURE;
2009         }
2010
2011         if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2012             (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2013
2014                 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2015                                                   trusts, r->in.trust_flags);
2016                 W_ERROR_NOT_OK_RETURN(werr);
2017         }
2018
2019         /* NOTE: we currently are always the root of the forest */
2020         if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2021                 uint32_t n = trusts->count;
2022
2023                 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2024                                       &dom_res, dom_attrs);
2025                 if (ret != 1) {
2026                         return WERR_GENERAL_FAILURE;
2027                 }
2028
2029                 trusts->count = n + 1;
2030                 trusts->array = talloc_realloc(trusts, trusts->array,
2031                                                struct netr_DomainTrust,
2032                                                trusts->count);
2033                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2034
2035                 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2036                 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2037                 trusts->array[n].trust_flags =
2038                         NETR_TRUST_FLAG_NATIVE |
2039                         NETR_TRUST_FLAG_TREEROOT |
2040                         NETR_TRUST_FLAG_IN_FOREST |
2041                         NETR_TRUST_FLAG_PRIMARY;
2042                 /* we are always the root domain for now */
2043                 trusts->array[n].parent_index = 0;
2044                 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2045                 trusts->array[n].trust_attributes = 0;
2046                 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2047                                                             dom_res[0],
2048                                                             "objectSid");
2049                 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2050                                                           "objectGUID");
2051                 talloc_free(dom_res);
2052         }
2053
2054         return WERR_OK;
2055 }
2056
2057
2058 /*
2059   netr_DsrDeregisterDNSHostRecords
2060 */
2061 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2062                        struct netr_DsrDeregisterDNSHostRecords *r)
2063 {
2064         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2065 }
2066
2067
2068 /*
2069   netr_ServerTrustPasswordsGet
2070 */
2071 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2072                        struct netr_ServerTrustPasswordsGet *r)
2073 {
2074         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2075 }
2076
2077
2078 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2079                                       struct ldb_context *sam_ctx,
2080                                       struct loadparm_context *lp_ctx,
2081                                       struct lsa_ForestTrustInformation *info)
2082 {
2083         struct lsa_ForestTrustDomainInfo *domain_info;
2084         struct lsa_ForestTrustRecord *e;
2085         struct ldb_message **dom_res;
2086         const char * const dom_attrs[] = { "objectSid", NULL };
2087         int ret;
2088
2089         /* we need to provide 2 entries:
2090          * 1. the Root Forest name
2091          * 2. the Domain Information
2092          */
2093
2094         info->count = 2;
2095         info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2096         W_ERROR_HAVE_NO_MEMORY(info->entries);
2097
2098         /* Forest root info */
2099         e = talloc(info, struct lsa_ForestTrustRecord);
2100         W_ERROR_HAVE_NO_MEMORY(e);
2101
2102         e->flags = 0;
2103         e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2104         e->time = 0; /* so far always 0 in trces. */
2105         e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2106                                                                        mem_ctx);
2107         W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2108
2109         info->entries[0] = e;
2110
2111         /* Domain info */
2112         e = talloc(info, struct lsa_ForestTrustRecord);
2113         W_ERROR_HAVE_NO_MEMORY(e);
2114
2115         /* get our own domain info */
2116         ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2117         if (ret != 1) {
2118                 return WERR_GENERAL_FAILURE;
2119         }
2120
2121         /* TODO: check if disabled and set flags accordingly */
2122         e->flags = 0;
2123         e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2124         e->time = 0; /* so far always 0 in traces. */
2125
2126         domain_info = &e->forest_trust_data.domain_info;
2127         domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2128                                                        "objectSid");
2129         domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2130         domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2131
2132         info->entries[1] = e;
2133
2134         talloc_free(dom_res);
2135
2136         return WERR_OK;
2137 }
2138
2139 /*
2140   netr_DsRGetForestTrustInformation
2141 */
2142 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2143                                                        TALLOC_CTX *mem_ctx,
2144                                                        struct netr_DsRGetForestTrustInformation *r)
2145 {
2146         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2147         struct lsa_ForestTrustInformation *info, **info_ptr;
2148         struct ldb_context *sam_ctx;
2149         WERROR werr;
2150
2151         if (r->in.flags & 0xFFFFFFFE) {
2152                 return WERR_INVALID_FLAGS;
2153         }
2154
2155         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2156                                 dce_call->conn->auth_state.session_info, 0);
2157         if (sam_ctx == NULL) {
2158                 return WERR_GENERAL_FAILURE;
2159         }
2160
2161         if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2162                 if (!samdb_is_pdc(sam_ctx)) {
2163                         return WERR_NERR_NOTPRIMARY;
2164                 }
2165
2166                 if (r->in.trusted_domain_name == NULL) {
2167                         return WERR_INVALID_FLAGS;
2168                 }
2169
2170                 /* TODO: establish an schannel connection with
2171                  * r->in.trusted_domain_name and perform a
2172                  * netr_GetForestTrustInformation call against it */
2173
2174                 /* for now return not implementd */
2175                 return WERR_CALL_NOT_IMPLEMENTED;
2176         }
2177
2178         /* TODO: check r->in.server_name is our name */
2179
2180         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2181         W_ERROR_HAVE_NO_MEMORY(info_ptr);
2182
2183         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2184         W_ERROR_HAVE_NO_MEMORY(info);
2185
2186         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2187         W_ERROR_NOT_OK_RETURN(werr);
2188
2189         *info_ptr = info;
2190         r->out.forest_trust_info = info_ptr;
2191
2192         return WERR_OK;
2193 }
2194
2195
2196 /*
2197   netr_GetForestTrustInformation
2198 */
2199 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2200                                                       TALLOC_CTX *mem_ctx,
2201                                                       struct netr_GetForestTrustInformation *r)
2202 {
2203         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2204         struct netlogon_creds_CredentialState *creds;
2205         struct lsa_ForestTrustInformation *info, **info_ptr;
2206         struct ldb_context *sam_ctx;
2207         NTSTATUS status;
2208         WERROR werr;
2209
2210         status = dcesrv_netr_creds_server_step_check(dce_call,
2211                                                      mem_ctx,
2212                                                      r->in.computer_name,
2213                                                      r->in.credential,
2214                                                      r->out.return_authenticator,
2215                                                      &creds);
2216         if (!NT_STATUS_IS_OK(status)) {
2217                 return status;
2218         }
2219
2220         if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2221             (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2222                 return NT_STATUS_NOT_IMPLEMENTED;
2223         }
2224
2225         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2226                                 dce_call->conn->auth_state.session_info, 0);
2227         if (sam_ctx == NULL) {
2228                 return NT_STATUS_UNSUCCESSFUL;
2229         }
2230
2231         /* TODO: check r->in.server_name is our name */
2232
2233         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2234         if (!info_ptr) {
2235                 return NT_STATUS_NO_MEMORY;
2236         }
2237         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2238         if (!info) {
2239                 return NT_STATUS_NO_MEMORY;
2240         }
2241
2242         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2243         if (!W_ERROR_IS_OK(werr)) {
2244                 return werror_to_ntstatus(werr);
2245         }
2246
2247         *info_ptr = info;
2248         r->out.forest_trust_info = info_ptr;
2249
2250         return NT_STATUS_OK;
2251 }
2252
2253
2254 /*
2255   netr_ServerGetTrustInfo
2256 */
2257 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2258                        struct netr_ServerGetTrustInfo *r)
2259 {
2260         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2261 }
2262
2263 /*
2264   netr_Unused47
2265 */
2266 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2267                                      struct netr_Unused47 *r)
2268 {
2269         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2270 }
2271
2272
2273 struct netr_dnsupdate_RODC_state {
2274         struct dcesrv_call_state *dce_call;
2275         struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2276         struct dnsupdate_RODC *r2;
2277 };
2278
2279 /*
2280   called when the forwarded RODC dns update request is finished
2281  */
2282 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2283 {
2284         struct netr_dnsupdate_RODC_state *st =
2285                 tevent_req_callback_data(subreq,
2286                                          struct netr_dnsupdate_RODC_state);
2287         NTSTATUS status;
2288
2289         status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2290         TALLOC_FREE(subreq);
2291         if (!NT_STATUS_IS_OK(status)) {
2292                 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2293                 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2294         }
2295
2296         st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2297
2298         status = dcesrv_reply(st->dce_call);
2299         if (!NT_STATUS_IS_OK(status)) {
2300                 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2301         }
2302 }
2303
2304 /*
2305   netr_DsrUpdateReadOnlyServerDnsRecords
2306 */
2307 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2308                                                               TALLOC_CTX *mem_ctx,
2309                                                               struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2310 {
2311         struct netlogon_creds_CredentialState *creds;
2312         NTSTATUS nt_status;
2313         struct dcerpc_binding_handle *binding_handle;
2314         struct netr_dnsupdate_RODC_state *st;
2315         struct tevent_req *subreq;
2316
2317         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2318                                                         mem_ctx,
2319                                                         r->in.computer_name,
2320                                                         r->in.credential,
2321                                                         r->out.return_authenticator,
2322                                                         &creds);
2323         NT_STATUS_NOT_OK_RETURN(nt_status);
2324
2325         if (creds->secure_channel_type != SEC_CHAN_RODC) {
2326                 return NT_STATUS_ACCESS_DENIED;
2327         }
2328
2329         st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2330         NT_STATUS_HAVE_NO_MEMORY(st);
2331
2332         st->dce_call = dce_call;
2333         st->r = r;
2334         st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2335         NT_STATUS_HAVE_NO_MEMORY(st->r2);
2336
2337         st->r2->in.dom_sid = creds->sid;
2338         st->r2->in.site_name = r->in.site_name;
2339         st->r2->in.dns_ttl = r->in.dns_ttl;
2340         st->r2->in.dns_names = r->in.dns_names;
2341         st->r2->out.dns_names = r->out.dns_names;
2342
2343         binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2344                                                      "dnsupdate", &ndr_table_irpc);
2345         if (binding_handle == NULL) {
2346                 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2347                 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2348                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2349         }
2350
2351         /* forward the call */
2352         subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2353                                               binding_handle, st->r2);
2354         NT_STATUS_HAVE_NO_MEMORY(subreq);
2355
2356         dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2357
2358         /* setup the callback */
2359         tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2360
2361         return NT_STATUS_OK;
2362 }
2363
2364
2365 /* include the generated boilerplate */
2366 #include "librpc/gen_ndr/ndr_netlogon_s.c"