diff options
-rw-r--r-- | source3/Makefile.in | 2 | ||||
-rw-r--r-- | source3/lib/smbpasswd.c | 201 | ||||
-rw-r--r-- | source3/passdb/ldap.c | 6 | ||||
-rw-r--r-- | source3/passdb/nispass.c | 5 | ||||
-rw-r--r-- | source3/passdb/passdb.c | 132 | ||||
-rw-r--r-- | source3/passdb/pdb_smbpasswd.c | 12 | ||||
-rw-r--r-- | source3/passdb/smbpassfile.c | 2 | ||||
-rw-r--r-- | source3/utils/pdbedit.c | 28 |
8 files changed, 232 insertions, 156 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index 71f8015cb9..bb059ba1c0 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -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 diff --git a/source3/lib/smbpasswd.c b/source3/lib/smbpasswd.c new file mode 100644 index 0000000000..dbd12d90db --- /dev/null +++ b/source3/lib/smbpasswd.c @@ -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; +} diff --git a/source3/passdb/ldap.c b/source3/passdb/ldap.c index ee99664af4..8a2befcaa8 100644 --- a/source3/passdb/ldap.c +++ b/source3/passdb/ldap.c @@ -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); diff --git a/source3/passdb/nispass.c b/source3/passdb/nispass.c index a17a29ca7a..04b3765d59 100644 --- a/source3/passdb/nispass.c +++ b/source3/passdb/nispass.c @@ -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 diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index fae538a77d..615083ca41 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -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 ********************************************************************/ diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c index 1ef2995d71..1d532c0d50 100644 --- a/source3/passdb/pdb_smbpasswd.c +++ b/source3/passdb/pdb_smbpasswd.c @@ -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 diff --git a/source3/passdb/smbpassfile.c b/source3/passdb/smbpassfile.c index 3f3e2332a0..368414ff83 100644 --- a/source3/passdb/smbpassfile.c +++ b/source3/passdb/smbpassfile.c @@ -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 diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c index 1068446905..f09fd4f773 100644 --- a/source3/utils/pdbedit.c +++ b/source3/utils/pdbedit.c @@ -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 */ |