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