Merge from HEAD - make Samba compile with -Wwrite-strings without additional
[tprouty/samba.git] / source / lib / smbpasswd.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    smbpasswd file format routines
5
6    Copyright (C) Andrew Tridgell 1992-1998 
7    Modified by Jeremy Allison 1995.
8    Modified by Gerald (Jerry) Carter 2000-2001
9    Copyright (C) Tim Potter 2001
10    
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 2 of the License, or
14    (at your option) any later version.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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
57 /*! Convert 32 hex characters into a 16 byte array. */
58
59 BOOL smbpasswd_gethexpwd(char *p, unsigned char *pwd)
60 {
61         int i;
62         unsigned char   lonybble, hinybble;
63         const char      *hexchars = "0123456789ABCDEF";
64         char           *p1, *p2;
65         
66         if (!p) return (False);
67         
68         for (i = 0; i < 32; i += 2)
69         {
70                 hinybble = toupper(p[i]);
71                 lonybble = toupper(p[i + 1]);
72
73                 p1 = strchr_m(hexchars, hinybble);
74                 p2 = strchr_m(hexchars, lonybble);
75
76                 if (!p1 || !p2)
77                 {
78                         return (False);
79                 }
80
81                 hinybble = PTR_DIFF(p1, hexchars);
82                 lonybble = PTR_DIFF(p2, hexchars);
83
84                 pwd[i / 2] = (hinybble << 4) | lonybble;
85         }
86         return (True);
87 }
88
89 /*! Convert a 16-byte array into 32 hex characters. */
90
91 void smbpasswd_sethexpwd(fstring p, unsigned char *pwd, uint16 acb_info)
92 {
93         if (pwd != NULL) {
94                 int i;
95                 for (i = 0; i < 16; i++)
96                         slprintf(&p[i*2], 3, "%02X", pwd[i]);
97         } else {
98                 if (acb_info & ACB_PWNOTREQ)
99                         safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
100                 else
101                         safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
102         }
103 }
104
105 /*! Decode the account control bits (ACB) info from a string. */
106
107 uint16 smbpasswd_decode_acb_info(const char *p)
108 {
109         uint16 acb_info = 0;
110         BOOL finished = False;
111
112         /*
113          * Check if the account type bits have been encoded after the
114          * NT password (in the form [NDHTUWSLXI]).
115          */
116
117         if (*p != '[') return 0;
118
119         for (p++; *p && !finished; p++)
120         {
121                 switch (*p) {
122                 case 'N': /* 'N'o password. */
123                         acb_info |= ACB_PWNOTREQ; 
124                         break;
125                 case 'D': /* 'D'isabled. */
126                         acb_info |= ACB_DISABLED; 
127                         break; 
128                 case 'H': /* 'H'omedir required. */
129                         acb_info |= ACB_HOMDIRREQ; 
130                         break;
131                 case 'T': /* 'T'emp account. */
132                         acb_info |= ACB_TEMPDUP; 
133                         break;
134                 case 'U': /* 'U'ser account (normal). */
135                         acb_info |= ACB_NORMAL;
136                         break;
137                 case 'M': /* 'M'NS logon user account. What is this ? */
138                         acb_info |= ACB_MNS; 
139                         break; 
140                 case 'W': /* 'W'orkstation account. */
141                         acb_info |= ACB_WSTRUST; 
142                         break; 
143                 case 'S': /* 'S'erver account. */ 
144                         acb_info |= ACB_SVRTRUST; 
145                         break; 
146                 case 'L': /* 'L'ocked account. */
147                         acb_info |= ACB_AUTOLOCK; 
148                         break; 
149                 case 'X': /* No 'X'piry on password */
150                         acb_info |= ACB_PWNOEXP; 
151                         break; 
152                 case 'I': /* 'I'nterdomain trust account. */
153                         acb_info |= ACB_DOMTRUST; 
154                         break; 
155
156                 case ' ': 
157                         break;
158                 case ':':
159                 case '\n':
160                 case '\0': 
161                 case ']':
162                 default:  
163                         finished = True;
164                         break;
165                 }
166         }
167
168         return acb_info;
169 }
170
171 /*! Encode account control bits (ACBs) into a string. */
172
173 char *smbpasswd_encode_acb_info(uint16 acb_info)
174 {
175         static fstring acct_str;
176         size_t i = 0;
177
178         acct_str[i++] = '[';
179
180         if (acb_info & ACB_PWNOTREQ ) acct_str[i++] = 'N';
181         if (acb_info & ACB_DISABLED ) acct_str[i++] = 'D';
182         if (acb_info & ACB_HOMDIRREQ) acct_str[i++] = 'H';
183         if (acb_info & ACB_TEMPDUP  ) acct_str[i++] = 'T'; 
184         if (acb_info & ACB_NORMAL   ) acct_str[i++] = 'U';
185         if (acb_info & ACB_MNS      ) acct_str[i++] = 'M';
186         if (acb_info & ACB_WSTRUST  ) acct_str[i++] = 'W';
187         if (acb_info & ACB_SVRTRUST ) acct_str[i++] = 'S';
188         if (acb_info & ACB_AUTOLOCK ) acct_str[i++] = 'L';
189         if (acb_info & ACB_PWNOEXP  ) acct_str[i++] = 'X';
190         if (acb_info & ACB_DOMTRUST ) acct_str[i++] = 'I';
191
192         for ( ; i < NEW_PW_FORMAT_SPACE_PADDED_LEN - 2 ; i++ )
193                 acct_str[i] = ' ';
194
195         i = NEW_PW_FORMAT_SPACE_PADDED_LEN - 2;
196         acct_str[i++] = ']';
197         acct_str[i++] = '\0';
198
199         return acct_str;
200 }