Fix check_path_syntax() for multibyte encodings which have no '\' as second byte.
[Samba/gebeck_regimport.git] / source3 / sam / account.c
blobb8336146cda23d2b5a74fe5086ca695abfc254c6
1 /*
2 Unix SMB/CIFS implementation.
3 Password and authentication handling
4 Copyright (C) Jeremy Allison 1996-2001
5 Copyright (C) Luke Kenneth Casson Leighton 1996-1998
6 Copyright (C) Gerald (Jerry) Carter 2000-2001
7 Copyright (C) Andrew Bartlett 2001-2002
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_SAM
29 /************************************************************
30 Fill the SAM_ACCOUNT_HANDLE with default values.
31 ***********************************************************/
33 static void sam_fill_default_account(SAM_ACCOUNT_HANDLE *account)
35 ZERO_STRUCT(account->private); /* Don't touch the talloc context */
37 /* Don't change these timestamp settings without a good reason.
38 They are important for NT member server compatibility. */
40 /* FIXME: We should actually call get_nt_time_max() or sthng
41 * here */
42 unix_to_nt_time(&(account->private.logoff_time),get_time_t_max());
43 unix_to_nt_time(&(account->private.kickoff_time),get_time_t_max());
44 unix_to_nt_time(&(account->private.pass_must_change_time),get_time_t_max());
45 account->private.unknown_1 = 0x00ffffff; /* don't know */
46 account->private.logon_divs = 168; /* hours per week */
47 account->private.hours_len = 21; /* 21 times 8 bits = 168 */
48 memset(account->private.hours, 0xff, account->private.hours_len); /* available at all hours */
49 account->private.unknown_2 = 0x00000000; /* don't know */
50 account->private.unknown_3 = 0x000004ec; /* don't know */
53 static void destroy_sam_talloc(SAM_ACCOUNT_HANDLE **account)
55 if (*account) {
56 data_blob_clear_free(&((*account)->private.lm_pw));
57 data_blob_clear_free(&((*account)->private.nt_pw));
58 if((*account)->private.plaintext_pw!=NULL)
59 memset((*account)->private.plaintext_pw,'\0',strlen((*account)->private.plaintext_pw));
61 talloc_destroy((*account)->mem_ctx);
62 *account = NULL;
67 /**********************************************************************
68 Alloc memory and initialises a SAM_ACCOUNT_HANDLE on supplied mem_ctx.
69 ***********************************************************************/
71 NTSTATUS sam_init_account_talloc(TALLOC_CTX *mem_ctx, SAM_ACCOUNT_HANDLE **account)
73 SMB_ASSERT(*account != NULL);
75 if (!mem_ctx) {
76 DEBUG(0,("sam_init_account_talloc: mem_ctx was NULL!\n"));
77 return NT_STATUS_UNSUCCESSFUL;
80 *account=(SAM_ACCOUNT_HANDLE *)talloc(mem_ctx, sizeof(SAM_ACCOUNT_HANDLE));
82 if (*account==NULL) {
83 DEBUG(0,("sam_init_account_talloc: error while allocating memory\n"));
84 return NT_STATUS_NO_MEMORY;
87 (*account)->mem_ctx = mem_ctx;
89 (*account)->free_fn = NULL;
91 sam_fill_default_account(*account);
93 return NT_STATUS_OK;
97 /*************************************************************
98 Alloc memory and initialises a struct sam_passwd.
99 ************************************************************/
101 NTSTATUS sam_init_account(SAM_ACCOUNT_HANDLE **account)
103 TALLOC_CTX *mem_ctx;
104 NTSTATUS nt_status;
106 mem_ctx = talloc_init("sam internal SAM_ACCOUNT_HANDLE allocation");
108 if (!mem_ctx) {
109 DEBUG(0,("sam_init_account: error while doing talloc_init()\n"));
110 return NT_STATUS_NO_MEMORY;
113 if (!NT_STATUS_IS_OK(nt_status = sam_init_account_talloc(mem_ctx, account))) {
114 talloc_destroy(mem_ctx);
115 return nt_status;
118 (*account)->free_fn = destroy_sam_talloc;
120 return NT_STATUS_OK;
124 * Free the contents of the SAM_ACCOUNT_HANDLE, but not the structure.
126 * Also wipes the LM and NT hashes and plaintext password from
127 * memory.
129 * @param account SAM_ACCOUNT_HANDLE to free members of.
132 static void sam_free_account_contents(SAM_ACCOUNT_HANDLE *account)
135 /* Kill off sensitive data. Free()ed by the
136 talloc mechinism */
138 data_blob_clear_free(&(account->private.lm_pw));
139 data_blob_clear_free(&(account->private.nt_pw));
140 if (account->private.plaintext_pw)
141 memset(account->private.plaintext_pw,'\0',strlen(account->private.plaintext_pw));
145 /************************************************************
146 Reset the SAM_ACCOUNT_HANDLE and free the NT/LM hashes.
147 ***********************************************************/
149 NTSTATUS sam_reset_sam(SAM_ACCOUNT_HANDLE *account)
151 SMB_ASSERT(account != NULL);
153 sam_free_account_contents(account);
155 sam_fill_default_account(account);
157 return NT_STATUS_OK;
161 /************************************************************
162 Free the SAM_ACCOUNT_HANDLE and the member pointers.
163 ***********************************************************/
165 NTSTATUS sam_free_account(SAM_ACCOUNT_HANDLE **account)
167 SMB_ASSERT(*account != NULL);
169 sam_free_account_contents(*account);
171 if ((*account)->free_fn) {
172 (*account)->free_fn(account);
175 return NT_STATUS_OK;
179 /**********************************************************
180 Encode the account control bits into a string.
181 length = length of string to encode into (including terminating
182 null). length *MUST BE MORE THAN 2* !
183 **********************************************************/
185 char *sam_encode_acct_ctrl(uint16 acct_ctrl, size_t length)
187 static fstring acct_str;
188 size_t i = 0;
190 acct_str[i++] = '[';
192 if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
193 if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
194 if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
195 if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T';
196 if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U';
197 if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M';
198 if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W';
199 if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
200 if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
201 if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X';
202 if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
204 for ( ; i < length - 2 ; i++ )
205 acct_str[i] = ' ';
207 i = length - 2;
208 acct_str[i++] = ']';
209 acct_str[i++] = '\0';
211 return acct_str;
214 /**********************************************************
215 Decode the account control bits from a string.
216 **********************************************************/
218 uint16 sam_decode_acct_ctrl(const char *p)
220 uint16 acct_ctrl = 0;
221 BOOL finished = False;
224 * Check if the account type bits have been encoded after the
225 * NT password (in the form [NDHTUWSLXI]).
228 if (*p != '[')
229 return 0;
231 for (p++; *p && !finished; p++) {
232 switch (*p) {
233 case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
234 case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
235 case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
236 case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
237 case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
238 case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
239 case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
240 case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
241 case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
242 case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
243 case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
244 case ' ': { break; }
245 case ':':
246 case '\n':
247 case '\0':
248 case ']':
249 default: { finished = True; }
253 return acct_ctrl;
256 /*************************************************************
257 Routine to set 32 hex password characters from a 16 byte array.
258 **************************************************************/
260 void sam_sethexpwd(char *p, const unsigned char *pwd, uint16 acct_ctrl)
262 if (pwd != NULL) {
263 int i;
264 for (i = 0; i < 16; i++)
265 slprintf(&p[i*2], 3, "%02X", pwd[i]);
266 } else {
267 if (acct_ctrl & ACB_PWNOTREQ)
268 safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
269 else
270 safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
274 /*************************************************************
275 Routine to get the 32 hex characters and turn them
276 into a 16 byte array.
277 **************************************************************/
279 BOOL sam_gethexpwd(const char *p, unsigned char *pwd)
281 int i;
282 unsigned char lonybble, hinybble;
283 char *hexchars = "0123456789ABCDEF";
284 char *p1, *p2;
286 if (!p)
287 return (False);
289 for (i = 0; i < 32; i += 2) {
290 hinybble = toupper(p[i]);
291 lonybble = toupper(p[i + 1]);
293 p1 = strchr(hexchars, hinybble);
294 p2 = strchr(hexchars, lonybble);
296 if (!p1 || !p2)
297 return (False);
299 hinybble = PTR_DIFF(p1, hexchars);
300 lonybble = PTR_DIFF(p2, hexchars);
302 pwd[i / 2] = (hinybble << 4) | lonybble;
304 return (True);