Preventing password changes on remote computers (encrypted
passwords)
Beau Kuiper
ekuiperba at cc.curtin.edu.au
Wed Mar 10 15:34:24 GMT 1999
Hello All,
I needed to be able to prevent the users on a network I am setting
up from changing the special guest account we have set up. We
are using samba as a PDC on a win 95/win 98 network. We use
encrypted passwords so we could have a separate unix user list to
the samba users list.
Now instead of asking someone for a solution to my problem, I
actually coded one myself. I have attached a patch doing this.
WHAT THE PATCH DOES AND HOW IT DOES IT:
I needed individual account control. Ie i wanted normal users to
be able to change their passwords easily, but not change the
guest accounts password. So i added a new setting to the
smbpasswd database file in the ACB field. I increased the size
of the field to 12 characters. I added a new character that can be
inserted, and thought 'P' would do nicely for my job. I added the
constant ACB_PWLOCK 0x0800 so it works much like the other
settings in that field. The way i prevent password changes ( i have
no idea if i did it correctly ) was to check for ACB_PWLOCK after the
password is loaded for changing in smbd/chgpasswd.c. If it
is set, then i change the return value so the password doesn't get
changed and the user is told incorrect old password. But it worked
of me :)
I also modified smbpasswd, and added the -p option, which when
used to add a user or change their password, will put the 'P'
character in the ACB field in smbpasswd. Unfortunately i haven't got a
way to switch it off yet :(, but you can always edit the smbpasswd
file manual and delete the 'P' char.
The patch applies cleanly to samba 2.0.3. It is a context patch (3 lines
context (and i managed to get a normal diff, not a reversed diff :).
To apply:
1) goto the dir above the samba-2.0.3 dir (eg if the dir for the
samba source is /usr/src/samba-2.0.3, goto the /usr/src dir)
2) run the command
patch -p0 < lockedpasswords.samba.2-0-3.patch
Then just make samba as usual.
THANKS TO THE SAMBA DEVELOPMENT TEAM / COMMUNITY:
I found modifying the samba code really easy. Thanks for keeping the
source code easy to read and understand. I use samba on as a PDC on
a school network since NT doesn't ship with quotas. I have found samba's
performance and flexibility legendary. I look forward to using the full PDC
features *evil grin*. I hope you find my patch useful.
Please feel free to contact me if you want help / want to flame or want to
shoot me. I don't get enough email :)
Beau Kuiper
ekuiperba at cc.curtin.edu.au
-------------- next part --------------
diff -C 3 -r old/samba-2.0.3/source/include/proto.h samba-2.0.3/source/include/proto.h
*** old/samba-2.0.3/source/include/proto.h Sun Feb 28 06:08:59 1999
--- samba-2.0.3/source/include/proto.h Wed Mar 10 22:12:23 1999
***************
*** 1260,1265 ****
--- 1260,1266 ----
BOOL local_password_change(char *user_name, BOOL trust_account, BOOL add_user,
BOOL enable_user, BOOL disable_user, BOOL set_no_password,
+ BOOL password_locked,
char *new_passwd,
char *err_str, size_t err_str_len,
char *msg_str, size_t msg_str_len);
diff -C 3 -r old/samba-2.0.3/source/include/smb.h samba-2.0.3/source/include/smb.h
*** old/samba-2.0.3/source/include/smb.h Sun Feb 28 06:08:59 1999
--- samba-2.0.3/source/include/smb.h Wed Mar 10 02:57:00 1999
***************
*** 366,372 ****
#define ACB_SVRTRUST 0x0100 /* 1 = Server trust account */
#define ACB_PWNOEXP 0x0200 /* 1 = User password does not expire */
#define ACB_AUTOLOCK 0x0400 /* 1 = Account auto locked */
!
#define MAX_HOURS_LEN 32
struct sam_passwd
--- 366,373 ----
#define ACB_SVRTRUST 0x0100 /* 1 = Server trust account */
#define ACB_PWNOEXP 0x0200 /* 1 = User password does not expire */
#define ACB_AUTOLOCK 0x0400 /* 1 = Account auto locked */
! #define ACB_PWLOCK 0x0800 /* 1 = Password Unchangeable */
!
#define MAX_HOURS_LEN 32
struct sam_passwd
***************
*** 1704,1710 ****
* Size of new password account encoding string. DO NOT CHANGE.
*/
! #define NEW_PW_FORMAT_SPACE_PADDED_LEN 14
/*
Do you want session setups at user level security with a invalid
--- 1705,1711 ----
* Size of new password account encoding string. DO NOT CHANGE.
*/
! #define NEW_PW_FORMAT_SPACE_PADDED_LEN 15
/*
Do you want session setups at user level security with a invalid
diff -C 3 -r old/samba-2.0.3/source/passdb/passdb.c samba-2.0.3/source/passdb/passdb.c
*** old/samba-2.0.3/source/passdb/passdb.c Sat Feb 6 10:17:50 1999
--- samba-2.0.3/source/passdb/passdb.c Wed Mar 10 04:02:24 1999
***************
*** 535,541 ****
if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X';
if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
!
for ( ; i < length - 2 ; i++ ) { acct_str[i] = ' '; }
i = length - 2;
--- 535,542 ----
if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X';
if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
! if (acct_ctrl & ACB_PWLOCK ) acct_str[i++] = 'P';
!
for ( ; i < length - 2 ; i++ ) { acct_str[i] = ' '; }
i = length - 2;
***************
*** 580,585 ****
--- 581,587 ----
case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
+ case 'P': { acct_ctrl |= ACB_PWLOCK ; break; /* 'P'assword cannot be changed. */ }
case ' ': { break; }
case ':':
case '\n':
diff -C 3 -r old/samba-2.0.3/source/passdb/smbpasschange.c samba-2.0.3/source/passdb/smbpasschange.c
*** old/samba-2.0.3/source/passdb/smbpasschange.c Sun Feb 28 06:09:01 1999
--- samba-2.0.3/source/passdb/smbpasschange.c Wed Mar 10 22:09:58 1999
***************
*** 57,62 ****
--- 57,63 ----
BOOL local_password_change(char *user_name, BOOL trust_account, BOOL add_user,
BOOL enable_user, BOOL disable_user, BOOL set_no_password,
+ BOOL password_locked,
char *new_passwd,
char *err_str, size_t err_str_len,
char *msg_str, size_t msg_str_len)
***************
*** 168,173 ****
--- 169,178 ----
smb_pwent->smb_nt_passwd = new_nt_p16;
}
+ if (password_locked)
+ {
+ smb_pwent->acct_ctrl |= ACB_PWLOCK;
+ }
if(mod_smbpwd_entry(smb_pwent,True) == False) {
slprintf(err_str, err_str_len-1, "Failed to modify entry for user %s.\n",
pwd->pw_name);
diff -C 3 -r old/samba-2.0.3/source/smbd/chgpasswd.c samba-2.0.3/source/smbd/chgpasswd.c
*** old/samba-2.0.3/source/smbd/chgpasswd.c Sun Feb 28 06:09:09 1999
--- samba-2.0.3/source/smbd/chgpasswd.c Wed Mar 10 03:28:55 1999
***************
*** 593,598 ****
--- 593,603 ----
* as the plaintext of the old users password is not
* available. JRA.
*/
+
+ if (sampw->acct_ctrl & ACB_PWLOCK)
+ {
+ ret = False;
+ }
if ( ret && lp_unix_password_sync())
{
diff -C 3 -r old/samba-2.0.3/source/utils/smbpasswd.c samba-2.0.3/source/utils/smbpasswd.c
*** old/samba-2.0.3/source/utils/smbpasswd.c Sun Feb 28 06:09:10 1999
--- samba-2.0.3/source/utils/smbpasswd.c Wed Mar 10 22:26:55 1999
***************
*** 59,64 ****
--- 59,65 ----
printf(" -D LEVEL debug level\n");
printf(" -U USER remote username\n");
printf(" -r MACHINE remote machine\n");
+ printf(" -p protect password from remote changes\n");
if (getuid() == 0) {
printf(" -R ORDER name resolve order\n");
***************
*** 225,238 ****
char *old_passwd, char *new_passwd,
BOOL add_user, BOOL enable_user,
BOOL disable_user, BOOL set_no_password,
! BOOL trust_account)
{
BOOL ret;
pstring err_str;
pstring msg_str;
if (remote_machine != NULL) {
! if (add_user || enable_user || disable_user || set_no_password || trust_account) {
/* these things can't be done remotely yet */
return False;
}
--- 226,239 ----
char *old_passwd, char *new_passwd,
BOOL add_user, BOOL enable_user,
BOOL disable_user, BOOL set_no_password,
! BOOL trust_account, BOOL password_locked)
{
BOOL ret;
pstring err_str;
pstring msg_str;
if (remote_machine != NULL) {
! if (add_user || enable_user || disable_user || set_no_password || trust_account || password_locked) {
/* these things can't be done remotely yet */
return False;
}
***************
*** 244,250 ****
}
ret = local_password_change(user_name, trust_account, add_user, enable_user,
! disable_user, set_no_password, new_passwd,
err_str, sizeof(err_str), msg_str, sizeof(msg_str));
if(*msg_str)
--- 245,251 ----
}
ret = local_password_change(user_name, trust_account, add_user, enable_user,
! disable_user, set_no_password, password_locked, new_passwd,
err_str, sizeof(err_str), msg_str, sizeof(msg_str));
if(*msg_str)
***************
*** 270,282 ****
BOOL enable_user = False;
BOOL set_no_password = False;
BOOL stdin_passwd_get = False;
char *user_name = NULL;
char *new_domain = NULL;
char *new_passwd = NULL;
char *old_passwd = NULL;
char *remote_machine = NULL;
! while ((ch = getopt(argc, argv, "adehmnj:r:sR:D:U:")) != EOF) {
switch(ch) {
case 'a':
add_user = True;
--- 271,284 ----
BOOL enable_user = False;
BOOL set_no_password = False;
BOOL stdin_passwd_get = False;
+ BOOL password_locked = False;
char *user_name = NULL;
char *new_domain = NULL;
char *new_passwd = NULL;
char *old_passwd = NULL;
char *remote_machine = NULL;
! while ((ch = getopt(argc, argv, "adehmnpj:r:sR:D:U:")) != EOF) {
switch(ch) {
case 'a':
add_user = True;
***************
*** 317,322 ****
--- 319,327 ----
case 'U':
user_name = optarg;
break;
+ case 'p':
+ password_locked = True;
+ break;
default:
usage();
}
***************
*** 432,438 ****
if (!password_change(remote_machine, user_name, old_passwd, new_passwd,
add_user, enable_user, disable_user, set_no_password,
! trust_account)) {
fprintf(stderr,"Failed to change password entry for %s\n", user_name);
return 1;
}
--- 437,443 ----
if (!password_change(remote_machine, user_name, old_passwd, new_passwd,
add_user, enable_user, disable_user, set_no_password,
! trust_account, password_locked)) {
fprintf(stderr,"Failed to change password entry for %s\n", user_name);
return 1;
}
***************
*** 464,475 ****
struct passwd *pwd = NULL;
int ch;
BOOL stdin_passwd_get = False;
char *old_passwd = NULL;
char *remote_machine = NULL;
char *user_name = NULL;
char *new_passwd = NULL;
! while ((ch = getopt(argc, argv, "hD:r:sU:")) != EOF) {
switch(ch) {
case 'D':
DEBUGLEVEL = atoi(optarg);
--- 469,481 ----
struct passwd *pwd = NULL;
int ch;
BOOL stdin_passwd_get = False;
+ BOOL password_locked = False;
char *old_passwd = NULL;
char *remote_machine = NULL;
char *user_name = NULL;
char *new_passwd = NULL;
! while ((ch = getopt(argc, argv, "phD:r:sU:")) != EOF) {
switch(ch) {
case 'D':
DEBUGLEVEL = atoi(optarg);
***************
*** 486,491 ****
--- 492,500 ----
case 'U':
user_name = optarg;
break;
+ case 'p':
+ password_locked = True;
+ break;
default:
usage();
}
***************
*** 536,542 ****
}
if (!password_change(remote_machine, user_name, old_passwd, new_passwd,
! False, False, False, False, False)) {
fprintf(stderr,"Failed to change password for %s\n", user_name);
return 1;
}
--- 545,551 ----
}
if (!password_change(remote_machine, user_name, old_passwd, new_passwd,
! False, False, False, False, False, password_locked)) {
fprintf(stderr,"Failed to change password for %s\n", user_name);
return 1;
}
diff -C 3 -r old/samba-2.0.3/source/web/swat.c samba-2.0.3/source/web/swat.c
*** old/samba-2.0.3/source/web/swat.c Fri Jan 15 04:07:40 1999
--- samba-2.0.3/source/web/swat.c Wed Mar 10 22:17:36 1999
***************
*** 631,639 ****
printf("Can't setup password database vectors.\n<p>");
return False;
}
!
ret = local_password_change(user_name, False, add_user, enable_user,
! disable_user, False, new_passwd, err_str, sizeof(err_str),
msg_str, sizeof(msg_str));
if(*msg_str)
--- 631,639 ----
printf("Can't setup password database vectors.\n<p>");
return False;
}
!
ret = local_password_change(user_name, False, add_user, enable_user,
! disable_user, False, False, new_passwd, err_str, sizeof(err_str),
msg_str, sizeof(msg_str));
if(*msg_str)
More information about the samba-technical
mailing list