source: branches/samba-3.2.x/source/libnet/libnet_samsync.c

Last change on this file was 228, checked in by Herwig Bauernfeind, 16 years ago

Update 3.2 branch to 3.2.6

File size: 5.5 KB
Line 
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
26/**
27 * Decrypt and extract the user's passwords.
28 *
29 * The writes decrypted (no longer 'RID encrypted' or arcfour encrypted)
30 * passwords back into the structure
31 */
32
33static NTSTATUS fix_user(TALLOC_CTX *mem_ctx,
34 DATA_BLOB *session_key,
35 enum netr_SamDatabaseID database_id,
36 struct netr_DELTA_ENUM *delta)
37{
38
39 uint32_t rid = delta->delta_id_union.rid;
40 struct netr_DELTA_USER *user = delta->delta_union.user;
41 struct samr_Password lm_hash;
42 struct samr_Password nt_hash;
43 unsigned char zero_buf[16];
44
45 memset(zero_buf, '\0', sizeof(zero_buf));
46
47 /* Note that win2000 may send us all zeros
48 * for the hashes if it doesn't
49 * think this channel is secure enough. */
50 if (user->lm_password_present) {
51 if (memcmp(user->lmpassword.hash, zero_buf, 16) != 0) {
52 sam_pwd_hash(rid, user->lmpassword.hash, lm_hash.hash, 0);
53 } else {
54 memset(lm_hash.hash, '\0', sizeof(lm_hash.hash));
55 }
56 user->lmpassword = lm_hash;
57 }
58
59 if (user->nt_password_present) {
60 if (memcmp(user->ntpassword.hash, zero_buf, 16) != 0) {
61 sam_pwd_hash(rid, user->ntpassword.hash, nt_hash.hash, 0);
62 } else {
63 memset(nt_hash.hash, '\0', sizeof(nt_hash.hash));
64 }
65 user->ntpassword = nt_hash;
66 }
67
68 if (user->user_private_info.SensitiveData) {
69 DATA_BLOB data;
70 struct netr_USER_KEYS keys;
71 enum ndr_err_code ndr_err;
72 data.data = user->user_private_info.SensitiveData;
73 data.length = user->user_private_info.DataLength;
74 SamOEMhashBlob(data.data, data.length, session_key);
75 user->user_private_info.SensitiveData = data.data;
76 user->user_private_info.DataLength = data.length;
77
78 ndr_err = ndr_pull_struct_blob(&data, mem_ctx, &keys,
79 (ndr_pull_flags_fn_t)ndr_pull_netr_USER_KEYS);
80 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
81 dump_data(10, data.data, data.length);
82 return ndr_map_error2ntstatus(ndr_err);
83 }
84
85 /* Note that win2000 may send us all zeros
86 * for the hashes if it doesn't
87 * think this channel is secure enough. */
88 if (keys.keys.keys2.lmpassword.length == 16) {
89 if (memcmp(keys.keys.keys2.lmpassword.pwd.hash,
90 zero_buf, 16) != 0) {
91 sam_pwd_hash(rid,
92 keys.keys.keys2.lmpassword.pwd.hash,
93 lm_hash.hash, 0);
94 } else {
95 memset(lm_hash.hash, '\0', sizeof(lm_hash.hash));
96 }
97 user->lmpassword = lm_hash;
98 user->lm_password_present = true;
99 }
100 if (keys.keys.keys2.ntpassword.length == 16) {
101 if (memcmp(keys.keys.keys2.ntpassword.pwd.hash,
102 zero_buf, 16) != 0) {
103 sam_pwd_hash(rid,
104 keys.keys.keys2.ntpassword.pwd.hash,
105 nt_hash.hash, 0);
106 } else {
107 memset(nt_hash.hash, '\0', sizeof(nt_hash.hash));
108 }
109 user->ntpassword = nt_hash;
110 user->nt_password_present = true;
111 }
112 /* TODO: rid decrypt history fields */
113 }
114 return NT_STATUS_OK;
115}
116
117/**
118 * Decrypt and extract the secrets
119 *
120 * The writes decrypted secrets back into the structure
121 */
122static NTSTATUS fix_secret(TALLOC_CTX *mem_ctx,
123 DATA_BLOB *session_key,
124 enum netr_SamDatabaseID database_id,
125 struct netr_DELTA_ENUM *delta)
126{
127 struct netr_DELTA_SECRET *secret = delta->delta_union.secret;
128
129 SamOEMhashBlob(secret->current_cipher.cipher_data,
130 secret->current_cipher.maxlen,
131 session_key);
132
133 SamOEMhashBlob(secret->old_cipher.cipher_data,
134 secret->old_cipher.maxlen,
135 session_key);
136
137 return NT_STATUS_OK;
138}
139
140/**
141 * Fix up the delta, dealing with encryption issues so that the final
142 * callback need only do the printing or application logic
143 */
144
145static NTSTATUS samsync_fix_delta(TALLOC_CTX *mem_ctx,
146 DATA_BLOB *session_key,
147 enum netr_SamDatabaseID database_id,
148 struct netr_DELTA_ENUM *delta)
149{
150 NTSTATUS status = NT_STATUS_OK;
151
152 switch (delta->delta_type) {
153 case NETR_DELTA_USER:
154
155 status = fix_user(mem_ctx,
156 session_key,
157 database_id,
158 delta);
159 break;
160 case NETR_DELTA_SECRET:
161
162 status = fix_secret(mem_ctx,
163 session_key,
164 database_id,
165 delta);
166 break;
167 default:
168 break;
169 }
170
171 return status;
172}
173
174/**
175 * Fix up the delta, dealing with encryption issues so that the final
176 * callback need only do the printing or application logic
177 */
178
179NTSTATUS samsync_fix_delta_array(TALLOC_CTX *mem_ctx,
180 DATA_BLOB *session_key,
181 enum netr_SamDatabaseID database_id,
182 struct netr_DELTA_ENUM_ARRAY *r)
183{
184 NTSTATUS status;
185 int i;
186
187 for (i = 0; i < r->num_deltas; i++) {
188
189 status = samsync_fix_delta(mem_ctx,
190 session_key,
191 database_id,
192 &r->delta_enum[i]);
193 if (!NT_STATUS_IS_OK(status)) {
194 return status;
195 }
196 }
197
198 return NT_STATUS_OK;
199}
Note: See TracBrowser for help on using the repository browser.