1
0
mirror of https://github.com/samba-team/samba.git synced 2025-07-31 20:22:15 +03:00

Started a cleanup of smbpasswd related stuff. I've created a new file

lib/smbpasswd.c which will contain routines related to manipulating
smbpasswd entries.

 - renamed and moved pdb_{get,set}hexpwd() functions
 - renamed and moved pdb_{decode,encode}acct_ctrl() functions
 - started hiding references to the cruftalicious
   NEW_PW_FORMAT_SPACE_PADDED_LEN constant
 - started gradual rename of references to acct_ctrl to acb_info which is
   the nomenclature used in MSDN and header files

There's still more work to be done.  Currently there are several places
where smbpasswd entries are iterated etc.  Ideally this should all happen
through the passdb system.
This commit is contained in:
Tim Potter
-
parent 7a7b13940e
commit 4a01e24030
8 changed files with 232 additions and 156 deletions

View File

@ -113,7 +113,7 @@ LIB_OBJ = lib/charcnv.o lib/debug.o lib/fault.o \
lib/util.o lib/util_sock.o lib/util_sec.o smbd/ssl.o \
lib/talloc.o lib/hash.o lib/substitute.o lib/fsusage.o \
lib/ms_fnmatch.o lib/select.o lib/error.o lib/messages.o \
lib/md5.o lib/hmacmd5.o lib/iconv.o \
lib/md5.o lib/hmacmd5.o lib/iconv.o lib/smbpasswd.o \
nsswitch/wb_client.o nsswitch/wb_common.o $(TDB_OBJ)
READLINE_OBJ = lib/readline.o

201
source/lib/smbpasswd.c Normal file
View File

@ -0,0 +1,201 @@
/*
Unix SMB/Netbios implementation.
Version 2.0
smbpasswd file format routines
Copyright (C) Andrew Tridgell 1992-1998
Modified by Jeremy Allison 1995.
Modified by Gerald (Jerry) Carter 2000-2001
Copyright (C) Tim Potter 2001
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*! \file lib/smbpasswd.c
The smbpasswd file is used to store encrypted passwords in a similar
fashion to the /etc/passwd file. The format is colon separated fields
with one user per line like so:
<username>:<uid>:<lanman hash>:<nt hash>:<acb info>:<last change time>
The username and uid must correspond to an entry in the /etc/passwd
file. The lanman and nt password hashes are 32 hex digits corresponding
to the 16-byte lanman and nt hashes respectively.
The password last change time is stored as a string of the format
LCD-<change time> where the change time is expressed as an
'N' No password
'D' Disabled
'H' Homedir required
'T' Temp account.
'U' User account (normal)
'M' MNS logon user account - what is this ?
'W' Workstation account
'S' Server account
'L' Locked account
'X' No Xpiry on password
'I' Interdomain trust account
*/
#include "includes.h"
/*! Convert 32 hex characters into a 16 byte array. */
BOOL smbpasswd_gethexpwd(char *p, unsigned char *pwd)
{
int i;
unsigned char lonybble, hinybble;
char *hexchars = "0123456789ABCDEF";
char *p1, *p2;
if (!p) return (False);
for (i = 0; i < 32; i += 2)
{
hinybble = toupper(p[i]);
lonybble = toupper(p[i + 1]);
p1 = strchr_m(hexchars, hinybble);
p2 = strchr_m(hexchars, lonybble);
if (!p1 || !p2)
{
return (False);
}
hinybble = PTR_DIFF(p1, hexchars);
lonybble = PTR_DIFF(p2, hexchars);
pwd[i / 2] = (hinybble << 4) | lonybble;
}
return (True);
}
/*! Convert a 16-byte array into 32 hex characters. */
void smbpasswd_sethexpwd(fstring p, unsigned char *pwd, uint16 acb_info)
{
if (pwd != NULL) {
int i;
for (i = 0; i < 16; i++)
slprintf(&p[i*2], 3, "%02X", pwd[i]);
} else {
if (acb_info & ACB_PWNOTREQ)
safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
else
safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
}
}
/*! Decode the account control bits (ACB) info from a string. */
uint16 smbpasswd_decode_acb_info(const char *p)
{
uint16 acb_info = 0;
BOOL finished = False;
/*
* Check if the account type bits have been encoded after the
* NT password (in the form [NDHTUWSLXI]).
*/
if (*p != '[') return 0;
for (p++; *p && !finished; p++)
{
switch (*p) {
case 'N': /* 'N'o password. */
acb_info |= ACB_PWNOTREQ;
break;
case 'D': /* 'D'isabled. */
acb_info |= ACB_DISABLED;
break;
case 'H': /* 'H'omedir required. */
acb_info |= ACB_HOMDIRREQ;
break;
case 'T': /* 'T'emp account. */
acb_info |= ACB_TEMPDUP;
break;
case 'U': /* 'U'ser account (normal). */
acb_info |= ACB_NORMAL;
break;
case 'M': /* 'M'NS logon user account. What is this ? */
acb_info |= ACB_MNS;
break;
case 'W': /* 'W'orkstation account. */
acb_info |= ACB_WSTRUST;
break;
case 'S': /* 'S'erver account. */
acb_info |= ACB_SVRTRUST;
break;
case 'L': /* 'L'ocked account. */
acb_info |= ACB_AUTOLOCK;
break;
case 'X': /* No 'X'piry on password */
acb_info |= ACB_PWNOEXP;
break;
case 'I': /* 'I'nterdomain trust account. */
acb_info |= ACB_DOMTRUST;
break;
case ' ':
break;
case ':':
case '\n':
case '\0':
case ']':
default:
finished = True;
break;
}
}
return acb_info;
}
/*! Encode account control bits (ACBs) into a string. */
char *smbpasswd_encode_acb_info(uint16 acb_info)
{
static fstring acct_str;
size_t i = 0;
acct_str[i++] = '[';
if (acb_info & ACB_PWNOTREQ ) acct_str[i++] = 'N';
if (acb_info & ACB_DISABLED ) acct_str[i++] = 'D';
if (acb_info & ACB_HOMDIRREQ) acct_str[i++] = 'H';
if (acb_info & ACB_TEMPDUP ) acct_str[i++] = 'T';
if (acb_info & ACB_NORMAL ) acct_str[i++] = 'U';
if (acb_info & ACB_MNS ) acct_str[i++] = 'M';
if (acb_info & ACB_WSTRUST ) acct_str[i++] = 'W';
if (acb_info & ACB_SVRTRUST ) acct_str[i++] = 'S';
if (acb_info & ACB_AUTOLOCK ) acct_str[i++] = 'L';
if (acb_info & ACB_PWNOEXP ) acct_str[i++] = 'X';
if (acb_info & ACB_DOMTRUST ) acct_str[i++] = 'I';
for ( ; i < NEW_PW_FORMAT_SPACE_PADDED_LEN - 2 ; i++ )
acct_str[i] = ' ';
i = NEW_PW_FORMAT_SPACE_PADDED_LEN - 2;
acct_str[i++] = ']';
acct_str[i++] = '\0';
return acct_str;
}

