r754: Implement the SetPassword operation on the netlogon pipe.
[abartlet/samba.git/.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
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "rpc_server/common/common.h"
25
26 struct server_pipe_state {
27         TALLOC_CTX *mem_ctx;
28         struct netr_Credential client_challenge;
29         struct netr_Credential server_challenge;
30         BOOL authenticated;
31         char *account_name;
32         char *computer_name;  /* for logging only */
33         uint32 acct_flags;
34         uint16 sec_chan_type;
35         struct creds_CredentialState *creds;
36 };
37
38 static NTSTATUS netlogon_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *di) 
39 {
40         dce_call->conn->private = NULL;
41
42         return NT_STATUS_OK;
43 }
44
45 /* this function is called when the client disconnects the endpoint */
46 static void netlogon_unbind(struct dcesrv_connection *conn, const struct dcesrv_interface *di) 
47 {
48         struct server_pipe_state *pipe_state = conn->private;
49
50         if (pipe_state)
51                 talloc_destroy(pipe_state->mem_ctx);
52         
53         conn->private = NULL;
54 }
55
56 #define DCESRV_INTERFACE_NETLOGON_BIND netlogon_bind
57 #define DCESRV_INTERFACE_NETLOGON_UNBIND netlogon_unbind
58
59 /* 
60   netr_ServerReqChallenge 
61
62         NTSTATUS netr_ServerReqChallenge(
63                 [in]        unistr *server_name,
64                 [in]        unistr computer_name,
65                 [in][out]   netr_Credential credentials
66                 );
67
68 */
69 static NTSTATUS netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
70                                         struct netr_ServerReqChallenge *r)
71 {
72         struct server_pipe_state *pipe_state = dce_call->conn->private;
73         TALLOC_CTX *pipe_mem_ctx;
74
75         ZERO_STRUCT(r->out.credentials);
76
77         /* destroyed on pipe shutdown */
78
79         if (pipe_state) {
80                 talloc_destroy(pipe_state->mem_ctx);
81                 dce_call->conn->private = NULL;
82         }
83         
84         pipe_mem_ctx = talloc_init("internal netlogon pipe state for %s", 
85                                    r->in.computer_name);
86         
87         if (!pipe_mem_ctx) {
88                 return NT_STATUS_NO_MEMORY;
89         }
90
91         pipe_state = talloc_p(pipe_mem_ctx, struct server_pipe_state);
92         if (!pipe_state) {
93                 talloc_destroy(pipe_mem_ctx);
94                 return NT_STATUS_NO_MEMORY;
95         }
96
97         pipe_state->mem_ctx = pipe_mem_ctx;
98         pipe_state->authenticated = False;
99         pipe_state->creds = NULL;
100         pipe_state->account_name = NULL;
101         pipe_state->computer_name = NULL;
102
103         pipe_state->client_challenge = r->in.credentials;
104
105         generate_random_buffer(pipe_state->server_challenge.data, 
106                                sizeof(pipe_state->server_challenge.data),
107                                False);
108
109         r->out.credentials = pipe_state->server_challenge;
110
111         dce_call->conn->private = pipe_state;
112
113         return NT_STATUS_OK;
114 }
115
116
117 /* 
118   netr_ServerAuthenticate 
119
120          secure channel types:
121  
122         const int SEC_CHAN_WKSTA   = 2;
123         const int SEC_CHAN_DOMAIN  = 4;
124         const int SEC_CHAN_BDC     = 6;
125
126         NTSTATUS netr_ServerAuthenticate(
127                 [in]        unistr *server_name,
128                 [in]        unistr username,
129                 [in]        uint16 secure_channel_type,
130                 [in]        unistr computer_name,
131                 [in,out]    netr_Credential credentials
132                 );
133
134
135 */
136
137 static NTSTATUS netr_ServerAuthenticateInternals(struct server_pipe_state *pipe_state,
138                                                  TALLOC_CTX *mem_ctx,
139                                                  const char *account_name, 
140                                                  const char *computer_name, 
141                                                  uint16 secure_channel_type,
142                                                  uint32 in_flags,
143                                                  const struct netr_Credential *client_credentials,
144                                                  struct netr_Credential *server_credentials,
145                                                  uint32 *out_flags) 
146 {
147         void *sam_ctx;
148         uint8 *mach_pwd;
149         uint16 acct_flags;
150         int num_records;
151         struct ldb_message **msgs;
152         NTSTATUS nt_status;
153
154         const char *attrs[] = {"unicodePwd", "lmPwdHash", "ntPwdHash", 
155                                "userAccountControl", NULL 
156         };
157
158         ZERO_STRUCTP(server_credentials);
159         if (out_flags) {
160                 *out_flags = 0;
161         }
162
163         if (!pipe_state) {
164                 DEBUG(1, ("No challange requested by client, cannot authenticate\n"));
165                 return NT_STATUS_ACCESS_DENIED;
166         }
167
168         sam_ctx = samdb_connect();
169         if (sam_ctx == NULL) {
170                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
171         }
172         /* pull the user attributes */
173         num_records = samdb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
174                                    "(&(sAMAccountName=%s)(objectclass=user))", 
175                                    account_name);
176
177         if (num_records == 0) {
178                 DEBUG(3,("Couldn't find user [%s] in samdb.\n", 
179                          account_name));
180                 samdb_close(sam_ctx);
181                 return NT_STATUS_NO_SUCH_USER;
182         }
183
184         if (num_records > 1) {
185                 DEBUG(1,("Found %d records matching user [%s]\n", num_records, account_name));
186                 samdb_close(sam_ctx);
187                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
188         }
189
190         acct_flags = samdb_result_acct_flags(msgs[0], 
191                                              "userAccountControl");
192
193         if (acct_flags & ACB_DISABLED) {
194                 DEBUG(1, ("Account [%s] is disabled\n", account_name));
195                 return NT_STATUS_ACCESS_DENIED;
196         }
197
198         if (secure_channel_type == SEC_CHAN_WKSTA) {
199                 if (!(acct_flags & ACB_WSTRUST)) {
200                         DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", acct_flags));
201                         return NT_STATUS_ACCESS_DENIED;
202                 }
203         } else if (secure_channel_type == SEC_CHAN_DOMAIN) {
204                 if (!(acct_flags & ACB_DOMTRUST)) {
205                         DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", acct_flags));
206                         return NT_STATUS_ACCESS_DENIED;
207                 }
208         } else if (secure_channel_type == SEC_CHAN_BDC) {
209                 if (!(acct_flags & ACB_SVRTRUST)) {
210                         DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", acct_flags));
211                         return NT_STATUS_ACCESS_DENIED;
212                 }
213         } else {
214                 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n", secure_channel_type));
215                 return NT_STATUS_ACCESS_DENIED;
216         }
217
218         pipe_state->acct_flags = acct_flags;
219         pipe_state->sec_chan_type = secure_channel_type;
220
221         if (!NT_STATUS_IS_OK(nt_status = samdb_result_passwords(mem_ctx, msgs[0], 
222                                                                 NULL, &mach_pwd))) {
223                 samdb_close(sam_ctx);
224                 return NT_STATUS_ACCESS_DENIED;
225         }
226
227         samdb_close(sam_ctx);
228
229         if (!pipe_state->creds) {
230                 pipe_state->creds = talloc_p(pipe_state->mem_ctx, struct creds_CredentialState);
231                 if (!pipe_state->creds) {
232                         return NT_STATUS_NO_MEMORY;
233                 }
234         }
235
236         creds_server_init(pipe_state->creds, &pipe_state->client_challenge, 
237                           &pipe_state->server_challenge, mach_pwd,
238                           server_credentials);
239
240         if (!creds_server_check(pipe_state->creds, client_credentials)) {
241                 return NT_STATUS_ACCESS_DENIED;
242         }
243
244         pipe_state->authenticated = True;
245
246         if (pipe_state->account_name) {
247                 /* We don't want a memory leak on this long-lived talloc context */
248                 talloc_free(pipe_state->mem_ctx, pipe_state->account_name);
249         }
250
251         pipe_state->account_name = talloc_strdup(pipe_state->mem_ctx, account_name);
252         
253         if (pipe_state->computer_name) {
254                 /* We don't want a memory leak on this long-lived talloc context */
255                 talloc_free(pipe_state->mem_ctx, pipe_state->account_name);
256         }
257
258         pipe_state->computer_name = talloc_strdup(pipe_state->mem_ctx, computer_name);
259         
260         if (out_flags) {
261                 *out_flags = NETLOGON_NEG_AUTH2_FLAGS;
262         }
263
264         return NT_STATUS_OK;
265 }
266                                                  
267
268 static NTSTATUS netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
269                                         struct netr_ServerAuthenticate *r)
270 {
271         struct server_pipe_state *pipe_state = dce_call->conn->private;
272         
273         return netr_ServerAuthenticateInternals(pipe_state,
274                                                 mem_ctx,
275                                                 r->in.username,
276                                                 r->in.computer_name,
277                                                 r->in.secure_channel_type,
278                                                 0,
279                                                 &r->in.credentials,
280                                                 &r->out.credentials,
281                                                 NULL); 
282 }
283
284 static NTSTATUS netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
285                                         struct netr_ServerAuthenticate2 *r)
286 {
287         struct server_pipe_state *pipe_state = dce_call->conn->private;
288         
289         return netr_ServerAuthenticateInternals(pipe_state,
290                                                 mem_ctx,
291                                                 r->in.username,
292                                                 r->in.computer_name,
293                                                 r->in.secure_channel_type,
294                                                 *r->in.negotiate_flags,
295                                                 &r->in.credentials,
296                                                 &r->out.credentials,
297                                                 r->out.negotiate_flags); 
298 }
299
300 static BOOL netr_creds_server_step_check(struct server_pipe_state *pipe_state,
301                                          struct netr_Authenticator *received_authenticator,
302                                          struct netr_Authenticator *return_authenticator) 
303 {
304         if (!pipe_state->authenticated) {
305                 return False;
306         }
307         return creds_server_step_check(pipe_state->creds, 
308                                        received_authenticator, 
309                                        return_authenticator);
310 }
311
312 /* 
313  netr_ServerPasswordSet 
314
315         NTSTATUS netr_ServerPasswordSet(
316                 [in]  unistr *server_name,
317                 [in]  unistr username,
318                 [in]  uint16 secure_channel_type,
319                 [in]  unistr computer_name,
320                 [in]  netr_Authenticator credential,
321                 [in]  netr_Password new_password,
322                 [out] netr_Authenticator return_authenticator
323                 );
324
325 */
326 static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
327                                        struct netr_ServerPasswordSet *r)
328 {
329         struct server_pipe_state *pipe_state = dce_call->conn->private;
330
331         void *sam_ctx;
332         int num_records;
333         int num_records_domain;
334         int ret;
335         int i;
336         struct ldb_message **msgs;
337         struct ldb_message **msgs_domain;
338         NTSTATUS nt_status;
339         struct samr_Hash newNtHash;
340         struct ldb_message mod, *msg_set_pw = &mod;
341         const char *domain_dn;
342         struct dom_sid *domain_sid;
343
344         const char *attrs[] = {"objectSid", NULL 
345         };
346
347         const char **domain_attrs = attrs;
348         ZERO_STRUCT(mod);
349
350         if (!netr_creds_server_step_check(pipe_state, &r->in.credential, &r->out.return_authenticator)) {
351                 return NT_STATUS_ACCESS_DENIED;
352         }
353
354         if (!pipe_state) {
355                 DEBUG(1, ("No challange requested by client, cannot authenticate\n"));
356                 return NT_STATUS_ACCESS_DENIED;
357         }
358
359         sam_ctx = samdb_connect();
360         if (sam_ctx == NULL) {
361                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
362         }
363         /* pull the user attributes */
364         num_records = samdb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
365                                    "(&(sAMAccountName=%s)(objectclass=user))", 
366                                    pipe_state->account_name);
367
368         if (num_records == 0) {
369                 DEBUG(3,("Couldn't find user [%s] in samdb.\n", 
370                          pipe_state->account_name));
371                 samdb_close(sam_ctx);
372                 return NT_STATUS_NO_SUCH_USER;
373         }
374
375         if (num_records > 1) {
376                 DEBUG(1,("Found %d records matching user [%s]\n", num_records, 
377                          pipe_state->account_name));
378                 samdb_close(sam_ctx);
379                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
380         }
381
382         domain_sid = dom_sid_parse_talloc(mem_ctx, 
383                                           samdb_result_string(msgs[0], 
384                                                               "objectSid", 
385                                                               NULL));
386         if (!domain_sid) {
387                 samdb_close(sam_ctx);
388                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
389         }
390
391         sid_split_rid(domain_sid, NULL);
392
393         /* find the domain's DN */
394         num_records_domain = samdb_search(sam_ctx, mem_ctx, NULL, 
395                                           &msgs_domain, domain_attrs,
396                                           "(&(objectSid=%s)(objectclass=domain))", 
397                                           dom_sid_string(mem_ctx, domain_sid));
398
399         if (num_records_domain == 0) {
400                 DEBUG(3,("check_sam_security: Couldn't find domain [%s] in passdb file.\n", 
401                          dom_sid_string(mem_ctx, domain_sid)));
402                 samdb_close(sam_ctx);
403                 return NT_STATUS_NO_SUCH_USER;
404         }
405
406         if (num_records_domain > 1) {
407                 DEBUG(1,("Found %d records matching domain [%s]\n", num_records_domain, dom_sid_string(mem_ctx, domain_sid)));
408                 samdb_close(sam_ctx);
409                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
410         }
411
412         domain_dn = msgs_domain[0]->dn;
413         
414         mod.dn = talloc_strdup(mem_ctx, msgs[0]->dn);
415         if (!mod.dn) {
416                 samdb_close(sam_ctx);
417                 return NT_STATUS_NO_MEMORY;
418         }
419         
420         creds_des_decrypt(pipe_state->creds, &r->in.new_password);
421
422         memcpy(newNtHash.hash, r->in.new_password.data, sizeof(newNtHash.hash));
423
424         /* set the password - samdb needs to know both the domain and user DNs,
425            so the domain password policy can be used */
426         nt_status = samdb_set_password(sam_ctx, mem_ctx,
427                                        msgs[0]->dn, domain_dn,
428                                        msg_set_pw, 
429                                        NULL, /* Don't have plaintext */
430                                        NULL, &newNtHash,
431                                        False /* This is not considered a password change */);
432         
433         if (!NT_STATUS_IS_OK(nt_status)) {
434                 samdb_close(sam_ctx);
435                 return nt_status;
436         }
437
438         /* mark all the message elements as LDB_FLAG_MOD_REPLACE, 
439            unless they are already marked with some other flag */
440         for (i=0;i<mod.num_elements;i++) {
441                 if (mod.elements[i].flags == 0) {
442                         mod.elements[i].flags = LDB_FLAG_MOD_REPLACE;
443                 }
444         }
445
446         ret = samdb_modify(sam_ctx, mem_ctx, msg_set_pw);
447         if (ret != 0) {
448                 /* we really need samdb.c to return NTSTATUS */
449
450                 samdb_close(sam_ctx);
451                 return NT_STATUS_UNSUCCESSFUL;
452         }
453
454         samdb_close(sam_ctx);
455         return NT_STATUS_OK;
456 }
457
458
459 /* 
460   netr_LogonUasLogon 
461 */
462 static WERROR netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
463                        struct netr_LogonUasLogon *r)
464 {
465         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
466 }
467
468
469 /* 
470   netr_LogonUasLogoff 
471 */
472 static WERROR netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
473                        struct netr_LogonUasLogoff *r)
474 {
475         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
476 }
477
478
479 /* 
480   netr_LogonSamLogon 
481
482
483
484 */
485 static NTSTATUS netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
486                        struct netr_LogonSamLogon *r)
487 {
488         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
489 }
490
491
492 /* 
493   netr_LogonSamLogoff 
494 */
495 static NTSTATUS netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
496                        struct netr_LogonSamLogoff *r)
497 {
498         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
499 }
500
501
502
503 /* 
504   netr_DatabaseDeltas 
505 */
506 static NTSTATUS netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
507                        struct netr_DatabaseDeltas *r)
508 {
509         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
510 }
511
512
513 /* 
514   netr_DatabaseSync 
515 */
516 static NTSTATUS netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
517                        struct netr_DatabaseSync *r)
518 {
519         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
520 }
521
522
523 /* 
524   netr_AccountDeltas 
525 */
526 static NTSTATUS netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
527                        struct netr_AccountDeltas *r)
528 {
529         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
530 }
531
532
533 /* 
534   netr_AccountSync 
535 */
536 static NTSTATUS netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
537                        struct netr_AccountSync *r)
538 {
539         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
540 }
541
542
543 /* 
544   netr_GetDcName 
545 */
546 static NTSTATUS netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
547                        struct netr_GetDcName *r)
548 {
549         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
550 }
551
552
553 /* 
554   netr_LogonControl 
555 */
556 static WERROR netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
557                        struct netr_LogonControl *r)
558 {
559         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
560 }
561
562
563 /* 
564   netr_GetAnyDCName 
565 */
566 static WERROR netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
567                        struct netr_GetAnyDCName *r)
568 {
569         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
570 }
571
572
573 /* 
574   netr_LogonControl2 
575 */
576 static WERROR netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
577                        struct netr_LogonControl2 *r)
578 {
579         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
580 }
581
582
583 /* 
584   netr_DatabaseSync2 
585 */
586 static NTSTATUS netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
587                        struct netr_DatabaseSync2 *r)
588 {
589         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
590 }
591
592
593 /* 
594   netr_DatabaseRedo 
595 */
596 static NTSTATUS netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
597                        struct netr_DatabaseRedo *r)
598 {
599         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
600 }
601
602
603 /* 
604   netr_LogonControl2Ex 
605 */
606 static WERROR netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
607                        struct netr_LogonControl2Ex *r)
608 {
609         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
610 }
611
612
613 /* include the generated boilerplate */
614 #include "librpc/gen_ndr/ndr_netlogon_s.c"