50e7cab7ff14df560fb0e1a2b47af29f52b9d9c5
[mat/samba.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    endpoint server for the netlogon pipe
5
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
7    Copyright (C) Stefan Metzmacher <metze@samba.org>  2005
8    Copyright (C) Matthias Dieter Wallnöfer            2009-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                         status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
751                                                                      mem_ctx,
752                                                                      &check);
753                         if (!NT_STATUS_IS_OK(status)) {
754                                 return status;
755                         }
756                         generic->length = check.out.generic_reply.length;
757                         generic->data = check.out.generic_reply.data;
758                         return NT_STATUS_OK;
759                 }
760
761                 /* Until we get an implemetnation of these other packages */
762                 return NT_STATUS_INVALID_PARAMETER;
763         }
764         default:
765                 return NT_STATUS_INVALID_PARAMETER;
766         }
767
768         nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
769         /* TODO: set *r->out.authoritative = 0 on specific errors */
770         NT_STATUS_NOT_OK_RETURN(nt_status);
771
772         switch (r->in.validation_level) {
773         case 2:
774                 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
775                 NT_STATUS_NOT_OK_RETURN(nt_status);
776
777                 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
778                 NT_STATUS_HAVE_NO_MEMORY(sam2);
779                 sam2->base = *sam;
780
781                 /* And put into the talloc tree */
782                 talloc_steal(sam2, sam);
783                 r->out.validation->sam2 = sam2;
784
785                 sam = &sam2->base;
786                 break;
787
788         case 3:
789                 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
790                                                               user_info_dc,
791                                                               &sam3);
792                 NT_STATUS_NOT_OK_RETURN(nt_status);
793
794                 r->out.validation->sam3 = sam3;
795
796                 sam = &sam3->base;
797                 break;
798
799         case 6:
800                 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
801                                                            user_info_dc,
802                                                            &sam3);
803                 NT_STATUS_NOT_OK_RETURN(nt_status);
804
805                 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
806                 NT_STATUS_HAVE_NO_MEMORY(sam6);
807                 sam6->base = sam3->base;
808                 sam = &sam6->base;
809                 sam6->sidcount = sam3->sidcount;
810                 sam6->sids = sam3->sids;
811
812                 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
813                 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
814                                                          sam->account_name.string, sam6->dns_domainname.string);
815                 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
816                 /* And put into the talloc tree */
817                 talloc_steal(sam6, sam3);
818
819                 r->out.validation->sam6 = sam6;
820                 break;
821
822         default:
823                 return NT_STATUS_INVALID_INFO_CLASS;
824         }
825
826         netlogon_creds_encrypt_samlogon_validation(creds,
827                                                    r->in.validation_level,
828                                                    r->out.validation);
829
830         /* TODO: Describe and deal with these flags */
831         *r->out.flags = 0;
832
833         return NT_STATUS_OK;
834 }
835
836 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
837                                      struct netr_LogonSamLogonEx *r)
838 {
839         NTSTATUS nt_status;
840         struct netlogon_creds_CredentialState *creds;
841
842         *r->out.authoritative = 1;
843
844         nt_status = dcesrv_netr_LogonSamLogon_check(r);
845         if (!NT_STATUS_IS_OK(nt_status)) {
846                 return nt_status;
847         }
848
849         nt_status = schannel_get_creds_state(mem_ctx,
850                                              dce_call->conn->dce_ctx->lp_ctx,
851                                              r->in.computer_name, &creds);
852         if (!NT_STATUS_IS_OK(nt_status)) {
853                 return nt_status;
854         }
855
856         if (!dce_call->conn->auth_state.auth_info ||
857             dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
858                 return NT_STATUS_ACCESS_DENIED;
859         }
860         return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
861 }
862
863 /*
864   netr_LogonSamLogonWithFlags
865
866 */
867 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
868                                             struct netr_LogonSamLogonWithFlags *r)
869 {
870         NTSTATUS nt_status;
871         struct netlogon_creds_CredentialState *creds;
872         struct netr_LogonSamLogonEx r2;
873
874         struct netr_Authenticator *return_authenticator;
875
876         ZERO_STRUCT(r2);
877
878         r2.in.server_name       = r->in.server_name;
879         r2.in.computer_name     = r->in.computer_name;
880         r2.in.logon_level       = r->in.logon_level;
881         r2.in.logon             = r->in.logon;
882         r2.in.validation_level  = r->in.validation_level;
883         r2.in.flags             = r->in.flags;
884         r2.out.validation       = r->out.validation;
885         r2.out.authoritative    = r->out.authoritative;
886         r2.out.flags            = r->out.flags;
887
888         *r->out.authoritative = 1;
889
890         nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
891         if (!NT_STATUS_IS_OK(nt_status)) {
892                 return nt_status;
893         }
894
895         return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
896         NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
897
898         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
899                                                         mem_ctx,
900                                                         r->in.computer_name,
901                                                         r->in.credential, return_authenticator,
902                                                         &creds);
903         NT_STATUS_NOT_OK_RETURN(nt_status);
904
905         nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
906
907         r->out.return_authenticator     = return_authenticator;
908
909         return nt_status;
910 }
911
912 /*
913   netr_LogonSamLogon
914 */
915 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
916                                    struct netr_LogonSamLogon *r)
917 {
918         struct netr_LogonSamLogonWithFlags r2;
919         uint32_t flags = 0;
920         NTSTATUS status;
921
922         ZERO_STRUCT(r2);
923
924         r2.in.server_name = r->in.server_name;
925         r2.in.computer_name = r->in.computer_name;
926         r2.in.credential  = r->in.credential;
927         r2.in.return_authenticator = r->in.return_authenticator;
928         r2.in.logon_level = r->in.logon_level;
929         r2.in.logon = r->in.logon;
930         r2.in.validation_level = r->in.validation_level;
931         r2.in.flags = &flags;
932         r2.out.validation = r->out.validation;
933         r2.out.authoritative = r->out.authoritative;
934         r2.out.flags = &flags;
935
936         status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
937
938         r->out.return_authenticator = r2.out.return_authenticator;
939
940         return status;
941 }
942
943
944 /*
945   netr_LogonSamLogoff
946 */
947 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
948                        struct netr_LogonSamLogoff *r)
949 {
950         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
951 }
952
953
954
955 /*
956   netr_DatabaseDeltas
957 */
958 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
959                        struct netr_DatabaseDeltas *r)
960 {
961         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
962 }
963
964
965 /*
966   netr_DatabaseSync2
967 */
968 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
969                        struct netr_DatabaseSync2 *r)
970 {
971         /* win2k3 native mode returns  "NOT IMPLEMENTED" for this call */
972         return NT_STATUS_NOT_IMPLEMENTED;
973 }
974
975
976 /*
977   netr_DatabaseSync
978 */
979 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
980                        struct netr_DatabaseSync *r)
981 {
982         struct netr_DatabaseSync2 r2;
983         NTSTATUS status;
984
985         ZERO_STRUCT(r2);
986
987         r2.in.logon_server = r->in.logon_server;
988         r2.in.computername = r->in.computername;
989         r2.in.credential = r->in.credential;
990         r2.in.database_id = r->in.database_id;
991         r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
992         r2.in.sync_context = r->in.sync_context;
993         r2.out.sync_context = r->out.sync_context;
994         r2.out.delta_enum_array = r->out.delta_enum_array;
995         r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
996
997         status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
998
999         return status;
1000 }
1001
1002
1003 /*
1004   netr_AccountDeltas
1005 */
1006 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1007                        struct netr_AccountDeltas *r)
1008 {
1009         /* w2k3 returns "NOT IMPLEMENTED" for this call */
1010         return NT_STATUS_NOT_IMPLEMENTED;
1011 }
1012
1013
1014 /*
1015   netr_AccountSync
1016 */
1017 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1018                        struct netr_AccountSync *r)
1019 {
1020         /* w2k3 returns "NOT IMPLEMENTED" for this call */
1021         return NT_STATUS_NOT_IMPLEMENTED;
1022 }
1023
1024
1025 /*
1026   netr_GetDcName
1027 */
1028 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1029                        struct netr_GetDcName *r)
1030 {
1031         const char * const attrs[] = { NULL };
1032         struct ldb_context *sam_ctx;
1033         struct ldb_message **res;
1034         struct ldb_dn *domain_dn;
1035         int ret;
1036         const char *dcname;
1037
1038         /*
1039          * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1040          * that the domainname needs to be a valid netbios domain
1041          * name, if it is not NULL.
1042          */
1043         if (r->in.domainname) {
1044                 const char *dot = strchr(r->in.domainname, '.');
1045                 size_t len = strlen(r->in.domainname);
1046
1047                 if (dot || len > 15) {
1048                         return WERR_DCNOTFOUND;
1049                 }
1050
1051                 /*
1052                  * TODO: Should we also varify that only valid
1053                  *       netbios name characters are used?
1054                  */
1055         }
1056
1057         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1058                                 dce_call->conn->dce_ctx->lp_ctx,
1059                                 dce_call->conn->auth_state.session_info, 0);
1060         if (sam_ctx == NULL) {
1061                 return WERR_DS_UNAVAILABLE;
1062         }
1063
1064         domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1065                                        r->in.domainname);
1066         if (domain_dn == NULL) {
1067                 return WERR_NO_SUCH_DOMAIN;
1068         }
1069
1070         ret = gendb_search_dn(sam_ctx, mem_ctx,
1071                               domain_dn, &res, attrs);
1072         if (ret != 1) {
1073                 return WERR_NO_SUCH_DOMAIN;
1074         }
1075
1076         /* TODO: - return real IP address
1077          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
1078          */
1079         dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1080                                  lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1081         W_ERROR_HAVE_NO_MEMORY(dcname);
1082
1083         *r->out.dcname = dcname;
1084         return WERR_OK;
1085 }
1086
1087
1088 /*
1089   netr_LogonControl2Ex
1090 */
1091 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1092                        struct netr_LogonControl2Ex *r)
1093 {
1094         return WERR_NOT_SUPPORTED;
1095 }
1096
1097
1098 /*
1099   netr_LogonControl
1100 */
1101 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1102                        struct netr_LogonControl *r)
1103 {
1104         struct netr_LogonControl2Ex r2;
1105         WERROR werr;
1106
1107         if (r->in.level == 0x00000001) {
1108                 ZERO_STRUCT(r2);
1109
1110                 r2.in.logon_server = r->in.logon_server;
1111                 r2.in.function_code = r->in.function_code;
1112                 r2.in.level = r->in.level;
1113                 r2.in.data = NULL;
1114                 r2.out.query = r->out.query;
1115
1116                 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1117         } else if (r->in.level == 0x00000002) {
1118                 werr = WERR_NOT_SUPPORTED;
1119         } else {
1120                 werr = WERR_UNKNOWN_LEVEL;
1121         }
1122
1123         return werr;
1124 }
1125
1126
1127 /*
1128   netr_LogonControl2
1129 */
1130 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1131                        struct netr_LogonControl2 *r)
1132 {
1133         struct netr_LogonControl2Ex r2;
1134         WERROR werr;
1135
1136         ZERO_STRUCT(r2);
1137
1138         r2.in.logon_server = r->in.logon_server;
1139         r2.in.function_code = r->in.function_code;
1140         r2.in.level = r->in.level;
1141         r2.in.data = r->in.data;
1142         r2.out.query = r->out.query;
1143
1144         werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1145
1146         return werr;
1147 }
1148
1149 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1150                                          struct ldb_context *sam_ctx,
1151                                          struct netr_DomainTrustList *trusts,
1152                                          uint32_t trust_flags);
1153
1154 /*
1155   netr_GetAnyDCName
1156 */
1157 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1158                        struct netr_GetAnyDCName *r)
1159 {
1160         struct netr_DomainTrustList *trusts;
1161         struct ldb_context *sam_ctx;
1162         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1163         uint32_t i;
1164         WERROR werr;
1165
1166         *r->out.dcname = NULL;
1167
1168         if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1169                 /* if the domainname parameter wasn't set assume our domain */
1170                 r->in.domainname = lpcfg_workgroup(lp_ctx);
1171         }
1172
1173         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1174                                 dce_call->conn->auth_state.session_info, 0);
1175         if (sam_ctx == NULL) {
1176                 return WERR_DS_UNAVAILABLE;
1177         }
1178
1179         if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1180                 /* well we asked for a DC of our own domain */
1181                 if (samdb_is_pdc(sam_ctx)) {
1182                         /* we are the PDC of the specified domain */
1183                         return WERR_NO_SUCH_DOMAIN;
1184                 }
1185
1186                 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1187                                                 lpcfg_netbios_name(lp_ctx));
1188                 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1189
1190                 return WERR_OK;
1191         }
1192
1193         /* Okay, now we have to consider the trusted domains */
1194
1195         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1196         W_ERROR_HAVE_NO_MEMORY(trusts);
1197
1198         trusts->count = 0;
1199
1200         werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1201                                           NETR_TRUST_FLAG_INBOUND
1202                                           | NETR_TRUST_FLAG_OUTBOUND);
1203         W_ERROR_NOT_OK_RETURN(werr);
1204
1205         for (i = 0; i < trusts->count; i++) {
1206                 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1207                         /* FIXME: Here we need to find a DC for the specified
1208                          * trusted domain. */
1209
1210                         /* return WERR_OK; */
1211                         return WERR_NO_SUCH_DOMAIN;
1212                 }
1213         }
1214
1215         return WERR_NO_SUCH_DOMAIN;
1216 }
1217
1218
1219 /*
1220   netr_DatabaseRedo
1221 */
1222 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1223                        struct netr_DatabaseRedo *r)
1224 {
1225         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1226 }
1227
1228
1229 /*
1230   netr_NetrEnumerateTrustedDomains
1231 */
1232 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1233                        struct netr_NetrEnumerateTrustedDomains *r)
1234 {
1235         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1236 }
1237
1238
1239 /*
1240   netr_LogonGetCapabilities
1241 */
1242 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1243                        struct netr_LogonGetCapabilities *r)
1244 {
1245         struct netlogon_creds_CredentialState *creds;
1246         NTSTATUS status;
1247
1248         status = dcesrv_netr_creds_server_step_check(dce_call,
1249                                                      mem_ctx,
1250                                                      r->in.computer_name,
1251                                                      r->in.credential,
1252                                                      r->out.return_authenticator,
1253                                                      &creds);
1254         if (!NT_STATUS_IS_OK(status)) {
1255                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1256         }
1257         NT_STATUS_NOT_OK_RETURN(status);
1258
1259         if (r->in.query_level != 1) {
1260                 return NT_STATUS_NOT_SUPPORTED;
1261         }
1262
1263         r->out.capabilities->server_capabilities = creds->negotiate_flags;
1264
1265         return NT_STATUS_OK;
1266 }
1267
1268
1269 /*
1270   netr_NETRLOGONSETSERVICEBITS
1271 */
1272 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1273                        struct netr_NETRLOGONSETSERVICEBITS *r)
1274 {
1275         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1276 }
1277
1278
1279 /*
1280   netr_LogonGetTrustRid
1281 */
1282 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1283                        struct netr_LogonGetTrustRid *r)
1284 {
1285         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1286 }
1287
1288
1289 /*
1290   netr_NETRLOGONCOMPUTESERVERDIGEST
1291 */
1292 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1293                        struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1294 {
1295         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1296 }
1297
1298
1299 /*
1300   netr_NETRLOGONCOMPUTECLIENTDIGEST
1301 */
1302 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1303                        struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1304 {
1305         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1306 }
1307
1308
1309
1310 /*
1311   netr_DsRGetSiteName
1312 */
1313 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1314                                   struct netr_DsRGetSiteName *r)
1315 {
1316         struct ldb_context *sam_ctx;
1317         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1318
1319         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1320                                 dce_call->conn->auth_state.session_info, 0);
1321         if (sam_ctx == NULL) {
1322                 return WERR_DS_UNAVAILABLE;
1323         }
1324
1325         /*
1326          * We assume to be a DC when we get called over NETLOGON. Hence we
1327          * get our site name always by using "samdb_server_site_name()"
1328          * and not "samdb_client_site_name()".
1329          */
1330         *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1331         W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1332
1333         return WERR_OK;
1334 }
1335
1336
1337 /*
1338   fill in a netr_OneDomainInfo from a ldb search result
1339 */
1340 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1341                                      struct loadparm_context *lp_ctx,
1342                                      struct ldb_context *sam_ctx,
1343                                      struct ldb_message *res,
1344                                      struct netr_OneDomainInfo *info,
1345                                      bool is_local, bool is_trust_list)
1346 {
1347         ZERO_STRUCTP(info);
1348
1349         if (is_trust_list) {
1350                 /* w2k8 only fills this on trusted domains */
1351                 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1352                 info->trust_extension.length = 16;
1353                 info->trust_extension.info->flags =
1354                         NETR_TRUST_FLAG_TREEROOT |
1355                         NETR_TRUST_FLAG_IN_FOREST |
1356                         NETR_TRUST_FLAG_PRIMARY |
1357                         NETR_TRUST_FLAG_NATIVE;
1358
1359                 info->trust_extension.info->parent_index = 0; /* should be index into array
1360                                                                  of parent */
1361                 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1362                 info->trust_extension.info->trust_attributes = 0; /*    TODO: base on ldb search? */
1363         }
1364
1365         if (is_trust_list) {
1366                 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1367                 info->dns_forestname.string = NULL;
1368         } else {
1369                 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1370                 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1371                 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1372                 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1373         }
1374
1375         if (is_local) {
1376                 info->domainname.string = lpcfg_workgroup(lp_ctx);
1377                 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1378                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1379                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1380         } else {
1381                 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1382                 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1383                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1384                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1385         }
1386         if (!is_trust_list) {
1387                 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1388         }
1389
1390         return NT_STATUS_OK;
1391 }
1392
1393 /*
1394   netr_LogonGetDomainInfo
1395   this is called as part of the ADS domain logon procedure.
1396
1397   It has an important role in convaying details about the client, such
1398   as Operating System, Version, Service Pack etc.
1399 */
1400 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1401         TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1402 {
1403         struct netlogon_creds_CredentialState *creds;
1404         const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1405                 "securityIdentifier", "trustPartner", NULL };
1406         const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1407                 "msDS-SupportedEncryptionTypes", NULL };
1408         const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1409         struct ldb_context *sam_ctx;
1410         struct ldb_message **res1, **res2, **res3, *new_msg;
1411         struct ldb_dn *workstation_dn;
1412         struct netr_DomainInformation *domain_info;
1413         struct netr_LsaPolicyInformation *lsa_policy_info;
1414         uint32_t default_supported_enc_types = 0xFFFFFFFF;
1415         bool update_dns_hostname = true;
1416         int ret, ret3, i;
1417         NTSTATUS status;
1418
1419         status = dcesrv_netr_creds_server_step_check(dce_call,
1420                                                      mem_ctx,
1421                                                      r->in.computer_name,
1422                                                      r->in.credential,
1423                                                      r->out.return_authenticator,
1424                                                      &creds);
1425         if (!NT_STATUS_IS_OK(status)) {
1426                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1427         }
1428         NT_STATUS_NOT_OK_RETURN(status);
1429
1430         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1431                                 dce_call->conn->dce_ctx->lp_ctx,
1432                                 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1433         if (sam_ctx == NULL) {
1434                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1435         }
1436
1437         switch (r->in.level) {
1438         case 1: /* Domain information */
1439
1440                 if (r->in.query->workstation_info == NULL) {
1441                         return NT_STATUS_INVALID_PARAMETER;
1442                 }
1443
1444                 /* Prepares the workstation DN */
1445                 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1446                                                 dom_sid_string(mem_ctx, creds->sid));
1447                 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1448
1449                 /* Lookup for attributes in workstation object */
1450                 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1451                                       attrs2);
1452                 if (ret != 1) {
1453                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1454                 }
1455
1456                 /* Gets the sam account name which is checked against the DNS
1457                  * hostname parameter. */
1458                 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1459                                                                "sAMAccountName",
1460                                                                NULL);
1461                 if (sam_account_name == NULL) {
1462                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1463                 }
1464
1465                 /*
1466                  * Checks that the sam account name without a possible "$"
1467                  * matches as prefix with the DNS hostname in the workstation
1468                  * info structure.
1469                  */
1470                 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1471                                          strcspn(sam_account_name, "$"));
1472                 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1473                 if (r->in.query->workstation_info->dns_hostname != NULL) {
1474                         prefix2 = talloc_strndup(mem_ctx,
1475                                                  r->in.query->workstation_info->dns_hostname,
1476                                                  strcspn(r->in.query->workstation_info->dns_hostname, "."));
1477                         NT_STATUS_HAVE_NO_MEMORY(prefix2);
1478
1479                         if (strcasecmp(prefix1, prefix2) != 0) {
1480                                 update_dns_hostname = false;
1481                         }
1482                 } else {
1483                         update_dns_hostname = false;
1484                 }
1485
1486                 /* Gets the old DNS hostname */
1487                 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1488                                                                "dNSHostName",
1489                                                                NULL);
1490
1491                 /*
1492                  * Updates the DNS hostname when the client wishes that the
1493                  * server should handle this for him
1494                  * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1495                  * obviously only checked when we do already have a
1496                  * "dNSHostName".
1497                  * See MS-NRPC section 3.5.4.3.9
1498                  */
1499                 if ((old_dns_hostname != NULL) &&
1500                     (r->in.query->workstation_info->workstation_flags
1501                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1502                         update_dns_hostname = false;
1503                 }
1504
1505                 /* Gets host information and put them into our directory */
1506
1507                 new_msg = ldb_msg_new(mem_ctx);
1508                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1509
1510                 new_msg->dn = workstation_dn;
1511
1512                 /* Sets the OS name */
1513
1514                 if (r->in.query->workstation_info->os_name.string == NULL) {
1515                         return NT_STATUS_INVALID_PARAMETER;
1516                 }
1517
1518                 ret = ldb_msg_add_string(new_msg, "operatingSystem",
1519                                          r->in.query->workstation_info->os_name.string);
1520                 if (ret != LDB_SUCCESS) {
1521                         return NT_STATUS_NO_MEMORY;
1522                 }
1523
1524                 /*
1525                  * Sets information from "os_version". On an empty structure
1526                  * the values are cleared.
1527                  */
1528                 if (r->in.query->workstation_info->os_version.os != NULL) {
1529                         struct netr_OsVersionInfoEx *os_version;
1530                         const char *os_version_str;
1531
1532                         os_version = &r->in.query->workstation_info->os_version.os->os;
1533
1534                         if (os_version->CSDVersion == NULL) {
1535                                 return NT_STATUS_INVALID_PARAMETER;
1536                         }
1537
1538                         os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
1539                                                          os_version->MajorVersion,
1540                                                          os_version->MinorVersion,
1541                                                          os_version->BuildNumber);
1542                         NT_STATUS_HAVE_NO_MEMORY(os_version_str);
1543
1544                         ret = ldb_msg_add_string(new_msg,
1545                                                  "operatingSystemServicePack",
1546                                                  os_version->CSDVersion);
1547                         if (ret != LDB_SUCCESS) {
1548                                 return NT_STATUS_NO_MEMORY;
1549                         }
1550
1551                         ret = ldb_msg_add_string(new_msg,
1552                                                  "operatingSystemVersion",
1553                                                  os_version_str);
1554                         if (ret != LDB_SUCCESS) {
1555                                 return NT_STATUS_NO_MEMORY;
1556                         }
1557                 } else {
1558                         ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1559                                                    "operatingSystemServicePack");
1560                         if (ret != LDB_SUCCESS) {
1561                                 return NT_STATUS_NO_MEMORY;
1562                         }
1563
1564                         ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1565                                                    "operatingSystemVersion");
1566                         if (ret != LDB_SUCCESS) {
1567                                 return NT_STATUS_NO_MEMORY;
1568                         }
1569                 }
1570
1571                 /*
1572                  * If the boolean "update_dns_hostname" remained true, then we
1573                  * are fine to start the update.
1574                  */
1575                 if (update_dns_hostname) {
1576                         ret = ldb_msg_add_string(new_msg,
1577                                                  "dNSHostname",
1578                                                  r->in.query->workstation_info->dns_hostname);
1579                         if (ret != LDB_SUCCESS) {
1580                                 return NT_STATUS_NO_MEMORY;
1581                         }
1582
1583                         /* This manual "servicePrincipalName" generation is
1584                          * still needed! Since the update in the samldb LDB
1585                          * module does only work if the entries already exist
1586                          * which isn't always the case. */
1587                         ret = ldb_msg_add_string(new_msg,
1588                                                  "servicePrincipalName",
1589                                                  talloc_asprintf(new_msg, "HOST/%s",
1590                                                  r->in.computer_name));
1591                         if (ret != LDB_SUCCESS) {
1592                                 return NT_STATUS_NO_MEMORY;
1593                         }
1594
1595                         ret = ldb_msg_add_string(new_msg,
1596                                                  "servicePrincipalName",
1597                                                  talloc_asprintf(new_msg, "HOST/%s",
1598                                                  r->in.query->workstation_info->dns_hostname));
1599                         if (ret != LDB_SUCCESS) {
1600                                 return NT_STATUS_NO_MEMORY;
1601                         }
1602                 }
1603
1604                 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1605                         DEBUG(3,("Impossible to update samdb: %s\n",
1606                                 ldb_errstring(sam_ctx)));
1607                 }
1608
1609                 talloc_free(new_msg);
1610
1611                 /* Writes back the domain information */
1612
1613                 /* We need to do two searches. The first will pull our primary
1614                    domain and the second will pull any trusted domains. Our
1615                    primary domain is also a "trusted" domain, so we need to
1616                    put the primary domain into the lists of returned trusts as
1617                    well. */
1618                 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1619                         &res2, attrs);
1620                 if (ret != 1) {
1621                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1622                 }
1623
1624                 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1625                         "(objectClass=trustedDomain)");
1626                 if (ret3 == -1) {
1627                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1628                 }
1629
1630                 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1631                 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1632
1633                 ZERO_STRUCTP(domain_info);
1634
1635                 /* Informations about the local and trusted domains */
1636
1637                 status = fill_one_domain_info(mem_ctx,
1638                         dce_call->conn->dce_ctx->lp_ctx,
1639                         sam_ctx, res2[0], &domain_info->primary_domain,
1640                         true, false);
1641                 NT_STATUS_NOT_OK_RETURN(status);
1642
1643                 domain_info->trusted_domain_count = ret3 + 1;
1644                 domain_info->trusted_domains = talloc_array(mem_ctx,
1645                         struct netr_OneDomainInfo,
1646                         domain_info->trusted_domain_count);
1647                 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1648
1649                 for (i=0;i<ret3;i++) {
1650                         status = fill_one_domain_info(mem_ctx,
1651                                 dce_call->conn->dce_ctx->lp_ctx,
1652                                 sam_ctx, res3[i],
1653                                 &domain_info->trusted_domains[i],
1654                                 false, true);
1655                         NT_STATUS_NOT_OK_RETURN(status);
1656                 }
1657
1658                 status = fill_one_domain_info(mem_ctx,
1659                         dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1660                         &domain_info->trusted_domains[i], true, true);
1661                 NT_STATUS_NOT_OK_RETURN(status);
1662
1663                 /* Sets the supported encryption types */
1664                 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1665                         "msDS-SupportedEncryptionTypes",
1666                         default_supported_enc_types);
1667
1668                 /* Other host domain information */
1669
1670                 lsa_policy_info = talloc(mem_ctx,
1671                         struct netr_LsaPolicyInformation);
1672                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1673                 ZERO_STRUCTP(lsa_policy_info);
1674
1675                 domain_info->lsa_policy = *lsa_policy_info;
1676
1677                 /* The DNS hostname is only returned back when there is a chance
1678                  * for a change. */
1679                 if ((r->in.query->workstation_info->workstation_flags
1680                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1681                         domain_info->dns_hostname.string = old_dns_hostname;
1682                 } else {
1683                         domain_info->dns_hostname.string = NULL;
1684                 }
1685
1686                 domain_info->workstation_flags =
1687                         r->in.query->workstation_info->workstation_flags & (
1688                         NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
1689
1690                 r->out.info->domain_info = domain_info;
1691         break;
1692         case 2: /* LSA policy information - not used at the moment */
1693                 lsa_policy_info = talloc(mem_ctx,
1694                         struct netr_LsaPolicyInformation);
1695                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1696                 ZERO_STRUCTP(lsa_policy_info);
1697
1698                 r->out.info->lsa_policy_info = lsa_policy_info;
1699         break;
1700         default:
1701                 return NT_STATUS_INVALID_LEVEL;
1702         break;
1703         }
1704
1705         return NT_STATUS_OK;
1706 }
1707
1708
1709 /*
1710   netr_ServerPasswordGet
1711 */
1712 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1713                        struct netr_ServerPasswordGet *r)
1714 {
1715         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1716 }
1717
1718
1719 /*
1720   netr_NETRLOGONSENDTOSAM
1721 */
1722 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1723                        struct netr_NETRLOGONSENDTOSAM *r)
1724 {
1725         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1726 }
1727
1728
1729 /*
1730   netr_DsRGetDCNameEx2
1731 */
1732 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1733                                           TALLOC_CTX *mem_ctx,
1734                                           struct netr_DsRGetDCNameEx2 *r)
1735 {
1736         struct ldb_context *sam_ctx;
1737         struct netr_DsRGetDCNameInfo *info;
1738         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1739         const struct tsocket_address *remote_address;
1740         char *addr = NULL;
1741         const char *server_site_name;
1742         char *guid_str;
1743         struct netlogon_samlogon_response response;
1744         NTSTATUS status;
1745         const char *dc_name = NULL;
1746         const char *domain_name = NULL;
1747         struct interface *ifaces;
1748         const char *pdc_ip;
1749
1750         ZERO_STRUCTP(r->out.info);
1751
1752         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1753                                 dce_call->conn->auth_state.session_info, 0);
1754         if (sam_ctx == NULL) {
1755                 return WERR_DS_UNAVAILABLE;
1756         }
1757
1758         remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1759         if (tsocket_address_is_inet(remote_address, "ip")) {
1760                 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1761                 W_ERROR_HAVE_NO_MEMORY(addr);
1762         }
1763
1764         /* "server_unc" is ignored by w2k3 */
1765
1766         if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1767                 return WERR_INVALID_FLAGS;
1768         }
1769
1770         if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1771             r->in.flags & DS_PDC_REQUIRED &&
1772             r->in.flags & DS_KDC_REQUIRED) {
1773                 return WERR_INVALID_FLAGS;
1774         }
1775         if (r->in.flags & DS_IS_FLAT_NAME &&
1776             r->in.flags & DS_IS_DNS_NAME) {
1777                 return WERR_INVALID_FLAGS;
1778         }
1779         if (r->in.flags & DS_RETURN_DNS_NAME &&
1780             r->in.flags & DS_RETURN_FLAT_NAME) {
1781                 return WERR_INVALID_FLAGS;
1782         }
1783         if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1784             r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1785                 return WERR_INVALID_FLAGS;
1786         }
1787
1788         if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1789             r->in.flags &
1790             (DS_DIRECTORY_SERVICE_REQUIRED |
1791              DS_DIRECTORY_SERVICE_PREFERRED |
1792              DS_GC_SERVER_REQUIRED |
1793              DS_PDC_REQUIRED |
1794              DS_KDC_REQUIRED)) {
1795                 return WERR_INVALID_FLAGS;
1796         }
1797
1798         if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1799             r->in.site_name) {
1800                 return WERR_INVALID_FLAGS;
1801         }
1802
1803         /* Proof server site parameter "site_name" if it was specified */
1804         server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1805         W_ERROR_HAVE_NO_MEMORY(server_site_name);
1806         if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1807                                                      server_site_name) != 0)) {
1808                 return WERR_NO_SUCH_DOMAIN;
1809         }
1810
1811         guid_str = r->in.domain_guid != NULL ?
1812                  GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1813
1814         status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1815                                                  r->in.domain_name,
1816                                                  r->in.domain_name,
1817                                                  NULL, guid_str,
1818                                                  r->in.client_account,
1819                                                  r->in.mask, addr,
1820                                                  NETLOGON_NT_VERSION_5EX_WITH_IP,
1821                                                  lp_ctx, &response, true);
1822         if (!NT_STATUS_IS_OK(status)) {
1823                 return ntstatus_to_werror(status);
1824         }
1825
1826         /*
1827          * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
1828          * (O) flag when the returned forest name is in DNS format. This is here
1829          * always the case (see below).
1830          */
1831         response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
1832
1833         if (r->in.flags & DS_RETURN_DNS_NAME) {
1834                 dc_name = response.data.nt5_ex.pdc_dns_name;
1835                 domain_name = response.data.nt5_ex.dns_domain;
1836                 /*
1837                  * According to MS-NRPC 2.2.1.2.1 we should set the
1838                  * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
1839                  * the returned information is in DNS form.
1840                  */
1841                 response.data.nt5_ex.server_type |=
1842                         DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
1843         } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1844                 dc_name = response.data.nt5_ex.pdc_name;
1845                 domain_name = response.data.nt5_ex.domain_name;
1846         } else {
1847
1848                 /*
1849                  * TODO: autodetect what we need to return
1850                  * based on the given arguments
1851                  */
1852                 dc_name = response.data.nt5_ex.pdc_name;
1853                 domain_name = response.data.nt5_ex.domain_name;
1854         }
1855
1856         if (!dc_name || !dc_name[0]) {
1857                 return WERR_NO_SUCH_DOMAIN;
1858         }
1859
1860         if (!domain_name || !domain_name[0]) {
1861                 return WERR_NO_SUCH_DOMAIN;
1862         }
1863
1864         info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1865         W_ERROR_HAVE_NO_MEMORY(info);
1866         info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
1867                         dc_name[0] == '\\'? "\\\\":"",
1868                         talloc_strdup(mem_ctx, dc_name));
1869         W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1870
1871         load_interface_list(mem_ctx, lp_ctx, &ifaces);
1872         pdc_ip = iface_list_best_ip(ifaces, addr);
1873         if (pdc_ip == NULL) {
1874                 pdc_ip = "127.0.0.1";
1875         }
1876         info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
1877         W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1878         info->dc_address_type  = DS_ADDRESS_TYPE_INET;
1879         info->domain_guid      = response.data.nt5_ex.domain_uuid;
1880         info->domain_name      = domain_name;
1881         info->forest_name      = response.data.nt5_ex.forest;
1882         info->dc_flags         = response.data.nt5_ex.server_type;
1883         if (r->in.flags & DS_RETURN_DNS_NAME) {
1884                 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
1885                  * returned if we are returning info->dc_unc containing a FQDN.
1886                  * This attribute is called DomainControllerName in the specs,
1887                  * it seems that we decide to return FQDN or netbios depending on
1888                  * DS_RETURN_DNS_NAME.
1889                  */
1890                 info->dc_flags |= DS_DNS_CONTROLLER;
1891         }
1892         info->dc_site_name     = response.data.nt5_ex.server_site;
1893         info->client_site_name = response.data.nt5_ex.client_site;
1894
1895         *r->out.info = info;
1896
1897         return WERR_OK;
1898 }
1899
1900 /*
1901   netr_DsRGetDCNameEx
1902 */
1903 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1904                                   struct netr_DsRGetDCNameEx *r)
1905 {
1906         struct netr_DsRGetDCNameEx2 r2;
1907         WERROR werr;
1908
1909         ZERO_STRUCT(r2);
1910
1911         r2.in.server_unc = r->in.server_unc;
1912         r2.in.client_account = NULL;
1913         r2.in.mask = 0;
1914         r2.in.domain_guid = r->in.domain_guid;
1915         r2.in.domain_name = r->in.domain_name;
1916         r2.in.site_name = r->in.site_name;
1917         r2.in.flags = r->in.flags;
1918         r2.out.info = r->out.info;
1919
1920         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1921
1922         return werr;
1923 }
1924
1925 /*
1926   netr_DsRGetDCName
1927 */
1928 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1929                                 struct netr_DsRGetDCName *r)
1930 {
1931         struct netr_DsRGetDCNameEx2 r2;
1932         WERROR werr;
1933
1934         ZERO_STRUCT(r2);
1935
1936         r2.in.server_unc = r->in.server_unc;
1937         r2.in.client_account = NULL;
1938         r2.in.mask = 0;
1939         r2.in.domain_name = r->in.domain_name;
1940         r2.in.domain_guid = r->in.domain_guid;
1941
1942         r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1943         r2.in.flags = r->in.flags;
1944         r2.out.info = r->out.info;
1945
1946         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1947
1948         return werr;
1949 }
1950 /*
1951   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1952 */
1953 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1954                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1955 {
1956         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1957 }
1958
1959
1960 /*
1961   netr_NetrEnumerateTrustedDomainsEx
1962 */
1963 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1964                        struct netr_NetrEnumerateTrustedDomainsEx *r)
1965 {
1966         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1967 }
1968
1969
1970 /*
1971   netr_DsRAddressToSitenamesExW
1972 */
1973 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1974                                                    struct netr_DsRAddressToSitenamesExW *r)
1975 {
1976         struct ldb_context *sam_ctx;
1977         struct netr_DsRAddressToSitenamesExWCtr *ctr;
1978         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1979         sa_family_t sin_family;
1980         struct sockaddr_in *addr;
1981 #ifdef HAVE_IPV6
1982         struct sockaddr_in6 *addr6;
1983         char addr_str[INET6_ADDRSTRLEN];
1984 #else
1985         char addr_str[INET_ADDRSTRLEN];
1986 #endif
1987         char *subnet_name;
1988         const char *res;
1989         uint32_t i;
1990
1991         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1992                                 dce_call->conn->auth_state.session_info, 0);
1993         if (sam_ctx == NULL) {
1994                 return WERR_DS_UNAVAILABLE;
1995         }
1996
1997         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1998         W_ERROR_HAVE_NO_MEMORY(ctr);
1999
2000         *r->out.ctr = ctr;
2001
2002         ctr->count = r->in.count;
2003         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2004         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2005         ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
2006         W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
2007
2008         for (i=0; i<ctr->count; i++) {
2009                 ctr->sitename[i].string = NULL;
2010                 ctr->subnetname[i].string = NULL;
2011
2012                 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2013                         continue;
2014                 }
2015                 /* The first two byte of the buffer are reserved for the
2016                  * "sin_family" but for now only the first one is used. */
2017                 sin_family = r->in.addresses[i].buffer[0];
2018
2019                 switch (sin_family) {
2020                 case AF_INET:
2021                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2022                                 continue;
2023                         }
2024                         addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2025                         res = inet_ntop(AF_INET, &addr->sin_addr,
2026                                         addr_str, sizeof(addr_str));
2027                         break;
2028 #ifdef HAVE_IPV6
2029                 case AF_INET6:
2030                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2031                                 continue;
2032                         }
2033                         addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2034                         res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2035                                         addr_str, sizeof(addr_str));
2036                         break;
2037 #endif
2038                 default:
2039                         continue;
2040                 }
2041
2042                 if (res == NULL) {
2043                         continue;
2044                 }
2045
2046                 ctr->sitename[i].string   = samdb_client_site_name(sam_ctx,
2047                                                                    mem_ctx,
2048                                                                    addr_str,
2049                                                                    &subnet_name);
2050                 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2051                 ctr->subnetname[i].string = subnet_name;
2052         }
2053
2054         return WERR_OK;
2055 }
2056
2057
2058 /*
2059   netr_DsRAddressToSitenamesW
2060 */
2061 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2062                        struct netr_DsRAddressToSitenamesW *r)
2063 {
2064         struct netr_DsRAddressToSitenamesExW r2;
2065         struct netr_DsRAddressToSitenamesWCtr *ctr;
2066         uint32_t i;
2067         WERROR werr;
2068
2069         ZERO_STRUCT(r2);
2070
2071         r2.in.server_name = r->in.server_name;
2072         r2.in.count = r->in.count;
2073         r2.in.addresses = r->in.addresses;
2074
2075         r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2076         W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2077
2078         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2079         W_ERROR_HAVE_NO_MEMORY(ctr);
2080
2081         *r->out.ctr = ctr;
2082
2083         ctr->count = r->in.count;
2084         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2085         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2086
2087         werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2088
2089         for (i=0; i<ctr->count; i++) {
2090                 ctr->sitename[i].string   = (*r2.out.ctr)->sitename[i].string;
2091         }
2092
2093         return werr;
2094 }
2095
2096
2097 /*
2098   netr_DsrGetDcSiteCoverageW
2099 */
2100 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2101                        struct netr_DsrGetDcSiteCoverageW *r)
2102 {
2103         struct ldb_context *sam_ctx;
2104         struct DcSitesCtr *ctr;
2105         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2106
2107         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2108                                 dce_call->conn->auth_state.session_info, 0);
2109         if (sam_ctx == NULL) {
2110                 return WERR_DS_UNAVAILABLE;
2111         }
2112
2113         ctr = talloc(mem_ctx, struct DcSitesCtr);
2114         W_ERROR_HAVE_NO_MEMORY(ctr);
2115
2116         *r->out.ctr = ctr;
2117
2118         /* For now only return our default site */
2119         ctr->num_sites = 1;
2120         ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2121         W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2122         ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2123         W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2124
2125         return WERR_OK;
2126 }
2127
2128
2129 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2130                                          struct ldb_context *sam_ctx,
2131                                          struct netr_DomainTrustList *trusts,
2132                                          uint32_t trust_flags)
2133 {
2134         struct ldb_dn *system_dn;
2135         struct ldb_message **dom_res = NULL;
2136         const char *trust_attrs[] = { "flatname", "trustPartner",
2137                                       "securityIdentifier", "trustDirection",
2138                                       "trustType", "trustAttributes", NULL };
2139         uint32_t n;
2140         int i;
2141         int ret;
2142
2143         if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2144                              NETR_TRUST_FLAG_OUTBOUND))) {
2145                 return WERR_INVALID_FLAGS;
2146         }
2147
2148         system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2149                                     ldb_get_default_basedn(sam_ctx),
2150                                     "(&(objectClass=container)(cn=System))");
2151         if (!system_dn) {
2152                 return WERR_GENERAL_FAILURE;
2153         }
2154
2155         ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2156                            &dom_res, trust_attrs,
2157                            "(objectclass=trustedDomain)");
2158
2159         for (i = 0; i < ret; i++) {
2160                 unsigned int trust_dir;
2161                 uint32_t flags = 0;
2162
2163                 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2164                                                       "trustDirection", 0);
2165
2166                 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2167                         flags |= NETR_TRUST_FLAG_INBOUND;
2168                 }
2169                 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2170                         flags |= NETR_TRUST_FLAG_OUTBOUND;
2171                 }
2172
2173                 if (!(flags & trust_flags)) {
2174                         /* this trust direction was not requested */
2175                         continue;
2176                 }
2177
2178                 n = trusts->count;
2179                 trusts->array = talloc_realloc(trusts, trusts->array,
2180                                                struct netr_DomainTrust,
2181                                                n + 1);
2182                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2183
2184                 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2185                 if (!trusts->array[n].netbios_name) {
2186                         DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2187                                   "without flatname\n", 
2188                                   ldb_dn_get_linearized(dom_res[i]->dn)));
2189                 }
2190
2191                 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2192
2193                 trusts->array[n].trust_flags = flags;
2194                 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2195                     !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2196                         /* TODO: find if we have parent in the list */
2197                         trusts->array[n].parent_index = 0;
2198                 }
2199
2200                 trusts->array[n].trust_type =
2201                                 ldb_msg_find_attr_as_uint(dom_res[i],
2202                                                   "trustType", 0);
2203                 trusts->array[n].trust_attributes =
2204                                 ldb_msg_find_attr_as_uint(dom_res[i],
2205                                                   "trustAttributes", 0);
2206
2207                 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2208                     (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2209                         struct dom_sid zero_sid;
2210                         ZERO_STRUCT(zero_sid);
2211                         trusts->array[n].sid =
2212                                 dom_sid_dup(trusts, &zero_sid);
2213                 } else {
2214                         trusts->array[n].sid =
2215                                 samdb_result_dom_sid(trusts, dom_res[i],
2216                                                      "securityIdentifier");
2217                 }
2218                 trusts->array[n].guid = GUID_zero();
2219
2220                 trusts->count = n + 1;
2221         }
2222
2223         talloc_free(dom_res);
2224         return WERR_OK;
2225 }
2226
2227 /*
2228   netr_DsrEnumerateDomainTrusts
2229 */
2230 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2231                                                    TALLOC_CTX *mem_ctx,
2232                                                    struct netr_DsrEnumerateDomainTrusts *r)
2233 {
2234         struct netr_DomainTrustList *trusts;
2235         struct ldb_context *sam_ctx;
2236         int ret;
2237         struct ldb_message **dom_res;
2238         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2239         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2240         const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2241         const char *p;
2242         WERROR werr;
2243
2244         if (r->in.trust_flags & 0xFFFFFE00) {
2245                 return WERR_INVALID_FLAGS;
2246         }
2247
2248         /* TODO: turn to hard check once we are sure this is 100% correct */
2249         if (!r->in.server_name) {
2250                 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2251                           "But received NULL!\n", dnsdomain));
2252         } else {
2253                 p = strchr(r->in.server_name, '.');
2254                 if (!p) {
2255                         DEBUG(3, ("Invalid domain! Expected name in domain "
2256                                   "[%s]. But received [%s]!\n",
2257                                   dnsdomain, r->in.server_name));
2258                         p = r->in.server_name;
2259                 } else {
2260                         p++;
2261                 }
2262                 if (strcasecmp(p, dnsdomain)) {
2263                         DEBUG(3, ("Invalid domain! Expected name in domain "
2264                                   "[%s]. But received [%s]!\n",
2265                                   dnsdomain, r->in.server_name));
2266                 }
2267         }
2268
2269         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2270         W_ERROR_HAVE_NO_MEMORY(trusts);
2271
2272         trusts->count = 0;
2273         r->out.trusts = trusts;
2274
2275         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2276                                 dce_call->conn->auth_state.session_info, 0);
2277         if (sam_ctx == NULL) {
2278                 return WERR_GENERAL_FAILURE;
2279         }
2280
2281         if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2282             (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2283
2284                 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2285                                                   trusts, r->in.trust_flags);
2286                 W_ERROR_NOT_OK_RETURN(werr);
2287         }
2288
2289         /* NOTE: we currently are always the root of the forest */
2290         if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2291                 uint32_t n = trusts->count;
2292
2293                 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2294                                       &dom_res, dom_attrs);
2295                 if (ret != 1) {
2296                         return WERR_GENERAL_FAILURE;
2297                 }
2298
2299                 trusts->count = n + 1;
2300                 trusts->array = talloc_realloc(trusts, trusts->array,
2301                                                struct netr_DomainTrust,
2302                                                trusts->count);
2303                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2304
2305                 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2306                 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2307                 trusts->array[n].trust_flags =
2308                         NETR_TRUST_FLAG_NATIVE |
2309                         NETR_TRUST_FLAG_TREEROOT |
2310                         NETR_TRUST_FLAG_IN_FOREST |
2311                         NETR_TRUST_FLAG_PRIMARY;
2312                 /* we are always the root domain for now */
2313                 trusts->array[n].parent_index = 0;
2314                 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2315                 trusts->array[n].trust_attributes = 0;
2316                 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2317                                                             dom_res[0],
2318                                                             "objectSid");
2319                 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2320                                                           "objectGUID");
2321                 talloc_free(dom_res);
2322         }
2323
2324         return WERR_OK;
2325 }
2326
2327
2328 /*
2329   netr_DsrDeregisterDNSHostRecords
2330 */
2331 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2332                        struct netr_DsrDeregisterDNSHostRecords *r)
2333 {
2334         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2335 }
2336
2337
2338 /*
2339   netr_ServerTrustPasswordsGet
2340 */
2341 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2342                        struct netr_ServerTrustPasswordsGet *r)
2343 {
2344         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2345 }
2346
2347
2348 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2349                                       struct ldb_context *sam_ctx,
2350                                       struct loadparm_context *lp_ctx,
2351                                       struct lsa_ForestTrustInformation *info)
2352 {
2353         struct lsa_ForestTrustDomainInfo *domain_info;
2354         struct lsa_ForestTrustRecord *e;
2355         struct ldb_message **dom_res;
2356         const char * const dom_attrs[] = { "objectSid", NULL };
2357         int ret;
2358
2359         /* we need to provide 2 entries:
2360          * 1. the Root Forest name
2361          * 2. the Domain Information
2362          */
2363
2364         info->count = 2;
2365         info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2366         W_ERROR_HAVE_NO_MEMORY(info->entries);
2367
2368         /* Forest root info */
2369         e = talloc(info, struct lsa_ForestTrustRecord);
2370         W_ERROR_HAVE_NO_MEMORY(e);
2371
2372         e->flags = 0;
2373         e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2374         e->time = 0; /* so far always 0 in trces. */
2375         e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2376                                                                        mem_ctx);
2377         W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2378
2379         info->entries[0] = e;
2380
2381         /* Domain info */
2382         e = talloc(info, struct lsa_ForestTrustRecord);
2383         W_ERROR_HAVE_NO_MEMORY(e);
2384
2385         /* get our own domain info */
2386         ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2387         if (ret != 1) {
2388                 return WERR_GENERAL_FAILURE;
2389         }
2390
2391         /* TODO: check if disabled and set flags accordingly */
2392         e->flags = 0;
2393         e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2394         e->time = 0; /* so far always 0 in traces. */
2395
2396         domain_info = &e->forest_trust_data.domain_info;
2397         domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2398                                                        "objectSid");
2399         domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2400         domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2401
2402         info->entries[1] = e;
2403
2404         talloc_free(dom_res);
2405
2406         return WERR_OK;
2407 }
2408
2409 /*
2410   netr_DsRGetForestTrustInformation
2411 */
2412 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2413                                                        TALLOC_CTX *mem_ctx,
2414                                                        struct netr_DsRGetForestTrustInformation *r)
2415 {
2416         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2417         struct lsa_ForestTrustInformation *info, **info_ptr;
2418         struct ldb_context *sam_ctx;
2419         WERROR werr;
2420
2421         if (r->in.flags & 0xFFFFFFFE) {
2422                 return WERR_INVALID_FLAGS;
2423         }
2424
2425         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2426                                 dce_call->conn->auth_state.session_info, 0);
2427         if (sam_ctx == NULL) {
2428                 return WERR_GENERAL_FAILURE;
2429         }
2430
2431         if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2432                 if (!samdb_is_pdc(sam_ctx)) {
2433                         return WERR_NERR_NOTPRIMARY;
2434                 }
2435
2436                 if (r->in.trusted_domain_name == NULL) {
2437                         return WERR_INVALID_FLAGS;
2438                 }
2439
2440                 /* TODO: establish an schannel connection with
2441                  * r->in.trusted_domain_name and perform a
2442                  * netr_GetForestTrustInformation call against it */
2443
2444                 /* for now return not implementd */
2445                 return WERR_CALL_NOT_IMPLEMENTED;
2446         }
2447
2448         /* TODO: check r->in.server_name is our name */
2449
2450         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2451         W_ERROR_HAVE_NO_MEMORY(info_ptr);
2452
2453         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2454         W_ERROR_HAVE_NO_MEMORY(info);
2455
2456         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2457         W_ERROR_NOT_OK_RETURN(werr);
2458
2459         *info_ptr = info;
2460         r->out.forest_trust_info = info_ptr;
2461
2462         return WERR_OK;
2463 }
2464
2465
2466 /*
2467   netr_GetForestTrustInformation
2468 */
2469 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2470                                                       TALLOC_CTX *mem_ctx,
2471                                                       struct netr_GetForestTrustInformation *r)
2472 {
2473         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2474         struct netlogon_creds_CredentialState *creds;
2475         struct lsa_ForestTrustInformation *info, **info_ptr;
2476         struct ldb_context *sam_ctx;
2477         NTSTATUS status;
2478         WERROR werr;
2479
2480         status = dcesrv_netr_creds_server_step_check(dce_call,
2481                                                      mem_ctx,
2482                                                      r->in.computer_name,
2483                                                      r->in.credential,
2484                                                      r->out.return_authenticator,
2485                                                      &creds);
2486         if (!NT_STATUS_IS_OK(status)) {
2487                 return status;
2488         }
2489
2490         if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2491             (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2492                 return NT_STATUS_NOT_IMPLEMENTED;
2493         }
2494
2495         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2496                                 dce_call->conn->auth_state.session_info, 0);
2497         if (sam_ctx == NULL) {
2498                 return NT_STATUS_INTERNAL_ERROR;
2499         }
2500
2501         /* TODO: check r->in.server_name is our name */
2502
2503         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2504         if (!info_ptr) {
2505                 return NT_STATUS_NO_MEMORY;
2506         }
2507         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2508         if (!info) {
2509                 return NT_STATUS_NO_MEMORY;
2510         }
2511
2512         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2513         if (!W_ERROR_IS_OK(werr)) {
2514                 return werror_to_ntstatus(werr);
2515         }
2516
2517         *info_ptr = info;
2518         r->out.forest_trust_info = info_ptr;
2519
2520         return NT_STATUS_OK;
2521 }
2522
2523
2524 /*
2525   netr_ServerGetTrustInfo
2526 */
2527 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2528                        struct netr_ServerGetTrustInfo *r)
2529 {
2530         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2531 }
2532
2533 /*
2534   netr_Unused47
2535 */
2536 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2537                                      struct netr_Unused47 *r)
2538 {
2539         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2540 }
2541
2542
2543 struct netr_dnsupdate_RODC_state {
2544         struct dcesrv_call_state *dce_call;
2545         struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2546         struct dnsupdate_RODC *r2;
2547 };
2548
2549 /*
2550   called when the forwarded RODC dns update request is finished
2551  */
2552 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2553 {
2554         struct netr_dnsupdate_RODC_state *st =
2555                 tevent_req_callback_data(subreq,
2556                                          struct netr_dnsupdate_RODC_state);
2557         NTSTATUS status;
2558
2559         status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2560         TALLOC_FREE(subreq);
2561         if (!NT_STATUS_IS_OK(status)) {
2562                 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2563                 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2564         }
2565
2566         st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2567
2568         status = dcesrv_reply(st->dce_call);
2569         if (!NT_STATUS_IS_OK(status)) {
2570                 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2571         }
2572 }
2573
2574 /*
2575   netr_DsrUpdateReadOnlyServerDnsRecords
2576 */
2577 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2578                                                               TALLOC_CTX *mem_ctx,
2579                                                               struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2580 {
2581         struct netlogon_creds_CredentialState *creds;
2582         NTSTATUS nt_status;
2583         struct dcerpc_binding_handle *binding_handle;
2584         struct netr_dnsupdate_RODC_state *st;
2585         struct tevent_req *subreq;
2586
2587         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2588                                                         mem_ctx,
2589                                                         r->in.computer_name,
2590                                                         r->in.credential,
2591                                                         r->out.return_authenticator,
2592                                                         &creds);
2593         NT_STATUS_NOT_OK_RETURN(nt_status);
2594
2595         if (creds->secure_channel_type != SEC_CHAN_RODC) {
2596                 return NT_STATUS_ACCESS_DENIED;
2597         }
2598
2599         st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2600         NT_STATUS_HAVE_NO_MEMORY(st);
2601
2602         st->dce_call = dce_call;
2603         st->r = r;
2604         st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2605         NT_STATUS_HAVE_NO_MEMORY(st->r2);
2606
2607         st->r2->in.dom_sid = creds->sid;
2608         st->r2->in.site_name = r->in.site_name;
2609         st->r2->in.dns_ttl = r->in.dns_ttl;
2610         st->r2->in.dns_names = r->in.dns_names;
2611         st->r2->out.dns_names = r->out.dns_names;
2612
2613         binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2614                                                      "dnsupdate", &ndr_table_irpc);
2615         if (binding_handle == NULL) {
2616                 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2617                 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2618                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2619         }
2620
2621         /* forward the call */
2622         subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2623                                               binding_handle, st->r2);
2624         NT_STATUS_HAVE_NO_MEMORY(subreq);
2625
2626         dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2627
2628         /* setup the callback */
2629         tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2630
2631         return NT_STATUS_OK;
2632 }
2633
2634
2635 /* include the generated boilerplate */
2636 #include "librpc/gen_ndr/ndr_netlogon_s.c"