Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Extract the user/system database from a remote SamSync server
5 :
6 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
7 : Copyright (C) Guenther Deschner <gd@samba.org> 2008
8 :
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 3 of the License, or
12 : (at your option) any later version.
13 :
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.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 :
24 : #include "includes.h"
25 : #include "../libcli/auth/libcli_auth.h"
26 : #include "../libcli/samsync/samsync.h"
27 : #include "librpc/gen_ndr/ndr_netlogon.h"
28 : #include "lib/crypto/gnutls_helpers.h"
29 :
30 : /**
31 : * Decrypt and extract the user's passwords.
32 : *
33 : * The writes decrypted (no longer 'RID encrypted' or arcfour encrypted)
34 : * passwords back into the structure
35 : */
36 :
37 0 : static NTSTATUS fix_user(TALLOC_CTX *mem_ctx,
38 : struct netlogon_creds_CredentialState *creds,
39 : enum netr_SamDatabaseID database_id,
40 : struct netr_DELTA_ENUM *delta)
41 : {
42 :
43 0 : uint32_t rid = delta->delta_id_union.rid;
44 0 : struct netr_DELTA_USER *user = delta->delta_union.user;
45 0 : struct samr_Password lm_hash;
46 0 : struct samr_Password nt_hash;
47 0 : int rc;
48 :
49 : /* Note that win2000 may send us all zeros
50 : * for the hashes if it doesn't
51 : * think this channel is secure enough. */
52 0 : if (user->lm_password_present) {
53 0 : if (!all_zero(user->lmpassword.hash, 16)) {
54 0 : rc = sam_rid_crypt(rid, user->lmpassword.hash,
55 : lm_hash.hash, SAMBA_GNUTLS_DECRYPT);
56 0 : if (rc != 0) {
57 0 : return gnutls_error_to_ntstatus(rc,
58 : NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
59 : }
60 : } else {
61 0 : memset(lm_hash.hash, '\0', sizeof(lm_hash.hash));
62 : }
63 0 : user->lmpassword = lm_hash;
64 : }
65 :
66 0 : if (user->nt_password_present) {
67 0 : if (!all_zero(user->ntpassword.hash, 16)) {
68 0 : rc = sam_rid_crypt(rid, user->ntpassword.hash,
69 : nt_hash.hash, SAMBA_GNUTLS_DECRYPT);
70 0 : if (rc != 0) {
71 0 : return gnutls_error_to_ntstatus(rc,
72 : NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
73 : }
74 : } else {
75 0 : memset(nt_hash.hash, '\0', sizeof(nt_hash.hash));
76 : }
77 0 : user->ntpassword = nt_hash;
78 : }
79 :
80 0 : if (user->user_private_info.SensitiveData) {
81 0 : DATA_BLOB data;
82 0 : struct netr_USER_KEYS keys;
83 0 : enum ndr_err_code ndr_err;
84 0 : NTSTATUS status;
85 :
86 0 : data.data = user->user_private_info.SensitiveData;
87 0 : data.length = user->user_private_info.DataLength;
88 :
89 0 : status = netlogon_creds_arcfour_crypt(creds,
90 : data.data,
91 : data.length);
92 0 : if (!NT_STATUS_IS_OK(status)) {
93 0 : return status;
94 : }
95 :
96 0 : user->user_private_info.SensitiveData = data.data;
97 0 : user->user_private_info.DataLength = data.length;
98 :
99 0 : ndr_err = ndr_pull_struct_blob(&data, mem_ctx, &keys,
100 : (ndr_pull_flags_fn_t)ndr_pull_netr_USER_KEYS);
101 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
102 0 : dump_data(10, data.data, data.length);
103 0 : return ndr_map_error2ntstatus(ndr_err);
104 : }
105 :
106 : /* Note that win2000 may send us all zeros
107 : * for the hashes if it doesn't
108 : * think this channel is secure enough. */
109 0 : if (keys.keys.keys2.lmpassword.length == 16) {
110 0 : if (!all_zero(keys.keys.keys2.lmpassword.pwd.hash,
111 : 16)) {
112 0 : rc = sam_rid_crypt(rid,
113 : keys.keys.keys2.lmpassword.pwd.hash,
114 : lm_hash.hash, SAMBA_GNUTLS_DECRYPT);
115 0 : if (rc != 0) {
116 0 : return gnutls_error_to_ntstatus(rc,
117 : NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
118 : }
119 : } else {
120 0 : memset(lm_hash.hash, '\0', sizeof(lm_hash.hash));
121 : }
122 0 : user->lmpassword = lm_hash;
123 0 : user->lm_password_present = true;
124 : }
125 0 : if (keys.keys.keys2.ntpassword.length == 16) {
126 0 : if (!all_zero(keys.keys.keys2.ntpassword.pwd.hash,
127 : 16)) {
128 0 : rc = sam_rid_crypt(rid,
129 : keys.keys.keys2.ntpassword.pwd.hash,
130 : nt_hash.hash, SAMBA_GNUTLS_DECRYPT);
131 0 : if (rc != 0) {
132 0 : return gnutls_error_to_ntstatus(rc,
133 : NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
134 : }
135 : } else {
136 0 : memset(nt_hash.hash, '\0', sizeof(nt_hash.hash));
137 : }
138 0 : user->ntpassword = nt_hash;
139 0 : user->nt_password_present = true;
140 : }
141 : /* TODO: rid decrypt history fields */
142 : }
143 0 : return NT_STATUS_OK;
144 : }
145 :
146 : /**
147 : * Decrypt and extract the secrets
148 : *
149 : * The writes decrypted secrets back into the structure
150 : */
151 0 : static NTSTATUS fix_secret(TALLOC_CTX *mem_ctx,
152 : struct netlogon_creds_CredentialState *creds,
153 : enum netr_SamDatabaseID database,
154 : struct netr_DELTA_ENUM *delta)
155 : {
156 0 : struct netr_DELTA_SECRET *secret = delta->delta_union.secret;
157 0 : NTSTATUS status;
158 :
159 0 : status = netlogon_creds_arcfour_crypt(creds,
160 : secret->current_cipher.cipher_data,
161 0 : secret->current_cipher.maxlen);
162 0 : if (!NT_STATUS_IS_OK(status)) {
163 0 : return status;
164 : }
165 :
166 0 : status = netlogon_creds_arcfour_crypt(creds,
167 : secret->old_cipher.cipher_data,
168 0 : secret->old_cipher.maxlen);
169 0 : if (!NT_STATUS_IS_OK(status)) {
170 0 : return status;
171 : }
172 :
173 0 : return NT_STATUS_OK;
174 : }
175 :
176 : /**
177 : * Fix up the delta, dealing with encryption issues so that the final
178 : * callback need only do the printing or application logic
179 : */
180 :
181 0 : NTSTATUS samsync_fix_delta(TALLOC_CTX *mem_ctx,
182 : struct netlogon_creds_CredentialState *creds,
183 : enum netr_SamDatabaseID database_id,
184 : struct netr_DELTA_ENUM *delta)
185 : {
186 0 : NTSTATUS status = NT_STATUS_OK;
187 :
188 0 : switch (delta->delta_type) {
189 0 : case NETR_DELTA_USER:
190 :
191 0 : status = fix_user(mem_ctx,
192 : creds,
193 : database_id,
194 : delta);
195 0 : break;
196 0 : case NETR_DELTA_SECRET:
197 :
198 0 : status = fix_secret(mem_ctx,
199 : creds,
200 : database_id,
201 : delta);
202 0 : break;
203 0 : default:
204 0 : break;
205 : }
206 :
207 0 : return status;
208 : }
209 :
|