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