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