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