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