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