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