f001040682a429fcf11c44297083bf30be8701fb
[samba.git] / source3 / passdb / smbpasschange.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    change a password in a local smbpasswd file
5    Copyright (C) Andrew Tridgell 1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24
25 /*************************************************************
26 add a new user to the local smbpasswd file
27 *************************************************************/
28 static BOOL add_new_user(char *user_name, uid_t uid, BOOL trust_account, 
29                          BOOL disable_user, BOOL set_no_password,
30                          uchar *new_p16, uchar *new_nt_p16)
31 {
32         struct smb_passwd new_smb_pwent;
33
34         pwdb_init_smb(&new_smb_pwent);
35
36         /* Create a new smb passwd entry and set it to the given password. */
37         new_smb_pwent.unix_uid = uid;
38         new_smb_pwent.nt_name = user_name; 
39         new_smb_pwent.smb_passwd = NULL;
40         new_smb_pwent.smb_nt_passwd = NULL;
41         new_smb_pwent.acct_ctrl = (trust_account ? ACB_WSTRUST : ACB_NORMAL);
42         
43         if(disable_user) {
44                 new_smb_pwent.acct_ctrl |= ACB_DISABLED;
45         } else if (set_no_password) {
46                 new_smb_pwent.acct_ctrl |= ACB_PWNOTREQ;
47         } else {
48                 new_smb_pwent.smb_passwd = new_p16;
49                 new_smb_pwent.smb_nt_passwd = new_nt_p16;
50         }
51         
52         return add_smbpwd_entry(&new_smb_pwent);
53 }
54
55
56 /*************************************************************
57 change a password entry in the local smbpasswd file
58 *************************************************************/
59 BOOL local_password_change(char *user_name, BOOL trust_account, BOOL add_user,
60                            BOOL enable_user, BOOL disable_user, BOOL set_no_password,
61                            char *new_passwd, 
62                            char *err_str, size_t err_str_len,
63                            char *msg_str, size_t msg_str_len)
64 {
65         struct passwd  *pwd;
66         struct smb_passwd *smb_pwent;
67         uchar           new_p16[16];
68         uchar           new_nt_p16[16];
69         fstring unix_name;
70         uid_t unix_uid;
71
72         *err_str = '\0';
73         *msg_str = '\0';
74
75         pwd = getpwnam(user_name);
76         
77         /*
78          * Check for a machine account.
79          */
80         
81         if (pwd == NULL)
82         {
83                 if (trust_account)
84                 {
85                         slprintf(err_str, err_str_len - 1, "User %s does not \
86 exist in system password file (usually /etc/passwd).  \
87 Cannot add machine account without a valid system user.\n", user_name);
88                 }
89                 else
90                 {
91                         slprintf(err_str, err_str_len - 1, "User %s does not \
92 exist in system password file (usually /etc/passwd).\n", user_name);
93                 }
94                 return False;
95         }
96
97         unix_uid = pwd->pw_uid;
98         fstrcpy(unix_name, pwd->pw_name);
99
100         /* Calculate the MD4 hash (NT compatible) of the new password. */
101         nt_lm_owf_gen(new_passwd, new_nt_p16, new_p16);
102
103         /* Get the smb passwd entry for this user */
104         smb_pwent = getsmbpwnam(user_name);
105         if (smb_pwent == NULL) {
106                 if(add_user == False) {
107                         slprintf(err_str, err_str_len-1,
108                                 "Failed to find entry for user %s.\n", unix_name);
109                         return False;
110                 }
111
112                 if (add_new_user(user_name, unix_uid, trust_account, disable_user,
113                                  set_no_password, new_p16, new_nt_p16)) {
114                         slprintf(msg_str, msg_str_len-1, "Added user %s.\n", user_name);
115                         return True;
116                 } else {
117                         slprintf(err_str, err_str_len-1, "Failed to add entry for user %s.\n", user_name);
118                         return False;
119                 }
120         } else {
121                 /* the entry already existed */
122                 add_user = False;
123         }
124
125         /*
126          * We are root - just write the new password
127          * and the valid last change time.
128          */
129
130         if(disable_user) {
131                 smb_pwent->acct_ctrl |= ACB_DISABLED;
132         } else if (enable_user) {
133                 if(smb_pwent->smb_passwd == NULL) {
134                         smb_pwent->smb_passwd = new_p16;
135                         smb_pwent->smb_nt_passwd = new_nt_p16;
136                 }
137                 smb_pwent->acct_ctrl &= ~ACB_DISABLED;
138         } else if (set_no_password) {
139                 smb_pwent->acct_ctrl |= ACB_PWNOTREQ;
140                 /* This is needed to preserve ACB_PWNOTREQ in mod_smbfilepwd_entry */
141                 smb_pwent->smb_passwd = NULL;
142                 smb_pwent->smb_nt_passwd = NULL;
143         } else {
144                 smb_pwent->acct_ctrl &= ~ACB_PWNOTREQ;
145                 smb_pwent->smb_passwd = new_p16;
146                 smb_pwent->smb_nt_passwd = new_nt_p16;
147         }
148         
149         if(mod_smbpwd_entry(smb_pwent,True) == False) {
150                 slprintf(err_str, err_str_len-1, "Failed to modify entry for user %s.\n",
151                         unix_name);
152                 return False;
153         }
154
155         return True;
156 }