When doing a cli_ulogoff don't invalidate the cnum, invalidate the vuid.
[Samba.git] / source / libnet / libnet_samsync.c
blob8a1433830f5170e1db9ddd5879028bd4890d1690
1 /*
2 Unix SMB/CIFS implementation.
4 Extract the user/system database from a remote SamSync server
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
7 Copyright (C) Guenther Deschner <gd@samba.org> 2008
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.
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, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
26 /**
27 * Decrypt and extract the user's passwords.
29 * The writes decrypted (no longer 'RID encrypted' or arcfour encrypted)
30 * passwords back into the structure
33 static NTSTATUS fix_user(TALLOC_CTX *mem_ctx,
34 DATA_BLOB *session_key,
35 enum netr_SamDatabaseID database_id,
36 struct netr_DELTA_ENUM *delta)
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];
45 memset(zero_buf, '\0', sizeof(zero_buf));
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));
56 user->lmpassword = lm_hash;
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));
65 user->ntpassword = nt_hash;
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;
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);
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));
97 user->lmpassword = lm_hash;
98 user->lm_password_present = true;
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));
109 user->ntpassword = nt_hash;
110 user->nt_password_present = true;
112 /* TODO: rid decrypt history fields */
114 return NT_STATUS_OK;
118 * Decrypt and extract the secrets
120 * The writes decrypted secrets back into the structure
122 static NTSTATUS fix_secret(TALLOC_CTX *mem_ctx,
123 DATA_BLOB *session_key,
124 enum netr_SamDatabaseID database_id,
125 struct netr_DELTA_ENUM *delta)
127 struct netr_DELTA_SECRET *secret = delta->delta_union.secret;
129 SamOEMhashBlob(secret->current_cipher.cipher_data,
130 secret->current_cipher.maxlen,
131 session_key);
133 SamOEMhashBlob(secret->old_cipher.cipher_data,
134 secret->old_cipher.maxlen,
135 session_key);
137 return NT_STATUS_OK;
141 * Fix up the delta, dealing with encryption issues so that the final
142 * callback need only do the printing or application logic
145 static 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)
150 NTSTATUS status = NT_STATUS_OK;
152 switch (delta->delta_type) {
153 case NETR_DELTA_USER:
155 status = fix_user(mem_ctx,
156 session_key,
157 database_id,
158 delta);
159 break;
160 case NETR_DELTA_SECRET:
162 status = fix_secret(mem_ctx,
163 session_key,
164 database_id,
165 delta);
166 break;
167 default:
168 break;
171 return status;
175 * Fix up the delta, dealing with encryption issues so that the final
176 * callback need only do the printing or application logic
179 NTSTATUS 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)
184 NTSTATUS status;
185 int i;
187 for (i = 0; i < r->num_deltas; i++) {
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;
198 return NT_STATUS_OK;