View File

@ -601,7 +601,8 @@ static BOOL modadd_ldappwd_entry(struct smb_passwd *newpwd, int flag)
make_a_mod(&mods, ldap_state, "rid", rid);
make_a_mod(&mods, ldap_state, "pwdLastSet", lst);
make_a_mod(&mods, ldap_state, "userAccountControl", pdb_encode_acct_ctrl(newpwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN));
make_a_mod(&mods, ldap_state, "userAccountControl",
smbpasswd_encode_acb_info(newpwd->acct_ctrl));
switch(flag)
{
@ -733,7 +734,8 @@ static BOOL modadd_ldap21pwd_entry(struct sam_passwd *newpwd, int flag)
make_a_mod(&mods, ldap_state, "rid", rid);
make_a_mod(&mods, ldap_state, "pwdLastSet", lst);
make_a_mod(&mods, ldap_state, "userAccountControl", pdb_encode_acct_ctrl(newpwd->acct_ctrl,NEW_PW_FORMAT_SPACE_PADDED_LEN));
make_a_mod(&mods, ldap_state, "userAccountControl",
smbpasswd_encode_acct_ctrl(newpwd->acct_ctrl));
ldap_modify_s(ldap_struct, dn, mods);

View File

@ -641,7 +641,8 @@ static BOOL add_nisp21pwd_entry(struct sam_passwd *newpwd)
slprintf(smb_grpid, sizeof(smb_grpid)-1, "%u", newpwd->smb_grpid);
slprintf(group_rid, sizeof(group_rid)-1, "0x%x", newpwd->group_rid);
safe_strcpy(acb, pdb_encode_acct_ctrl(newpwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN), sizeof(acb)-1);
safe_strcpy(acb, smbpasswd_encode_acct_ctrl(newpwd->acct_ctrl),
sizeof(acb)-1);
set_single_attribute(&new_obj, NPF_NAME , newpwd->smb_name , strlen(newpwd->smb_name) , 0);
set_single_attribute(&new_obj, NPF_UID , uid , strlen(uid) , 0);
@ -805,7 +806,7 @@ static BOOL mod_nisp21pwd_entry(struct sam_passwd* pwd, BOOL override)
* acct ctrl field. Encode the given acct ctrl
* bits into it.
*/
fstrcpy(acb, pdb_encode_acct_ctrl(pwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN));
fstrcpy(acb, smbpasswd_encode_acct_ctrl(pwd->acct_ctrl));
} else {
/*
* If using the old format and the ACB_DISABLED or

View File

@ -203,138 +203,6 @@ struct sam_disp_info *pdb_sam_to_dispinfo(SAM_ACCOUNT *user)
return &disp_info;
}
/**********************************************************
Encode the account control bits into a string.
length = length of string to encode into (including terminating
null). length *MUST BE MORE THAN 2* !
**********************************************************/
char *pdb_encode_acct_ctrl(uint16 acct_ctrl, size_t length)
{
static fstring acct_str;
size_t i = 0;
acct_str[i++] = '[';
if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T';
if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U';
if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M';
if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W';
if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
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;
acct_str[i++] = ']';
acct_str[i++] = '\0';
return acct_str;
}
/**********************************************************
Decode the account control bits from a string.
this function breaks coding standards minimum line width of 80 chars.
reason: vertical line-up code clarity - all case statements fit into
15 lines, which is more important.
**********************************************************/
uint16 pdb_decode_acct_ctrl(const char *p)
{
uint16 acct_ctrl = 0;
BOOL finished = False;
/*
* Check if the account type bits have been encoded after the
* NT password (in the form [NDHTUWSLXI]).
*/
if (*p != '[') return 0;
for (p++; *p && !finished; p++)
{
switch (*p)
{
case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
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 ' ': { break; }
case ':':
case '\n':
case '\0':
case ']':
default: { finished = True; }
}
}
return acct_ctrl;
}
/*************************************************************
Routine to set 32 hex password characters from a 16 byte array.
**************************************************************/
void pdb_sethexpwd(char *p, unsigned char *pwd, uint16 acct_ctrl)
{
if (pwd != NULL) {
int i;
for (i = 0; i < 16; i++)
slprintf(&p[i*2], 3, "%02X", pwd[i]);
} else {
if (acct_ctrl & ACB_PWNOTREQ)
safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
else
safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
}
}
/*************************************************************
Routine to get the 32 hex characters and turn them
into a 16 byte array.
**************************************************************/
BOOL pdb_gethexpwd(char *p, unsigned char *pwd)
{
int i;
unsigned char lonybble, hinybble;
char *hexchars = "0123456789ABCDEF";
char *p1, *p2;
if (!p) return (False);
for (i = 0; i < 32; i += 2)
{
hinybble = toupper(p[i]);
lonybble = toupper(p[i + 1]);
p1 = strchr_m(hexchars, hinybble);
p2 = strchr_m(hexchars, lonybble);
if (!p1 || !p2)
{
return (False);
}
hinybble = PTR_DIFF(p1, hexchars);
lonybble = PTR_DIFF(p2, hexchars);
pwd[i / 2] = (hinybble << 4) | lonybble;
}
return (True);
}
/*******************************************************************
Group and User RID username mapping function
********************************************************************/

View File

@ -414,7 +414,7 @@ static struct smb_passwd *getsmbfilepwent(void *vp)
pw_buf.smb_passwd = NULL;
pw_buf.acct_ctrl |= ACB_PWNOTREQ;
} else {
if (!pdb_gethexpwd((char *)p, smbpwd)) {
if (!smbpasswd_gethexpwd((char *)p, smbpwd)) {
DEBUG(0, ("getsmbfilepwent: Malformed Lanman password entry (non hex chars)\n"));
continue;
}
@ -431,7 +431,7 @@ static struct smb_passwd *getsmbfilepwent(void *vp)
the lanman password. */
if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) {
if (*p != '*' && *p != 'X') {
if(pdb_gethexpwd((char *)p,smbntpwd))
if(smbpasswd_gethexpwd((char *)p,smbntpwd))
pw_buf.smb_nt_passwd = smbntpwd;
}
p += 33; /* Move to the first character of the line after
@ -444,7 +444,7 @@ static struct smb_passwd *getsmbfilepwent(void *vp)
if (*p == '[')
{
unsigned char *end_p = (unsigned char *)strchr_m((char *)p, ']');
pw_buf.acct_ctrl = pdb_decode_acct_ctrl((char*)p);
pw_buf.acct_ctrl = smbpasswd_decode_acb_info((char*)p);
/* Must have some account type set. */
if(pw_buf.acct_ctrl == 0)
@ -545,8 +545,8 @@ static char *format_new_smbpasswd_entry(struct smb_passwd *newpwd)
*p++ = ':';
/* Add the account encoding and the last change time. */
slprintf((char *)p, new_entry_length - 1 - (p - new_entry), "%s:LCT-%08X:\n",
pdb_encode_acct_ctrl(newpwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN),
slprintf((char *)p, new_entry_length - 1 - (p - new_entry), "%s:LCT-%08X:\n",
smbpasswd_encode_acb_info(newpwd->acct_ctrl),
(uint32)newpwd->pass_last_set_time);
return new_entry;
@ -903,7 +903,7 @@ static BOOL mod_smbfilepwd_entry(struct smb_passwd* pwd, BOOL override)
* acct ctrl field. Encode the given acct ctrl
* bits into it.
*/
fstrcpy(encode_bits, pdb_encode_acct_ctrl(pwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN));
fstrcpy(encode_bits, smbpasswd_encode_acb_info(pwd->acct_ctrl));
} else {
/*
* If using the old format and the ACB_DISABLED or

View File

@ -236,7 +236,7 @@ static BOOL get_trust_account_password_from_file( unsigned char *ret_pwd, time_t
* Get the hex password.
*/
if (!pdb_gethexpwd((char *)linebuf, ret_pwd) || linebuf[32] != ':' ||
if (!smbpasswd_gethexpwd((char *)linebuf, ret_pwd) || linebuf[32] != ':' ||
strncmp(&linebuf[33], "TLC-", 4)) {
DEBUG(0,("get_trust_account_password: Malformed trust password file (incorrect format).\n"));
#ifdef DEBUG_PASSWORD

View File

@ -89,16 +89,20 @@ static int print_sam_info (SAM_ACCOUNT *sam_pwent, BOOL verbosity, BOOL smbpwdst
{
char lm_passwd[33];
char nt_passwd[33];
pdb_sethexpwd(lm_passwd, pdb_get_lanman_passwd(sam_pwent), pdb_get_acct_ctrl(sam_pwent));
pdb_sethexpwd(nt_passwd, pdb_get_nt_passwd(sam_pwent), pdb_get_acct_ctrl(sam_pwent));
smbpasswd_sethexpwd(lm_passwd,
pdb_get_lanman_passwd(sam_pwent),
pdb_get_acct_ctrl(sam_pwent));
smbpasswd_sethexpwd(nt_passwd,
pdb_get_nt_passwd(sam_pwent),
pdb_get_acct_ctrl(sam_pwent));
printf ("%s:%d:%s:%s:%s:LCT-%08x:\n",
pdb_get_username(sam_pwent),
pdb_get_uid(sam_pwent),
lm_passwd,
nt_passwd,
pdb_encode_acct_ctrl(pdb_get_acct_ctrl(sam_pwent),NEW_PW_FORMAT_SPACE_PADDED_LEN),
(uint32)pdb_get_pass_last_set_time(sam_pwent));
printf("%s:%d:%s:%s:%s:LCT-%08x:\n",
pdb_get_username(sam_pwent),
pdb_get_uid(sam_pwent),
lm_passwd,
nt_passwd,
smbpasswd_encode_acb_info(pdb_get_acct_ctrl(sam_pwent)),
(uint32)pdb_get_pass_last_set_time(sam_pwent));
}
else
{
@ -452,7 +456,7 @@ static int import_users (char *filename)
}
else
{
if (!pdb_gethexpwd((char *)p, smbpwd))
if (!smbpasswd_gethexpwd((char *)p, smbpwd))
{
fprintf (stderr, "Error: malformed Lanman password entry at line %d (non hex chars)\n", line);
continue;
@ -466,7 +470,7 @@ static int import_users (char *filename)
{
if (*p != '*' && *p != 'X')
{
if (pdb_gethexpwd((char *)p,smbntpwd))
if (smbpasswd_gethexpwd((char *)p,smbntpwd))
{
sam_pwent.nt_pw = smbntpwd;
}
@ -480,7 +484,7 @@ static int import_users (char *filename)
{
unsigned char *end_p = (unsigned char *)strchr_m((char *)p, ']');
sam_pwent.acct_ctrl = pdb_decode_acct_ctrl((char*)p);
sam_pwent.acct_ctrl = smbpasswd_decode_acb_info((char*)p);
if(sam_pwent.acct_ctrl == 0) sam_pwent.acct_ctrl = ACB_NORMAL;
/* Get last change time */