the password database updates from 2.0. This is mostly the fix for the
[Samba/gbeck.git] / source / passdb / smbpasschange.c
blob9d0aecf8b8a296ad71e54f8482e70bfbb2c7ac38
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
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.
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.
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.
22 #include "includes.h"
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)
32 struct smb_passwd new_smb_pwent;
34 /* Create a new smb passwd entry and set it to the given password. */
35 new_smb_pwent.smb_userid = uid;
36 new_smb_pwent.smb_name = user_name;
37 new_smb_pwent.smb_passwd = NULL;
38 new_smb_pwent.smb_nt_passwd = NULL;
39 new_smb_pwent.acct_ctrl = (trust_account ? ACB_WSTRUST : ACB_NORMAL);
41 if(disable_user) {
42 new_smb_pwent.acct_ctrl |= ACB_DISABLED;
43 } else if (set_no_password) {
44 new_smb_pwent.acct_ctrl |= ACB_PWNOTREQ;
45 } else {
46 new_smb_pwent.smb_passwd = new_p16;
47 new_smb_pwent.smb_nt_passwd = new_nt_p16;
50 return add_smbpwd_entry(&new_smb_pwent);
54 /*************************************************************
55 change a password entry in the local smbpasswd file
56 *************************************************************/
58 BOOL local_password_change(char *user_name, BOOL trust_account, BOOL add_user,
59 BOOL enable_user, BOOL disable_user, BOOL set_no_password,
60 char *new_passwd,
61 char *err_str, size_t err_str_len,
62 char *msg_str, size_t msg_str_len)
64 struct passwd *pwd;
65 void *vp;
66 struct smb_passwd *smb_pwent;
67 uchar new_p16[16];
68 uchar new_nt_p16[16];
70 *err_str = '\0';
71 *msg_str = '\0';
73 pwd = sys_getpwnam(user_name);
76 * Check for a local account.
79 if(!pwd) {
80 slprintf(err_str, err_str_len - 1, "User %s does not \
81 exist in system password file (usually /etc/passwd). Cannot add \
82 account without a valid local system user.\n", user_name);
83 return False;
86 /* Calculate the MD4 hash (NT compatible) of the new password. */
87 nt_lm_owf_gen(new_passwd, new_nt_p16, new_p16);
90 * Open the smbpaswd file.
92 vp = startsmbpwent(True);
93 if (!vp && errno == ENOENT) {
94 FILE *fp;
95 slprintf(msg_str,msg_str_len-1,
96 "smbpasswd file did not exist - attempting to create it.\n");
97 fp = sys_fopen(lp_smb_passwd_file(), "w");
98 if (fp) {
99 fprintf(fp, "# Samba SMB password file\n");
100 fclose(fp);
101 vp = startsmbpwent(True);
105 if (!vp) {
106 slprintf(err_str, err_str_len-1, "Cannot open file %s. Error was %s\n",
107 lp_smb_passwd_file(), strerror(errno) );
108 return False;
111 /* Get the smb passwd entry for this user */
112 smb_pwent = getsmbpwnam(user_name);
113 if (smb_pwent == NULL) {
114 if(add_user == False) {
115 slprintf(err_str, err_str_len-1,
116 "Failed to find entry for user %s.\n", pwd->pw_name);
117 endsmbpwent(vp);
118 return False;
121 if (add_new_user(user_name, pwd->pw_uid, trust_account, disable_user,
122 set_no_password, new_p16, new_nt_p16)) {
123 slprintf(msg_str, msg_str_len-1, "Added user %s.\n", user_name);
124 endsmbpwent(vp);
125 return True;
126 } else {
127 slprintf(err_str, err_str_len-1, "Failed to add entry for user %s.\n", user_name);
128 endsmbpwent(vp);
129 return False;
131 } else {
132 /* the entry already existed */
133 add_user = False;
137 * We are root - just write the new password
138 * and the valid last change time.
141 if(disable_user) {
142 smb_pwent->acct_ctrl |= ACB_DISABLED;
143 } else if (enable_user) {
144 if(smb_pwent->smb_passwd == NULL) {
145 smb_pwent->smb_passwd = new_p16;
146 smb_pwent->smb_nt_passwd = new_nt_p16;
148 smb_pwent->acct_ctrl &= ~ACB_DISABLED;
149 } else if (set_no_password) {
150 smb_pwent->acct_ctrl |= ACB_PWNOTREQ;
151 /* This is needed to preserve ACB_PWNOTREQ in mod_smbfilepwd_entry */
152 smb_pwent->smb_passwd = NULL;
153 smb_pwent->smb_nt_passwd = NULL;
154 } else {
156 * If we're dealing with setting a completely empty user account
157 * ie. One with a password of 'XXXX', but not set disabled (like
158 * an account created from scratch) then if the old password was
159 * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
160 * We remove that as we're giving this user their first password
161 * and the decision hasn't really been made to disable them (ie.
162 * don't create them disabled). JRA.
164 if((smb_pwent->smb_passwd == NULL) && (smb_pwent->acct_ctrl & ACB_DISABLED))
165 smb_pwent->acct_ctrl &= ~ACB_DISABLED;
166 smb_pwent->acct_ctrl &= ~ACB_PWNOTREQ;
167 smb_pwent->smb_passwd = new_p16;
168 smb_pwent->smb_nt_passwd = new_nt_p16;
171 if(mod_smbpwd_entry(smb_pwent,True) == False) {
172 slprintf(err_str, err_str_len-1, "Failed to modify entry for user %s.\n",
173 pwd->pw_name);
174 endsmbpwent(vp);
175 return False;
178 endsmbpwent(vp);
180 return True;