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)
|
---|
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)
|
---|
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)
|
---|
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)
|
---|
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 | }
|
---|