import HEAD into svn+ssh://svn.samba.org/home/svn/samba/trunk
[metze/old/v3-2-winbind-ndr.git] / source / libsmb / passchange.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB client password change routine
4    Copyright (C) Andrew Tridgell 1994-1998
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 #include "includes.h"
22
23 /*************************************************************
24 change a password on a remote machine using IPC calls
25 *************************************************************/
26 BOOL remote_password_change(const char *remote_machine, const char *user_name, 
27                             const char *old_passwd, const char *new_passwd,
28                             char *err_str, size_t err_str_len)
29 {
30         struct nmb_name calling, called;
31         struct cli_state cli;
32         struct in_addr ip;
33         struct ntuser_creds creds;
34
35         NTSTATUS result;
36
37         *err_str = '\0';
38
39         if(!resolve_name( remote_machine, &ip, 0x20)) {
40                 slprintf(err_str, err_str_len-1, "unable to find an IP address for machine %s.\n",
41                         remote_machine );
42                 return False;
43         }
44  
45         ZERO_STRUCT(cli);
46  
47         if (!cli_initialise(&cli) || !cli_connect(&cli, remote_machine, &ip)) {
48                 slprintf(err_str, err_str_len-1, "unable to connect to SMB server on machine %s. Error was : %s.\n",
49                         remote_machine, cli_errstr(&cli) );
50                 return False;
51         }
52   
53         make_nmb_name(&calling, global_myname() , 0x0);
54         make_nmb_name(&called , remote_machine, 0x20);
55         
56         if (!cli_session_request(&cli, &calling, &called)) {
57                 slprintf(err_str, err_str_len-1, "machine %s rejected the session setup. Error was : %s.\n",
58                         remote_machine, cli_errstr(&cli) );
59                 cli_shutdown(&cli);
60                 return False;
61         }
62   
63         cli.protocol = PROTOCOL_NT1;
64
65         if (!cli_negprot(&cli)) {
66                 slprintf(err_str, err_str_len-1, "machine %s rejected the negotiate protocol. Error was : %s.\n",        
67                         remote_machine, cli_errstr(&cli) );
68                 cli_shutdown(&cli);
69                 return False;
70         }
71   
72         /* Given things like SMB signing, restrict anonymous and the like, 
73            try an authenticated connection first */
74         if (!cli_session_setup(&cli, user_name, old_passwd, strlen(old_passwd)+1, old_passwd, strlen(old_passwd)+1, "")) {
75                 /*
76                  * We should connect as the anonymous user here, in case
77                  * the server has "must change password" checked...
78                  * Thanks to <Nicholas.S.Jenkins@cdc.com> for this fix.
79                  */
80
81                 if (!cli_session_setup(&cli, "", "", 0, "", 0, "")) {
82                         slprintf(err_str, err_str_len-1, "machine %s rejected the session setup. Error was : %s.\n",        
83                                  remote_machine, cli_errstr(&cli) );
84                         cli_shutdown(&cli);
85                         return False;
86                 }
87
88                 init_creds(&creds, "", "", NULL);
89                 cli_init_creds(&cli, &creds);
90         } else {
91                 init_creds(&creds, user_name, "", old_passwd);
92                 cli_init_creds(&cli, &creds);
93         }
94
95         if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) {
96                 slprintf(err_str, err_str_len-1, "machine %s rejected the tconX on the IPC$ share. Error was : %s.\n",
97                         remote_machine, cli_errstr(&cli) );
98                 cli_shutdown(&cli);
99                 return False;
100         }
101
102         /* Try not to give the password away to easily */
103
104         cli.pipe_auth_flags = AUTH_PIPE_NTLMSSP;
105         cli.pipe_auth_flags |= AUTH_PIPE_SIGN;
106         cli.pipe_auth_flags |= AUTH_PIPE_SEAL;
107         
108         if ( !cli_nt_session_open( &cli, PI_SAMR ) ) {
109                 if (lp_client_lanman_auth()) {
110                         if (!cli_oem_change_password(&cli, user_name, new_passwd, old_passwd)) {
111                                 slprintf(err_str, err_str_len-1, "machine %s rejected the password change: Error was : %s.\n",
112                                          remote_machine, cli_errstr(&cli) );
113                                 cli_shutdown(&cli);
114                                 return False;
115                         }
116                 } else {
117                         slprintf(err_str, err_str_len-1, "machine %s does not support SAMR connections, but LANMAN password changed are disabled\n",
118                                  remote_machine);
119                         cli_shutdown(&cli);
120                         return False;
121                 }
122         }
123
124         if (!NT_STATUS_IS_OK(result = cli_samr_chgpasswd_user(&cli, cli.mem_ctx, user_name, 
125                                                               new_passwd, old_passwd))) {
126
127                 if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) 
128                     || NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) {
129                         /* try the old Lanman method */
130                         if (lp_client_lanman_auth()) {
131                                 if (!cli_oem_change_password(&cli, user_name, new_passwd, old_passwd)) {
132                                         slprintf(err_str, err_str_len-1, "machine %s rejected the password change: Error was : %s.\n",
133                                                  remote_machine, cli_errstr(&cli) );
134                                         cli_shutdown(&cli);
135                                         return False;
136                                 }
137                         } else {
138                                 slprintf(err_str, err_str_len-1, "machine %s does not support SAMR connections, but LANMAN password changed are disabled\n",
139                                          remote_machine);
140                                 cli_shutdown(&cli);
141                                 return False;
142                         }
143                 } else {
144                         slprintf(err_str, err_str_len-1, "machine %s rejected the password change: Error was : %s.\n",
145                                  remote_machine, get_friendly_nt_error_msg(result));
146                         cli_shutdown(&cli);
147                         return False;
148                 }
149         }
150         cli_shutdown(&cli);
151         return True;
152 }