r1816: here's the initial idea of libnet
[kai/samba-autobuild/.git] / source4 / libnet / libnet_passwd.c
1 /* 
2    Unix SMB/CIFS implementation.
3    
4    Copyright (C) Stefan Metzmacher      2004
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 /*
22  * 1. connect to the SAMR pipe of *our* PDC
23  * 2. try samr_ChangePassword3
24  */
25 static NTSTATUS libnet_ChangePassword_rpc(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct net_ChangePassword *r)
26 {
27         NTSTATUS status;
28         struct dcerpc_pipe *p = NULL;
29         struct samr_ChangePasswordUser3 pw3;
30         struct samr_Name server, account;
31         struct samr_CryptPassword nt_pass, lm_pass;
32         struct samr_Password nt_verifier, lm_verifier;
33         uint8_t old_nt_hash[16], new_nt_hash[16];
34         uint8_t old_lm_hash[16], new_lm_hash[16];
35
36         /* connect to the SAMR pipe of the */
37         status = libnet_rpc_connect_pdc(ctx, mem_ctx,
38                                         r->rpc.in.domain_name,
39                                         DCERPC_SAMR_NAME,
40                                         DCERPC_SAMR_UUID,
41                                         DCERPC_SAMR_VERSION,
42                                         &p);
43         if (!NT_STATUS_IS_OK(status)) {
44                 r->rpc.out.error_string = talloc_asprintf(mem_ctx,
45                                                 "Connection to SAMR pipe of PDC of domain '%s' failed\n",
46                                                 r->rpc.in.domain_name);
47                 return status;
48         }
49
50         server.name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
51         init_samr_Name(&account, r->rpc.in.account_name);
52
53         E_md4hash(r->rpc.in.oldpassword, old_nt_hash);
54         E_md4hash(r->rpc.in.newpassword, new_nt_hash);
55
56         E_deshash(r->rpc.in.oldpassword, old_lm_hash);
57         E_deshash(r->rpc.in.newpassword, new_lm_hash);
58
59         encode_pw_buffer(lm_pass.data, r->rpc.in.newpassword, STR_UNICODE);
60         arcfour_crypt(lm_pass.data, old_nt_hash, 516);
61         E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
62
63         encode_pw_buffer(nt_pass.data,  r->rpc.in.newpassword, STR_UNICODE);
64         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
65         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
66
67         pw3.in.server = &server;
68         pw3.in.account = &account;
69         pw3.in.nt_password = &nt_pass;
70         pw3.in.nt_verifier = &nt_verifier;
71         pw3.in.lm_change = 1;
72         pw3.in.lm_password = &lm_pass;
73         pw3.in.lm_verifier = &lm_verifier;
74         pw3.in.password3 = NULL;
75
76         status = dcerpc_samr_ChangePassword3(p, mem_ctx, &pw3);
77         if (!NT_STATUS_IS_OK(status)) {
78                 r->rpc.out.error_string = talloc_asprintf(mem_ctx,
79                                                 "ChangePassword3 failed: %s\n",nt_errstr(status);
80                 return status;
81         }
82
83         if (!NT_STATUS_IS_OK(r->rpc.out.result)) {
84                 r->rpc.out.error_string = talloc_asprintf(mem_ctx,
85                                                 "ChangePassword3 for '%s\\%s' failed: %s\n",
86                                                 r->rpc.in.domain_name, r->rpc.in.account_name, 
87                                                 nt_errstr(status));
88                                                 /* TODO: give the reason of the reject */
89                 return status;
90         
91         }
92
93         dcerpc_diconnect(&p);
94
95         return NT_STATUS_OK;
96 }
97
98 static NTSTATUS libnet_ChangePassword_generic(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct net_ChangePassword *r)
99 {
100         return NT_STATUS_NOT_IMPLEMTED;
101 }
102
103 NTSTATUS libnet_ChangePassword(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct net_ChangePassword *r)
104 {
105         switch (r->generic.level) {
106                 case LIBNET_CHANGE_PASSWORD_GENERIC:
107                         return libnet_ChangePassword_generic(ctx, mem_ctx, r);
108                 case LIBNET_CHANGE_PASSWORD_RPC:
109                         return libnet_ChangePassword_rpc(ctx, mem_ctx, r);
110                 case LIBNET_CHANGE_PASSWORD_ADS:
111                         return NT_STATUS_NOT_IMPLEMTED;
112                 case LIBNET_CHANGE_PASSWORD_RAP:
113                         return NT_STATUS_NOT_IMPLEMTED;
114         }
115
116         return NT_STATUS_INVALID_LEVEL;
117 }