root/source4/lib/samba3/smbpasswd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. smbpasswd_gethexpwd
  2. smbpasswd_sethexpwd
  3. smbpasswd_decode_acb_info
  4. smbpasswd_encode_acb_info

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    smbpasswd file format routines
   4 
   5    Copyright (C) Andrew Tridgell 1992-1998 
   6    Modified by Jeremy Allison 1995.
   7    Modified by Gerald (Jerry) Carter 2000-2001
   8    Copyright (C) Tim Potter 2001
   9    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
  10    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2005
  11    
  12    This program is free software; you can redistribute it and/or modify
  13    it under the terms of the GNU General Public License as published by
  14    the Free Software Foundation; either version 3 of the License, or
  15    (at your option) any later version.
  16    
  17    This program is distributed in the hope that it will be useful,
  18    but WITHOUT ANY WARRANTY; without even the implied warranty of
  19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20    GNU General Public License for more details.
  21    
  22    You should have received a copy of the GNU General Public License
  23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  24 */
  25 
  26 /*! \file lib/smbpasswd.c
  27 
  28    The smbpasswd file is used to store encrypted passwords in a similar
  29    fashion to the /etc/passwd file.  The format is colon separated fields
  30    with one user per line like so:
  31 
  32    <username>:<uid>:<lanman hash>:<nt hash>:<acb info>:<last change time>
  33 
  34    The username and uid must correspond to an entry in the /etc/passwd
  35    file.  The lanman and nt password hashes are 32 hex digits corresponding
  36    to the 16-byte lanman and nt hashes respectively.  
  37 
  38    The password last change time is stored as a string of the format
  39    LCD-<change time> where the change time is expressed as an 
  40 
  41    'N'    No password
  42    'D'    Disabled
  43    'H'    Homedir required
  44    'T'    Temp account.
  45    'U'    User account (normal) 
  46    'M'    MNS logon user account - what is this ? 
  47    'W'    Workstation account
  48    'S'    Server account 
  49    'L'    Locked account
  50    'X'    No Xpiry on password 
  51    'I'    Interdomain trust account
  52 
  53 */
  54 
  55 #include "includes.h"
  56 #include "system/locale.h"
  57 #include "lib/samba3/samba3.h"
  58 
  59 /*! Convert 32 hex characters into a 16 byte array. */
  60 
  61 struct samr_Password *smbpasswd_gethexpwd(TALLOC_CTX *mem_ctx, const char *p)
     /* [<][>][^][v][top][bottom][index][help] */
  62 {
  63         int i;
  64         unsigned char   lonybble, hinybble;
  65         const char     *hexchars = "0123456789ABCDEF";
  66         const char     *p1, *p2;
  67         struct samr_Password *pwd = talloc(mem_ctx, struct samr_Password);
  68 
  69         if (!p) return NULL;
  70         
  71         for (i = 0; i < (sizeof(pwd->hash) * 2); i += 2)
  72         {
  73                 hinybble = toupper(p[i]);
  74                 lonybble = toupper(p[i + 1]);
  75                 
  76                 p1 = strchr_m(hexchars, hinybble);
  77                 p2 = strchr_m(hexchars, lonybble);
  78                 
  79                 if (!p1 || !p2) {
  80                         return NULL;
  81                 }
  82                 
  83                 hinybble = PTR_DIFF(p1, hexchars);
  84                 lonybble = PTR_DIFF(p2, hexchars);
  85                 
  86                 pwd->hash[i / 2] = (hinybble << 4) | lonybble;
  87         }
  88         return pwd;
  89 }
  90 
  91 /*! Convert a 16-byte array into 32 hex characters. */
  92 char *smbpasswd_sethexpwd(TALLOC_CTX *mem_ctx, struct samr_Password *pwd, uint16_t acb_info)
     /* [<][>][^][v][top][bottom][index][help] */
  93 {
  94         char *p;
  95         if (pwd != NULL) {
  96                 int i;
  97                 p = talloc_array(mem_ctx, char, 33);
  98                 if (!p) {
  99                         return NULL;
 100                 }
 101 
 102                 for (i = 0; i < sizeof(pwd->hash); i++)
 103                         slprintf(&p[i*2], 3, "%02X", pwd->hash[i]);
 104         } else {
 105                 if (acb_info & ACB_PWNOTREQ)
 106                         p = talloc_strdup(mem_ctx, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX");
 107                 else
 108                         p = talloc_strdup(mem_ctx, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
 109         }
 110         return p;
 111 }
 112 
 113 /*! Decode the account control bits (ACB) info from a string. */
 114 
 115 uint16_t smbpasswd_decode_acb_info(const char *p)
     /* [<][>][^][v][top][bottom][index][help] */
 116 {
 117         uint16_t acb_info = 0;
 118         bool finished = false;
 119 
 120         /*
 121          * Check if the account type bits have been encoded after the
 122          * NT password (in the form [NDHTUWSLXI]).
 123          */
 124 
 125         if (*p != '[') return 0;
 126 
 127         for (p++; *p && !finished; p++)
 128         {
 129                 switch (*p) {
 130                 case 'N': /* 'N'o password. */
 131                         acb_info |= ACB_PWNOTREQ; 
 132                         break;
 133                 case 'D': /* 'D'isabled. */
 134                         acb_info |= ACB_DISABLED; 
 135                         break; 
 136                 case 'H': /* 'H'omedir required. */
 137                         acb_info |= ACB_HOMDIRREQ; 
 138                         break;
 139                 case 'T': /* 'T'emp account. */
 140                         acb_info |= ACB_TEMPDUP; 
 141                         break;
 142                 case 'U': /* 'U'ser account (normal). */
 143                         acb_info |= ACB_NORMAL;
 144                         break;
 145                 case 'M': /* 'M'NS logon user account. What is this ? */
 146                         acb_info |= ACB_MNS; 
 147                         break; 
 148                 case 'W': /* 'W'orkstation account. */
 149                         acb_info |= ACB_WSTRUST; 
 150                         break; 
 151                 case 'S': /* 'S'erver account. */ 
 152                         acb_info |= ACB_SVRTRUST; 
 153                         break; 
 154                 case 'L': /* 'L'ocked account. */
 155                         acb_info |= ACB_AUTOLOCK; 
 156                         break; 
 157                 case 'X': /* No 'X'piry on password */
 158                         acb_info |= ACB_PWNOEXP; 
 159                         break; 
 160                 case 'I': /* 'I'nterdomain trust account. */
 161                         acb_info |= ACB_DOMTRUST; 
 162                         break; 
 163 
 164                 case ' ': 
 165                         break;
 166                 case ':':
 167                 case '\n':
 168                 case ']':
 169                 default:  
 170                         finished = true;
 171                         break;
 172                 }
 173         }
 174 
 175         return acb_info;
 176 }
 177 
 178 /*! Encode account control bits (ACBs) into a string. */
 179 
 180 char *smbpasswd_encode_acb_info(TALLOC_CTX *mem_ctx, uint16_t acb_info)
     /* [<][>][^][v][top][bottom][index][help] */
 181 {
 182         char *acct_str = talloc_array(mem_ctx, char, 35);
 183         size_t i = 0;
 184 
 185         acct_str[i++] = '[';
 186 
 187         if (acb_info & ACB_PWNOTREQ ) acct_str[i++] = 'N';
 188         if (acb_info & ACB_DISABLED ) acct_str[i++] = 'D';
 189         if (acb_info & ACB_HOMDIRREQ) acct_str[i++] = 'H';
 190         if (acb_info & ACB_TEMPDUP  ) acct_str[i++] = 'T'; 
 191         if (acb_info & ACB_NORMAL   ) acct_str[i++] = 'U';
 192         if (acb_info & ACB_MNS      ) acct_str[i++] = 'M';
 193         if (acb_info & ACB_WSTRUST  ) acct_str[i++] = 'W';
 194         if (acb_info & ACB_SVRTRUST ) acct_str[i++] = 'S';
 195         if (acb_info & ACB_AUTOLOCK ) acct_str[i++] = 'L';
 196         if (acb_info & ACB_PWNOEXP  ) acct_str[i++] = 'X';
 197         if (acb_info & ACB_DOMTRUST ) acct_str[i++] = 'I';
 198 
 199         acct_str[i++] = ']';
 200         acct_str[i++] = '\0';
 201 
 202         return acct_str;
 203 }     

/* [<][>][^][v][top][bottom][index][help] */