schannel: move schannel_sign to main directory.
[ira/wip.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 "rpc_server/common/common.h"
27 #include "lib/ldb/include/ldb.h"
28 #include "auth/auth.h"
29 #include "auth/auth_sam_reply.h"
30 #include "dsdb/samdb/samdb.h"
31 #include "../libds/common/flags.h"
32 #include "rpc_server/samr/proto.h"
33 #include "../lib/util/util_ldb.h"
34 #include "libcli/auth/libcli_auth.h"
35 #include "../libcli/auth/schannel.h"
36 #include "auth/gensec/schannel_state.h"
37 #include "libcli/security/security.h"
38 #include "param/param.h"
39 #include "lib/messaging/irpc.h"
40 #include "librpc/gen_ndr/ndr_irpc.h"
41 #include "librpc/gen_ndr/ndr_netlogon.h"
42
43 struct netlogon_server_pipe_state {
44         struct netr_Credential client_challenge;
45         struct netr_Credential server_challenge;
46 };
47
48
49 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
50                                         struct netr_ServerReqChallenge *r)
51 {
52         struct netlogon_server_pipe_state *pipe_state =
53                 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
54
55         ZERO_STRUCTP(r->out.return_credentials);
56
57         /* destroyed on pipe shutdown */
58
59         if (pipe_state) {
60                 talloc_free(pipe_state);
61                 dce_call->context->private_data = NULL;
62         }
63         
64         pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
65         NT_STATUS_HAVE_NO_MEMORY(pipe_state);
66
67         pipe_state->client_challenge = *r->in.credentials;
68
69         generate_random_buffer(pipe_state->server_challenge.data, 
70                                sizeof(pipe_state->server_challenge.data));
71
72         *r->out.return_credentials = pipe_state->server_challenge;
73
74         dce_call->context->private_data = pipe_state;
75
76         return NT_STATUS_OK;
77 }
78
79 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
80                                          struct netr_ServerAuthenticate3 *r)
81 {
82         struct netlogon_server_pipe_state *pipe_state =
83                 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
84         struct netlogon_creds_CredentialState *creds;
85         struct ldb_context *schannel_ldb;
86         struct ldb_context *sam_ctx;
87         struct samr_Password *mach_pwd;
88         uint32_t user_account_control;
89         int num_records;
90         struct ldb_message **msgs;
91         NTSTATUS nt_status;
92         const char *attrs[] = {"unicodePwd", "userAccountControl", 
93                                "objectSid", NULL};
94
95         const char *trust_dom_attrs[] = {"flatname", NULL};
96         const char *account_name;
97
98         ZERO_STRUCTP(r->out.return_credentials);
99         *r->out.rid = 0;
100
101         /*
102          * According to Microsoft (see bugid #6099)
103          * Windows 7 looks at the negotiate_flags
104          * returned in this structure *even if the
105          * call fails with access denied!
106          */
107         *r->out.negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
108                                   NETLOGON_NEG_PERSISTENT_SAMREPL |
109                                   NETLOGON_NEG_ARCFOUR |
110                                   NETLOGON_NEG_PROMOTION_COUNT |
111                                   NETLOGON_NEG_CHANGELOG_BDC |
112                                   NETLOGON_NEG_FULL_SYNC_REPL |
113                                   NETLOGON_NEG_MULTIPLE_SIDS |
114                                   NETLOGON_NEG_REDO |
115                                   NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
116                                   NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
117                                   NETLOGON_NEG_GENERIC_PASSTHROUGH |
118                                   NETLOGON_NEG_CONCURRENT_RPC |
119                                   NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
120                                   NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
121                                   NETLOGON_NEG_STRONG_KEYS |
122                                   NETLOGON_NEG_TRANSITIVE_TRUSTS |
123                                   NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
124                                   NETLOGON_NEG_PASSWORD_SET2 |
125                                   NETLOGON_NEG_GETDOMAININFO |
126                                   NETLOGON_NEG_CROSS_FOREST_TRUSTS |
127                                   NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
128                                   NETLOGON_NEG_RODC_PASSTHROUGH |
129                                   NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
130                                   NETLOGON_NEG_AUTHENTICATED_RPC;
131
132         if (!pipe_state) {
133                 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
134                 return NT_STATUS_ACCESS_DENIED;
135         }
136
137         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, 
138                                 system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
139         if (sam_ctx == NULL) {
140                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
141         }
142
143         if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
144                 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
145                 const char *flatname;
146                 if (!encoded_account) {
147                         return NT_STATUS_NO_MEMORY;
148                 }
149
150                 /* Kill the trailing dot */
151                 if (encoded_account[strlen(encoded_account)-1] == '.') {
152                         encoded_account[strlen(encoded_account)-1] = '\0';
153                 }
154
155                 /* pull the user attributes */
156                 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
157                                            trust_dom_attrs,
158                                            "(&(trustPartner=%s)(objectclass=trustedDomain))", 
159                                            encoded_account);
160                 
161                 if (num_records == 0) {
162                         DEBUG(3,("Couldn't find trust [%s] in samdb.\n", 
163                                  encoded_account));
164                         return NT_STATUS_ACCESS_DENIED;
165                 }
166                 
167                 if (num_records > 1) {
168                         DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
169                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
170                 }
171                 
172                 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
173                 if (!flatname) {
174                         /* No flatname for this trust - we can't proceed */
175                         return NT_STATUS_ACCESS_DENIED;
176                 }
177                 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
178
179                 if (!account_name) {
180                         return NT_STATUS_NO_MEMORY;
181                 }
182                 
183         } else {
184                 account_name = r->in.account_name;
185         }
186         
187         /* pull the user attributes */
188         num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
189                                    "(&(sAMAccountName=%s)(objectclass=user))", 
190                                    ldb_binary_encode_string(mem_ctx, account_name));
191
192         if (num_records == 0) {
193                 DEBUG(3,("Couldn't find user [%s] in samdb.\n", 
194                          r->in.account_name));
195                 return NT_STATUS_ACCESS_DENIED;
196         }
197
198         if (num_records > 1) {
199                 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
200                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
201         }
202
203         
204         user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
205
206         if (user_account_control & UF_ACCOUNTDISABLE) {
207                 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
208                 return NT_STATUS_ACCESS_DENIED;
209         }
210
211         if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
212                 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
213                         DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
214                         return NT_STATUS_ACCESS_DENIED;
215                 }
216         } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN || 
217                    r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
218                 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
219                         DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
220                         
221                         return NT_STATUS_ACCESS_DENIED;
222                 }
223         } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
224                 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
225                         DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
226                         return NT_STATUS_ACCESS_DENIED;
227                 }
228         } else {
229                 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n", 
230                           r->in.secure_channel_type));
231                 return NT_STATUS_ACCESS_DENIED;
232         }
233
234         *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0], 
235                                                 "objectSid", 0);
236
237         mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
238         if (mach_pwd == NULL) {
239                 return NT_STATUS_ACCESS_DENIED;
240         }
241
242         creds = netlogon_creds_server_init(mem_ctx,     
243                                            r->in.account_name,
244                                            r->in.computer_name,
245                                            r->in.secure_channel_type,
246                                            &pipe_state->client_challenge, 
247                                            &pipe_state->server_challenge, 
248                                            mach_pwd,
249                                            r->in.credentials,
250                                            r->out.return_credentials,
251                                            *r->in.negotiate_flags);
252         
253         if (!creds) {
254                 return NT_STATUS_ACCESS_DENIED;
255         }
256
257         creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
258
259         schannel_ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
260         if (!schannel_ldb) {
261                 return NT_STATUS_ACCESS_DENIED;
262         }
263
264         nt_status = schannel_store_session_key_ldb(schannel_ldb, mem_ctx, creds);
265         talloc_free(schannel_ldb);
266
267         return nt_status;
268 }
269                                                  
270 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
271                                         struct netr_ServerAuthenticate *r)
272 {
273         struct netr_ServerAuthenticate3 a;
274         uint32_t rid;
275         /* TODO: 
276          * negotiate_flags is used as an [in] parameter
277          * so it need to be initialised.
278          *
279          * (I think ... = 0; seems wrong here --metze)
280          */
281         uint32_t negotiate_flags_in = 0;
282         uint32_t negotiate_flags_out = 0;
283
284         a.in.server_name                = r->in.server_name;
285         a.in.account_name               = r->in.account_name;
286         a.in.secure_channel_type        = r->in.secure_channel_type;
287         a.in.computer_name              = r->in.computer_name;
288         a.in.credentials                = r->in.credentials;
289         a.in.negotiate_flags            = &negotiate_flags_in;
290
291         a.out.return_credentials        = r->out.return_credentials;
292         a.out.rid                       = &rid;
293         a.out.negotiate_flags           = &negotiate_flags_out;
294
295         return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
296 }
297
298 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
299                                          struct netr_ServerAuthenticate2 *r)
300 {
301         struct netr_ServerAuthenticate3 r3;
302         uint32_t rid = 0;
303
304         r3.in.server_name = r->in.server_name;
305         r3.in.account_name = r->in.account_name;
306         r3.in.secure_channel_type = r->in.secure_channel_type;
307         r3.in.computer_name = r->in.computer_name;
308         r3.in.credentials = r->in.credentials;
309         r3.out.return_credentials = r->out.return_credentials;
310         r3.in.negotiate_flags = r->in.negotiate_flags;
311         r3.out.negotiate_flags = r->out.negotiate_flags;
312         r3.out.rid = &rid;
313         
314         return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
315 }
316
317 /*
318   Validate an incoming authenticator against the credentials for the remote machine.
319
320   The credentials are (re)read and from the schannel database, and
321   written back after the caclulations are performed.
322
323   The creds_out parameter (if not NULL) returns the credentials, if
324   the caller needs some of that information.
325
326 */
327 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
328                                                     TALLOC_CTX *mem_ctx, 
329                                                     const char *computer_name,
330                                                     struct netr_Authenticator *received_authenticator,
331                                                     struct netr_Authenticator *return_authenticator,
332                                                     struct netlogon_creds_CredentialState **creds_out) 
333 {
334         NTSTATUS nt_status;
335         struct ldb_context *ldb;
336         bool schannel_global_required = false; /* Should be lp_schannel_server() == true */
337         bool schannel_in_use = dce_call->conn->auth_state.auth_info
338                 && dce_call->conn->auth_state.auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL
339                 && (dce_call->conn->auth_state.auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY 
340                     || dce_call->conn->auth_state.auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY);
341
342         ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
343         if (!ldb) {
344                 return NT_STATUS_ACCESS_DENIED;
345         }
346         nt_status = schannel_creds_server_step_check_ldb(ldb, mem_ctx,
347                                                          computer_name,
348                                                          schannel_global_required,
349                                                          schannel_in_use,
350                                                          received_authenticator,
351                                                          return_authenticator, creds_out);
352         talloc_free(ldb);
353         return nt_status;
354 }
355
356 /* 
357   Change the machine account password for the currently connected
358   client.  Supplies only the NT#.
359 */
360
361 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
362                                        struct netr_ServerPasswordSet *r)
363 {
364         struct netlogon_creds_CredentialState *creds;
365         struct ldb_context *sam_ctx;
366         NTSTATUS nt_status;
367
368         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
369                                                         mem_ctx, 
370                                                         r->in.computer_name, 
371                                                         r->in.credential, r->out.return_authenticator,
372                                                         &creds);
373         NT_STATUS_NOT_OK_RETURN(nt_status);
374
375         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
376         if (sam_ctx == NULL) {
377                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
378         }
379
380         netlogon_creds_des_decrypt(creds, r->in.new_password);
381
382         /* Using the sid for the account as the key, set the password */
383         nt_status = samdb_set_password_sid(sam_ctx, mem_ctx, 
384                                            creds->sid,
385                                            NULL, /* Don't have plaintext */
386                                            NULL, r->in.new_password,
387                                            true, /* Password change */
388                                            NULL, NULL);
389         return nt_status;
390 }
391
392 /* 
393   Change the machine account password for the currently connected
394   client.  Supplies new plaintext.
395 */
396 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
397                                        struct netr_ServerPasswordSet2 *r)
398 {
399         struct netlogon_creds_CredentialState *creds;
400         struct ldb_context *sam_ctx;
401         NTSTATUS nt_status;
402         DATA_BLOB new_password;
403
404         struct samr_CryptPassword password_buf;
405
406         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
407                                                         mem_ctx, 
408                                                         r->in.computer_name, 
409                                                         r->in.credential, r->out.return_authenticator,
410                                                         &creds);
411         NT_STATUS_NOT_OK_RETURN(nt_status);
412
413         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
414         if (sam_ctx == NULL) {
415                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
416         }
417
418         memcpy(password_buf.data, r->in.new_password->data, 512);
419         SIVAL(password_buf.data, 512, r->in.new_password->length);
420         netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
421
422         if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
423                 DEBUG(3,("samr: failed to decode password buffer\n"));
424                 return NT_STATUS_WRONG_PASSWORD;
425         }
426                 
427         /* Using the sid for the account as the key, set the password */
428         nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
429                                            creds->sid,
430                                            &new_password, /* we have plaintext */
431                                            NULL, NULL,
432                                            true, /* Password change */
433                                            NULL, NULL);
434         return nt_status;
435 }
436
437
438 /* 
439   netr_LogonUasLogon 
440 */
441 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
442                                  struct netr_LogonUasLogon *r)
443 {
444         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
445 }
446
447
448 /* 
449   netr_LogonUasLogoff 
450 */
451 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
452                        struct netr_LogonUasLogoff *r)
453 {
454         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
455 }
456
457
458 /* 
459   netr_LogonSamLogon_base
460
461   This version of the function allows other wrappers to say 'do not check the credentials'
462
463   We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
464 */
465 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
466                                         struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
467 {
468         struct auth_context *auth_context;
469         struct auth_usersupplied_info *user_info;
470         struct auth_serversupplied_info *server_info;
471         NTSTATUS nt_status;
472         static const char zeros[16];
473         struct netr_SamBaseInfo *sam;
474         struct netr_SamInfo2 *sam2;
475         struct netr_SamInfo3 *sam3;
476         struct netr_SamInfo6 *sam6;
477         
478         user_info = talloc(mem_ctx, struct auth_usersupplied_info);
479         NT_STATUS_HAVE_NO_MEMORY(user_info);
480
481         user_info->flags = 0;
482         user_info->mapped_state = false;
483         user_info->remote_host = NULL;
484
485         switch (r->in.logon_level) {
486         case NetlogonInteractiveInformation:
487         case NetlogonServiceInformation:
488         case NetlogonInteractiveTransitiveInformation:
489         case NetlogonServiceTransitiveInformation:
490                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
491                         netlogon_creds_arcfour_crypt(creds, 
492                                             r->in.logon->password->lmpassword.hash,
493                                             sizeof(r->in.logon->password->lmpassword.hash));
494                         netlogon_creds_arcfour_crypt(creds, 
495                                             r->in.logon->password->ntpassword.hash,
496                                             sizeof(r->in.logon->password->ntpassword.hash));
497                 } else {
498                         netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
499                         netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
500                 }
501
502                 /* TODO: we need to deny anonymous access here */
503                 nt_status = auth_context_create(mem_ctx, 
504                                                 dce_call->event_ctx, dce_call->msg_ctx,
505                                                 dce_call->conn->dce_ctx->lp_ctx,
506                                                 &auth_context);
507                 NT_STATUS_NOT_OK_RETURN(nt_status);
508
509                 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
510                 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
511                 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
512                 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
513                 
514                 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
515                 user_info->password_state = AUTH_PASSWORD_HASH;
516
517                 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
518                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
519                 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
520
521                 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
522                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
523                 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
524
525                 break;
526         case NetlogonNetworkInformation:
527         case NetlogonNetworkTransitiveInformation:
528
529                 /* TODO: we need to deny anonymous access here */
530                 nt_status = auth_context_create(mem_ctx, 
531                                                 dce_call->event_ctx, dce_call->msg_ctx,
532                                                 dce_call->conn->dce_ctx->lp_ctx,
533                                                 &auth_context);
534                 NT_STATUS_NOT_OK_RETURN(nt_status);
535
536                 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
537                 NT_STATUS_NOT_OK_RETURN(nt_status);
538
539                 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
540                 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
541                 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
542                 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
543                 
544                 user_info->password_state = AUTH_PASSWORD_RESPONSE;
545                 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
546                 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
547         
548                 break;
549
550                 
551         case NetlogonGenericInformation:
552         {
553                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
554                         netlogon_creds_arcfour_crypt(creds, 
555                                             r->in.logon->generic->data, r->in.logon->generic->length);
556                 } else {
557                         /* Using DES to verify kerberos tickets makes no sense */
558                         return NT_STATUS_INVALID_PARAMETER;
559                 }
560
561                 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
562                         NTSTATUS status;
563                         struct server_id *kdc;
564                         struct kdc_check_generic_kerberos check;
565                         struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
566                         NT_STATUS_HAVE_NO_MEMORY(generic);
567                         *r->out.authoritative = 1;
568                         
569                         /* TODO: Describe and deal with these flags */
570                         *r->out.flags = 0;
571
572                         r->out.validation->generic = generic;
573         
574                         kdc = irpc_servers_byname(dce_call->msg_ctx, mem_ctx, "kdc_server");
575                         if ((kdc == NULL) || (kdc[0].id == 0)) {
576                                 return NT_STATUS_NO_LOGON_SERVERS;
577                         }
578                         
579                         check.in.generic_request = 
580                                 data_blob_const(r->in.logon->generic->data,
581                                                 r->in.logon->generic->length);
582                         
583                         status = irpc_call(dce_call->msg_ctx, kdc[0],
584                                            &ndr_table_irpc, NDR_KDC_CHECK_GENERIC_KERBEROS,
585                                            &check, mem_ctx);
586                         if (!NT_STATUS_IS_OK(status)) {
587                                 return status;
588                         }
589                         generic->length = check.out.generic_reply.length;
590                         generic->data = check.out.generic_reply.data;
591                         return NT_STATUS_OK;
592                 }
593
594                 /* Until we get an implemetnation of these other packages */
595                 return NT_STATUS_INVALID_PARAMETER;
596         }
597         default:
598                 return NT_STATUS_INVALID_PARAMETER;
599         }
600         
601         nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info);
602         NT_STATUS_NOT_OK_RETURN(nt_status);
603
604         nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
605         NT_STATUS_NOT_OK_RETURN(nt_status);
606
607         /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
608         /* It appears that level 6 is not individually encrypted */
609         if ((r->in.validation_level != 6) &&
610             memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
611                 /* This key is sent unencrypted without the ARCFOUR flag set */
612                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
613                         netlogon_creds_arcfour_crypt(creds, 
614                                             sam->key.key, 
615                                             sizeof(sam->key.key));
616                 }
617         }
618
619         /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
620         /* It appears that level 6 is not individually encrypted */
621         if ((r->in.validation_level != 6) &&
622             memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
623                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
624                         netlogon_creds_arcfour_crypt(creds, 
625                                             sam->LMSessKey.key, 
626                                             sizeof(sam->LMSessKey.key));
627                 } else {
628                         netlogon_creds_des_encrypt_LMKey(creds, 
629                                                 &sam->LMSessKey);
630                 }
631         }
632
633         switch (r->in.validation_level) {
634         case 2:
635                 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
636                 NT_STATUS_HAVE_NO_MEMORY(sam2);
637                 sam2->base = *sam;
638                 r->out.validation->sam2 = sam2;
639                 break;
640
641         case 3:
642                 sam3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
643                 NT_STATUS_HAVE_NO_MEMORY(sam3);
644                 sam3->base = *sam;
645                 r->out.validation->sam3 = sam3;
646                 break;
647
648         case 6:
649                 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
650                 NT_STATUS_HAVE_NO_MEMORY(sam6);
651                 sam6->base = *sam;
652                 sam6->forest.string = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
653                 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s", 
654                                                          sam->account_name.string, sam6->forest.string);
655                 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
656                 r->out.validation->sam6 = sam6;
657                 break;
658
659         default:
660                 break;
661         }
662
663         *r->out.authoritative = 1;
664
665         /* TODO: Describe and deal with these flags */
666         *r->out.flags = 0;
667
668         return NT_STATUS_OK;
669 }
670
671 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
672                                      struct netr_LogonSamLogonEx *r) 
673 {
674         NTSTATUS nt_status;
675         struct netlogon_creds_CredentialState *creds;
676         struct ldb_context *ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
677         if (!ldb) {
678                 return NT_STATUS_ACCESS_DENIED;
679         }
680         
681         nt_status = schannel_fetch_session_key_ldb(ldb, mem_ctx, r->in.computer_name, &creds);
682         if (!NT_STATUS_IS_OK(nt_status)) {
683                 return nt_status;
684         }
685
686         if (!dce_call->conn->auth_state.auth_info ||
687             dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
688                 return NT_STATUS_ACCESS_DENIED;
689         }
690         return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
691 }
692
693 /* 
694   netr_LogonSamLogonWithFlags
695
696 */
697 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
698                                             struct netr_LogonSamLogonWithFlags *r)
699 {
700         NTSTATUS nt_status;
701         struct netlogon_creds_CredentialState *creds;
702         struct netr_LogonSamLogonEx r2;
703
704         struct netr_Authenticator *return_authenticator;
705
706         return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
707         NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
708
709         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
710                                                         mem_ctx, 
711                                                         r->in.computer_name, 
712                                                         r->in.credential, return_authenticator,
713                                                         &creds);
714         NT_STATUS_NOT_OK_RETURN(nt_status);
715
716         ZERO_STRUCT(r2);
717
718         r2.in.server_name       = r->in.server_name;
719         r2.in.computer_name     = r->in.computer_name;
720         r2.in.logon_level       = r->in.logon_level;
721         r2.in.logon             = r->in.logon;
722         r2.in.validation_level  = r->in.validation_level;
723         r2.in.flags             = r->in.flags;
724         r2.out.validation       = r->out.validation;
725         r2.out.authoritative    = r->out.authoritative;
726         r2.out.flags            = r->out.flags;
727
728         nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
729
730         r->out.return_authenticator     = return_authenticator;
731
732         return nt_status;
733 }
734
735 /* 
736   netr_LogonSamLogon
737 */
738 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
739                                    struct netr_LogonSamLogon *r)
740 {
741         struct netr_LogonSamLogonWithFlags r2;
742         uint32_t flags = 0;
743         NTSTATUS status;
744
745         ZERO_STRUCT(r2);
746
747         r2.in.server_name = r->in.server_name;
748         r2.in.computer_name = r->in.computer_name;
749         r2.in.credential  = r->in.credential;
750         r2.in.return_authenticator = r->in.return_authenticator;
751         r2.in.logon_level = r->in.logon_level;
752         r2.in.logon = r->in.logon;
753         r2.in.validation_level = r->in.validation_level;
754         r2.in.flags = &flags;
755         r2.out.validation = r->out.validation;
756         r2.out.authoritative = r->out.authoritative;
757         r2.out.flags = &flags;
758
759         status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
760
761         r->out.return_authenticator = r2.out.return_authenticator;
762
763         return status;
764 }
765
766
767 /* 
768   netr_LogonSamLogoff 
769 */
770 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
771                        struct netr_LogonSamLogoff *r)
772 {
773         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
774 }
775
776
777
778 /* 
779   netr_DatabaseDeltas 
780 */
781 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
782                        struct netr_DatabaseDeltas *r)
783 {
784         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
785 }
786
787
788 /* 
789   netr_DatabaseSync2 
790 */
791 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
792                        struct netr_DatabaseSync2 *r)
793 {
794         /* win2k3 native mode returns  "NOT IMPLEMENTED" for this call */
795         return NT_STATUS_NOT_IMPLEMENTED;
796 }
797
798
799 /* 
800   netr_DatabaseSync 
801 */
802 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
803                        struct netr_DatabaseSync *r)
804 {
805         struct netr_DatabaseSync2 r2;
806         NTSTATUS status;
807
808         ZERO_STRUCT(r2);
809
810         r2.in.logon_server = r->in.logon_server;
811         r2.in.computername = r->in.computername;
812         r2.in.credential = r->in.credential;
813         r2.in.database_id = r->in.database_id;
814         r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
815         r2.in.sync_context = r->in.sync_context;
816         r2.out.sync_context = r->out.sync_context;
817         r2.out.delta_enum_array = r->out.delta_enum_array;
818         r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
819
820         status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
821
822         return status;
823 }
824
825
826 /* 
827   netr_AccountDeltas 
828 */
829 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
830                        struct netr_AccountDeltas *r)
831 {
832         /* w2k3 returns "NOT IMPLEMENTED" for this call */
833         return NT_STATUS_NOT_IMPLEMENTED;
834 }
835
836
837 /* 
838   netr_AccountSync 
839 */
840 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
841                        struct netr_AccountSync *r)
842 {
843         /* w2k3 returns "NOT IMPLEMENTED" for this call */
844         return NT_STATUS_NOT_IMPLEMENTED;
845 }
846
847
848 /* 
849   netr_GetDcName 
850 */
851 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
852                        struct netr_GetDcName *r)
853 {
854         const char * const attrs[] = { NULL };
855         struct ldb_context *sam_ctx;
856         struct ldb_message **res;
857         struct ldb_dn *domain_dn;
858         int ret;
859         const char *dcname;
860
861         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
862                                 dce_call->conn->dce_ctx->lp_ctx,
863                                 dce_call->conn->auth_state.session_info);
864         if (sam_ctx == NULL) {
865                 return WERR_DS_UNAVAILABLE;
866         }
867
868         domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
869                                        r->in.domainname);
870         if (domain_dn == NULL) {
871                 return WERR_DS_UNAVAILABLE;
872         }
873
874         ret = gendb_search_dn(sam_ctx, mem_ctx,
875                               domain_dn, &res, attrs);
876         if (ret != 1) {
877                 return WERR_NO_SUCH_DOMAIN;
878         }
879
880         /* TODO: - return real IP address
881          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
882          */
883         dcname = talloc_asprintf(mem_ctx, "\\\\%s",
884                                  lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
885         W_ERROR_HAVE_NO_MEMORY(dcname);
886
887         *r->out.dcname = dcname;
888         return WERR_OK;
889 }
890
891
892 /* 
893   netr_LogonControl2Ex 
894 */
895 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
896                        struct netr_LogonControl2Ex *r)
897 {
898         return WERR_NOT_SUPPORTED;
899 }
900
901
902 /* 
903   netr_LogonControl 
904 */
905 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
906                        struct netr_LogonControl *r)
907 {
908         struct netr_LogonControl2Ex r2;
909         WERROR werr;
910
911         if (r->in.level == 0x00000001) {
912                 ZERO_STRUCT(r2);
913
914                 r2.in.logon_server = r->in.logon_server;
915                 r2.in.function_code = r->in.function_code;
916                 r2.in.level = r->in.level;
917                 r2.in.data = NULL;
918                 r2.out.query = r->out.query;
919
920                 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
921         } else if (r->in.level == 0x00000002) {
922                 werr = WERR_NOT_SUPPORTED;
923         } else {
924                 werr = WERR_UNKNOWN_LEVEL;
925         }
926
927         return werr;
928 }
929
930
931 /* 
932   netr_LogonControl2 
933 */
934 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
935                        struct netr_LogonControl2 *r)
936 {
937         struct netr_LogonControl2Ex r2;
938         WERROR werr;
939
940         ZERO_STRUCT(r2);
941
942         r2.in.logon_server = r->in.logon_server;
943         r2.in.function_code = r->in.function_code;
944         r2.in.level = r->in.level;
945         r2.in.data = r->in.data;
946         r2.out.query = r->out.query;
947
948         werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
949
950         return werr;
951 }
952
953
954 /* 
955   netr_GetAnyDCName 
956 */
957 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
958                        struct netr_GetAnyDCName *r)
959 {
960         struct netr_GetDcName r2;
961         WERROR werr;
962
963         ZERO_STRUCT(r2);
964
965         r2.in.logon_server      = r->in.logon_server;
966         r2.in.domainname        = r->in.domainname;
967         r2.out.dcname           = r->out.dcname;
968
969         werr = dcesrv_netr_GetDcName(dce_call, mem_ctx, &r2);
970
971         return werr;
972 }
973
974
975 /* 
976   netr_DatabaseRedo 
977 */
978 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
979                        struct netr_DatabaseRedo *r)
980 {
981         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
982 }
983
984
985 /* 
986   netr_NetrEnumerateTurstedDomains
987 */
988 static WERROR dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
989                        struct netr_NetrEnumerateTrustedDomains *r)
990 {
991         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
992 }
993
994
995 /* 
996   netr_LogonGetCapabilities
997 */
998 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
999                        struct netr_LogonGetCapabilities *r)
1000 {
1001         /* we don't support AES yet */
1002         return NT_STATUS_NOT_IMPLEMENTED;
1003 }
1004
1005
1006 /* 
1007   netr_NETRLOGONSETSERVICEBITS 
1008 */
1009 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1010                        struct netr_NETRLOGONSETSERVICEBITS *r)
1011 {
1012         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1013 }
1014
1015
1016 /*
1017   netr_LogonGetTrustRid
1018 */
1019 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1020                        struct netr_LogonGetTrustRid *r)
1021 {
1022         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1023 }
1024
1025
1026 /* 
1027   netr_NETRLOGONCOMPUTESERVERDIGEST 
1028 */
1029 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1030                        struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1031 {
1032         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1033 }
1034
1035
1036 /* 
1037   netr_NETRLOGONCOMPUTECLIENTDIGEST 
1038 */
1039 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1040                        struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1041 {
1042         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1043 }
1044
1045
1046
1047 /* 
1048   netr_DsRGetSiteName
1049 */
1050 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1051                                   struct netr_DsRGetSiteName *r)
1052 {
1053         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1054 }
1055
1056
1057 /*
1058   fill in a netr_OneDomainInfo from a ldb search result
1059 */
1060 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1061                                      struct loadparm_context *lp_ctx,
1062                                      struct ldb_context *sam_ctx,
1063                                      struct ldb_message *res,
1064                                      struct netr_OneDomainInfo *info,
1065                                      bool is_local, bool is_trust_list)
1066 {
1067         ZERO_STRUCTP(info);
1068
1069         info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1070         info->trust_extension.length = 16;
1071         info->trust_extension.info->flags = 
1072                 NETR_TRUST_FLAG_TREEROOT |
1073                 NETR_TRUST_FLAG_IN_FOREST | 
1074                 NETR_TRUST_FLAG_PRIMARY;
1075
1076         info->trust_extension.info->parent_index = 0; /* should be index into array
1077                                                          of parent */
1078         info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1079         info->trust_extension.info->trust_attributes = LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE; /* needs to be based on ldb search */
1080
1081         if (is_trust_list) {
1082                 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1083                 info->dns_forestname.string = NULL;
1084         } else {
1085                 char *p;
1086                 /* TODO: we need a common function for pulling the forest */
1087                 info->dns_forestname.string = ldb_dn_canonical_string(info, ldb_get_root_basedn(sam_ctx));
1088                 if (!info->dns_forestname.string) {
1089                         return NT_STATUS_NO_SUCH_DOMAIN;                
1090                 }
1091                 p = strchr(info->dns_forestname.string, '/');
1092                 if (p) {
1093                         *p = '\0';
1094                 }
1095         }
1096
1097         if (is_local) {
1098                 info->domainname.string = lp_sam_name(lp_ctx);
1099                 info->dns_domainname.string = lp_realm(lp_ctx);
1100                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1101                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1102         } else {
1103                 info->domainname.string = samdb_result_string(res, "flatName", NULL);
1104                 info->dns_domainname.string = samdb_result_string(res, "trustPartner", NULL);
1105                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1106                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1107         }
1108
1109         return NT_STATUS_OK;
1110 }
1111
1112 /* 
1113   netr_LogonGetDomainInfo
1114   this is called as part of the ADS domain logon procedure.
1115
1116   It has an important role in convaying details about the client, such
1117   as Operating System, Version, Service Pack etc.
1118 */
1119 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1120         TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1121 {
1122         struct netlogon_creds_CredentialState *creds;
1123         const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1124                 "securityIdentifier", "trustPartner", NULL };
1125         const char *temp_str;
1126         const char *old_dns_hostname;
1127         struct ldb_context *sam_ctx;
1128         struct ldb_message **res1, **res2, *new_msg;
1129         struct ldb_dn *workstation_dn;
1130         struct netr_DomainInformation *domain_info;
1131         struct netr_LsaPolicyInformation *lsa_policy_info;
1132         struct netr_OsVersionInfoEx *os_version;
1133         uint32_t default_supported_enc_types =
1134                 ENC_CRC32|ENC_RSA_MD5|ENC_RC4_HMAC_MD5;
1135         int ret1, ret2, i;
1136         NTSTATUS status;
1137
1138         status = dcesrv_netr_creds_server_step_check(dce_call,
1139                                                      mem_ctx, 
1140                                                      r->in.computer_name, 
1141                                                      r->in.credential, 
1142                                                      r->out.return_authenticator,
1143                                                      &creds);
1144         if (!NT_STATUS_IS_OK(status)) {
1145                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1146         }
1147         NT_STATUS_NOT_OK_RETURN(status);
1148
1149         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1150                 dce_call->conn->dce_ctx->lp_ctx,
1151                 system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
1152         if (sam_ctx == NULL) {
1153                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1154         }
1155
1156         switch (r->in.level) {
1157         case 1: /* Domain information */
1158
1159                 /* TODO: check NTSTATUS results - and fail also on SAMDB
1160                  * errors (needs some testing against Windows Server 2008) */
1161
1162                 /*
1163                  * Check that the computer name parameter matches as prefix with
1164                  * the DNS hostname in the workstation info structure.
1165                  */
1166                 temp_str = strndup(r->in.query->workstation_info->dns_hostname,
1167                         strcspn(r->in.query->workstation_info->dns_hostname,
1168                         "."));
1169                 if (strcasecmp(r->in.computer_name, temp_str) != 0)
1170                         return NT_STATUS_INVALID_PARAMETER;
1171
1172                 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1173                         dom_sid_string(mem_ctx, creds->sid));
1174                 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1175
1176                 /* Gets the old DNS hostname */
1177                 old_dns_hostname = samdb_search_string(sam_ctx, mem_ctx,
1178                                                         workstation_dn,
1179                                                         "dNSHostName",
1180                                                         NULL);
1181
1182                 /* Gets host informations and put them in our directory */
1183                 new_msg = ldb_msg_new(mem_ctx);
1184                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1185
1186                 new_msg->dn = workstation_dn;
1187
1188                 /* Deletes old OS version values */
1189                 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1190                         "operatingSystemServicePack");
1191                 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1192                         "operatingSystemVersion");
1193
1194                 if (samdb_replace(sam_ctx, mem_ctx, new_msg) != LDB_SUCCESS) {
1195                         DEBUG(3,("Impossible to update samdb: %s\n",
1196                                 ldb_errstring(sam_ctx)));
1197                 }
1198
1199                 talloc_free(new_msg);
1200
1201                 new_msg = ldb_msg_new(mem_ctx);
1202                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1203
1204                 new_msg->dn = workstation_dn;
1205
1206                 /* Sets the OS name */
1207                 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1208                         "operatingSystem",
1209                         r->in.query->workstation_info->os_name.string);
1210
1211                 /*
1212                  * Sets informations from "os_version". On a empty structure
1213                  * the values are cleared.
1214                  */
1215                 if (r->in.query->workstation_info->os_version.os != NULL) {
1216                         os_version = &r->in.query->workstation_info->os_version.os->os;
1217
1218                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1219                                              "operatingSystemServicePack",
1220                                              os_version->CSDVersion);
1221
1222                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1223                                 "operatingSystemVersion",
1224                                 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1225                                         os_version->MajorVersion,
1226                                         os_version->MinorVersion,
1227                                         os_version->BuildNumber
1228                                 )
1229                         );
1230                 }
1231
1232                 /*
1233                  * Updates the "dNSHostname" and the "servicePrincipalName"s
1234                  * since the client wishes that the server should handle this
1235                  * for him ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
1236                  * See MS-NRPC section 3.5.4.3.9
1237                  */
1238                 if ((r->in.query->workstation_info->workstation_flags
1239                         & NETR_WS_FLAG_HANDLES_SPN_UPDATE) == 0) {
1240
1241                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1242                                 "dNSHostname",
1243                                 r->in.query->workstation_info->dns_hostname);
1244                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1245                                 "servicePrincipalName",
1246                                 talloc_asprintf(mem_ctx, "HOST/%s",
1247                                 r->in.computer_name)
1248                         );
1249                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1250                                 "servicePrincipalName",
1251                                 talloc_asprintf(mem_ctx, "HOST/%s",
1252                                 r->in.query->workstation_info->dns_hostname)
1253                         );
1254                 }
1255
1256                 if (samdb_replace(sam_ctx, mem_ctx, new_msg) != LDB_SUCCESS) {
1257                         DEBUG(3,("Impossible to update samdb: %s\n",
1258                                 ldb_errstring(sam_ctx)));
1259                 }
1260
1261                 talloc_free(new_msg);
1262
1263                 /* Writes back the domain information */
1264
1265                 /* We need to do two searches. The first will pull our primary
1266                    domain and the second will pull any trusted domains. Our
1267                    primary domain is also a "trusted" domain, so we need to
1268                    put the primary domain into the lists of returned trusts as
1269                    well. */
1270                 ret1 = gendb_search_dn(sam_ctx, mem_ctx, samdb_base_dn(sam_ctx),
1271                         &res1, attrs);
1272                 if (ret1 != 1) {
1273                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1274                 }
1275
1276                 ret2 = gendb_search(sam_ctx, mem_ctx, NULL, &res2, attrs,
1277                         "(objectClass=trustedDomain)");
1278                 if (ret2 == -1) {
1279                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1280                 }
1281
1282                 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1283                 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1284
1285                 ZERO_STRUCTP(domain_info);
1286
1287                 /* Informations about the local and trusted domains */
1288
1289                 status = fill_one_domain_info(mem_ctx,
1290                         dce_call->conn->dce_ctx->lp_ctx,
1291                         sam_ctx, res1[0], &domain_info->primary_domain,
1292                         true, false);
1293                 NT_STATUS_NOT_OK_RETURN(status);
1294
1295                 domain_info->trusted_domain_count = ret2 + 1;
1296                 domain_info->trusted_domains = talloc_array(mem_ctx,
1297                         struct netr_OneDomainInfo,
1298                         domain_info->trusted_domain_count);
1299                 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1300
1301                 for (i=0;i<ret2;i++) {
1302                         status = fill_one_domain_info(mem_ctx,
1303                                 dce_call->conn->dce_ctx->lp_ctx,
1304                                 sam_ctx, res2[i],
1305                                 &domain_info->trusted_domains[i],
1306                                 false, true);
1307                         NT_STATUS_NOT_OK_RETURN(status);
1308                 }
1309
1310                 status = fill_one_domain_info(mem_ctx,
1311                         dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res1[0],
1312                         &domain_info->trusted_domains[i], true, true);
1313                 NT_STATUS_NOT_OK_RETURN(status);
1314
1315                 /* Sets the supported encryption types */
1316                 domain_info->supported_enc_types = samdb_search_uint(
1317                         sam_ctx, mem_ctx,
1318                         default_supported_enc_types, workstation_dn,
1319                         "msDS-SupportedEncryptionTypes", NULL);
1320
1321                 /* Other host domain informations */
1322
1323                 lsa_policy_info = talloc(mem_ctx,
1324                         struct netr_LsaPolicyInformation);
1325                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1326                 ZERO_STRUCTP(lsa_policy_info);
1327
1328                 domain_info->lsa_policy = *lsa_policy_info;
1329
1330                 domain_info->dns_hostname.string = old_dns_hostname;
1331                 domain_info->workstation_flags =
1332                         r->in.query->workstation_info->workstation_flags;
1333
1334                 r->out.info->domain_info = domain_info;
1335         break;
1336         case 2: /* LSA policy information - not used at the moment */
1337                 lsa_policy_info = talloc(mem_ctx,
1338                         struct netr_LsaPolicyInformation);
1339                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1340                 ZERO_STRUCTP(lsa_policy_info);
1341
1342                 r->out.info->lsa_policy_info = lsa_policy_info;
1343         break;
1344         default:
1345                 return NT_STATUS_INVALID_LEVEL;
1346         break;
1347         }
1348
1349         return NT_STATUS_OK;
1350 }
1351
1352
1353
1354 /*
1355   netr_ServerPasswordGet
1356 */
1357 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1358                        struct netr_ServerPasswordGet *r)
1359 {
1360         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1361 }
1362
1363
1364 /* 
1365   netr_NETRLOGONSENDTOSAM 
1366 */
1367 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1368                        struct netr_NETRLOGONSENDTOSAM *r)
1369 {
1370         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1371 }
1372
1373
1374 /* 
1375   netr_DsRAddressToSitenamesW 
1376 */
1377 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1378                        struct netr_DsRAddressToSitenamesW *r)
1379 {
1380         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1381 }
1382
1383
1384 /* 
1385   netr_DsRGetDCNameEx2
1386 */
1387 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1388                                    struct netr_DsRGetDCNameEx2 *r)
1389 {
1390         const char * const attrs[] = { "objectGUID", NULL };
1391         struct ldb_context *sam_ctx;
1392         struct ldb_message **res;
1393         struct ldb_dn *domain_dn;
1394         int ret;
1395         struct netr_DsRGetDCNameInfo *info;
1396
1397         ZERO_STRUCTP(r->out.info);
1398
1399         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
1400         if (sam_ctx == NULL) {
1401                 return WERR_DS_UNAVAILABLE;
1402         }
1403
1404         /* Win7-beta will send the domain name in the form the user typed, so we have to cope
1405            with both the short and long form here */
1406         if (r->in.domain_name != NULL && !lp_is_my_domain_or_realm(dce_call->conn->dce_ctx->lp_ctx, 
1407                                                                 r->in.domain_name)) {
1408                 return WERR_NO_SUCH_DOMAIN;
1409         }
1410
1411         domain_dn = ldb_get_default_basedn(sam_ctx);
1412         if (domain_dn == NULL) {
1413                 return WERR_DS_UNAVAILABLE;
1414         }
1415
1416         ret = gendb_search_dn(sam_ctx, mem_ctx,
1417                               domain_dn, &res, attrs);
1418         if (ret != 1) {
1419         }
1420
1421         info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1422         W_ERROR_HAVE_NO_MEMORY(info);
1423
1424         /* TODO: - return real IP address
1425          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
1426          */
1427         info->dc_unc                    = talloc_asprintf(mem_ctx, "\\\\%s.%s",
1428                                                           lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx), 
1429                                                           lp_realm(dce_call->conn->dce_ctx->lp_ctx));
1430         W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1431         info->dc_address                = talloc_strdup(mem_ctx, "\\\\0.0.0.0");
1432         W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1433         info->dc_address_type           = DS_ADDRESS_TYPE_INET;
1434         info->domain_guid               = samdb_result_guid(res[0], "objectGUID");
1435         info->domain_name               = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
1436         info->forest_name               = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
1437         info->dc_flags                  = DS_DNS_FOREST |
1438                                           DS_DNS_DOMAIN |
1439                                           DS_DNS_CONTROLLER |
1440                                           DS_SERVER_WRITABLE |
1441                                           DS_SERVER_CLOSEST |
1442                                           DS_SERVER_TIMESERV |
1443                                           DS_SERVER_KDC |
1444                                           DS_SERVER_DS |
1445                                           DS_SERVER_LDAP |
1446                                           DS_SERVER_GC |
1447                                           DS_SERVER_PDC;
1448         info->dc_site_name      = talloc_strdup(mem_ctx, "Default-First-Site-Name");
1449         W_ERROR_HAVE_NO_MEMORY(info->dc_site_name);
1450         info->client_site_name  = talloc_strdup(mem_ctx, "Default-First-Site-Name");
1451         W_ERROR_HAVE_NO_MEMORY(info->client_site_name);
1452
1453         *r->out.info = info;
1454
1455         return WERR_OK;
1456 }
1457
1458 /* 
1459   netr_DsRGetDCNameEx
1460 */
1461 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1462                                   struct netr_DsRGetDCNameEx *r)
1463 {
1464         struct netr_DsRGetDCNameEx2 r2;
1465         WERROR werr;
1466
1467         ZERO_STRUCT(r2);
1468
1469         r2.in.server_unc = r->in.server_unc;
1470         r2.in.client_account = NULL;
1471         r2.in.mask = 0;
1472         r2.in.domain_guid = r->in.domain_guid;
1473         r2.in.domain_name = r->in.domain_name;
1474         r2.in.site_name = r->in.site_name;
1475         r2.in.flags = r->in.flags;
1476         r2.out.info = r->out.info;
1477
1478         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1479
1480         return werr;
1481 }
1482
1483 /* 
1484   netr_DsRGetDCName
1485 */
1486 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1487                                 struct netr_DsRGetDCName *r)
1488 {
1489         struct netr_DsRGetDCNameEx2 r2;
1490         WERROR werr;
1491
1492         ZERO_STRUCT(r2);
1493
1494         r2.in.server_unc = r->in.server_unc;
1495         r2.in.client_account = NULL;
1496         r2.in.mask = 0;
1497         r2.in.domain_name = r->in.domain_name;
1498         r2.in.domain_guid = r->in.domain_guid;
1499         
1500         r2.in.site_name = NULL; /* should fill in from site GUID */
1501         r2.in.flags = r->in.flags;
1502         r2.out.info = r->out.info;
1503
1504         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1505
1506         return werr;
1507 }
1508 /* 
1509   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN 
1510 */
1511 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1512                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1513 {
1514         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1515 }
1516
1517
1518 /*
1519   netr_NetrEnumerateTrustedDomainsEx
1520 */
1521 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1522                        struct netr_NetrEnumerateTrustedDomainsEx *r)
1523 {
1524         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1525 }
1526
1527
1528 /* 
1529   netr_DsRAddressToSitenamesExW 
1530 */
1531 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1532                        struct netr_DsRAddressToSitenamesExW *r)
1533 {
1534         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1535 }
1536
1537
1538 /* 
1539   netr_DsrGetDcSiteCoverageW
1540 */
1541 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1542                        struct netr_DsrGetDcSiteCoverageW *r)
1543 {
1544         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1545 }
1546
1547
1548 /* 
1549   netr_DsrEnumerateDomainTrusts 
1550 */
1551 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1552                                               struct netr_DsrEnumerateDomainTrusts *r)
1553 {
1554         struct netr_DomainTrustList *trusts;
1555         struct ldb_context *sam_ctx;
1556         int ret;
1557         struct ldb_message **dom_res;
1558         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1559
1560         ZERO_STRUCT(r->out);
1561
1562         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
1563         if (sam_ctx == NULL) {
1564                 return WERR_GENERAL_FAILURE;
1565         }
1566
1567         ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
1568                               &dom_res, dom_attrs);
1569         if (ret == -1) {
1570                 return WERR_GENERAL_FAILURE;            
1571         }
1572         if (ret != 1) {
1573                 return WERR_GENERAL_FAILURE;
1574         }
1575
1576         trusts = talloc(mem_ctx, struct netr_DomainTrustList);
1577         W_ERROR_HAVE_NO_MEMORY(trusts);
1578
1579         trusts->array = talloc_array(trusts, struct netr_DomainTrust, ret);
1580         W_ERROR_HAVE_NO_MEMORY(trusts->array);
1581
1582         trusts->count = 1; /* ?? */
1583
1584         r->out.trusts = trusts;
1585
1586         /* TODO: add filtering by trust_flags, and correct trust_type
1587            and attributes */
1588         trusts->array[0].netbios_name = lp_sam_name(dce_call->conn->dce_ctx->lp_ctx);
1589         trusts->array[0].dns_name     = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
1590         trusts->array[0].trust_flags =
1591                 NETR_TRUST_FLAG_TREEROOT | 
1592                 NETR_TRUST_FLAG_IN_FOREST | 
1593                 NETR_TRUST_FLAG_PRIMARY;
1594         trusts->array[0].parent_index = 0;
1595         trusts->array[0].trust_type = 2;
1596         trusts->array[0].trust_attributes = 0;
1597         trusts->array[0].sid  = samdb_result_dom_sid(mem_ctx, dom_res[0], "objectSid");
1598         trusts->array[0].guid = samdb_result_guid(dom_res[0], "objectGUID");
1599
1600         return WERR_OK;
1601 }
1602
1603
1604 /*
1605   netr_DsrDeregisterDNSHostRecords
1606 */
1607 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1608                        struct netr_DsrDeregisterDNSHostRecords *r)
1609 {
1610         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1611 }
1612
1613
1614 /*
1615   netr_ServerTrustPasswordsGet
1616 */
1617 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1618                        struct netr_ServerTrustPasswordsGet *r)
1619 {
1620         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1621 }
1622
1623
1624 /* 
1625   netr_DsRGetForestTrustInformation 
1626 */
1627 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1628                        struct netr_DsRGetForestTrustInformation *r)
1629 {
1630         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1631 }
1632
1633
1634 /*
1635   netr_GetForestTrustInformation
1636 */
1637 static WERROR dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1638                        struct netr_GetForestTrustInformation *r)
1639 {
1640         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1641 }
1642
1643
1644 /*
1645   netr_ServerGetTrustInfo
1646 */
1647 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1648                        struct netr_ServerGetTrustInfo *r)
1649 {
1650         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1651 }
1652
1653
1654 /* include the generated boilerplate */
1655 #include "librpc/gen_ndr/ndr_netlogon_s.c"