util:datablob: data_blob_pad checks its alignment assumption
[samba.git] / source3 / rpc_client / init_lsa.c
bloba59a0b71e27b81e7df791ae253c5166822bc36af
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Guenther Deschner 2008.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "librpc/gen_ndr/lsa.h"
22 #include "librpc/gen_ndr/ndr_drsblobs.h"
23 #include "rpc_client/init_lsa.h"
24 #include "lib/crypto/gnutls_helpers.h"
25 #include "librpc/rpc/dcerpc_lsa.h"
27 #include <gnutls/gnutls.h>
28 #include <gnutls/crypto.h>
30 /*******************************************************************
31 inits a structure.
32 ********************************************************************/
34 void init_lsa_String(struct lsa_String *name, const char *s)
36 name->string = s;
37 name->size = 2 * strlen_m(s);
38 name->length = name->size;
41 /*******************************************************************
42 inits a structure.
43 ********************************************************************/
45 void init_lsa_StringLarge(struct lsa_StringLarge *name, const char *s)
47 name->string = s;
50 /*******************************************************************
51 inits a structure.
52 ********************************************************************/
54 void init_lsa_AsciiString(struct lsa_AsciiString *name, const char *s)
56 name->string = s;
59 /*******************************************************************
60 inits a structure.
61 ********************************************************************/
63 void init_lsa_AsciiStringLarge(struct lsa_AsciiStringLarge *name, const char *s)
65 name->string = s;
68 bool rpc_lsa_encrypt_trustdom_info(
69 TALLOC_CTX *mem_ctx,
70 const char *incoming_old,
71 const char *incoming_new,
72 const char *outgoing_old,
73 const char *outgoing_new,
74 DATA_BLOB session_key,
75 struct lsa_TrustDomainInfoAuthInfoInternal **_authinfo_internal)
77 struct timeval tv_now = timeval_current();
78 NTTIME now = timeval_to_nttime(&tv_now);
80 struct lsa_TrustDomainInfoAuthInfoInternal *authinfo_internal = NULL;
81 struct AuthenticationInformation in_cur_td_info = {
82 .AuthType = TRUST_AUTH_TYPE_CLEAR,
83 .LastUpdateTime = now,
85 struct AuthenticationInformation in_prev_td_buf = {
86 .AuthType = TRUST_AUTH_TYPE_CLEAR,
87 .LastUpdateTime = now,
89 struct AuthenticationInformation out_cur_td_info = {
90 .AuthType = TRUST_AUTH_TYPE_CLEAR,
91 .LastUpdateTime = now,
93 struct AuthenticationInformation out_prev_td_buf = {
94 .AuthType = TRUST_AUTH_TYPE_CLEAR,
95 .LastUpdateTime = now,
99 * This corresponds to MS-LSAD 2.2.7.16 LSAPR_TRUSTED_DOMAIN_AUTH_BLOB.
101 struct trustDomainPasswords dom_auth_info = {
102 .incoming = {
103 .count = 1,
104 .previous = {
105 .count = 1,
106 .array = &in_prev_td_buf,
109 .current = {
110 .count = 1,
111 .array = &in_cur_td_info,
115 .outgoing = {
116 .count = 1,
117 .previous = {
118 .count = 1,
119 .array = &out_prev_td_buf,
122 .current = {
123 .count = 1,
124 .array = &out_cur_td_info,
129 size_t converted_size = 0;
130 DATA_BLOB dom_auth_blob = data_blob_null;
131 enum ndr_err_code ndr_err;
132 bool ok;
133 gnutls_cipher_hd_t cipher_hnd = NULL;
134 gnutls_datum_t _session_key = {
135 .data = session_key.data,
136 .size = session_key.length,
139 authinfo_internal = talloc_zero(
140 mem_ctx, struct lsa_TrustDomainInfoAuthInfoInternal);
141 if (authinfo_internal == NULL) {
142 return false;
145 ok = convert_string_talloc(mem_ctx,
146 CH_UNIX,
147 CH_UTF16,
148 incoming_new,
149 strlen(incoming_new),
150 &in_cur_td_info.AuthInfo.clear.password,
151 &converted_size);
152 if (!ok) {
153 return false;
155 in_cur_td_info.AuthInfo.clear.size = converted_size;
157 ok = convert_string_talloc(mem_ctx,
158 CH_UNIX,
159 CH_UTF16,
160 incoming_old,
161 strlen(incoming_old),
162 &in_prev_td_buf.AuthInfo.clear.password,
163 &converted_size);
164 if (!ok) {
165 return false;
167 in_prev_td_buf.AuthInfo.clear.size = converted_size;
169 ok = convert_string_talloc(mem_ctx,
170 CH_UNIX,
171 CH_UTF16,
172 outgoing_new,
173 strlen(outgoing_new),
174 &out_cur_td_info.AuthInfo.clear.password,
175 &converted_size);
176 if (!ok) {
177 return false;
179 out_cur_td_info.AuthInfo.clear.size = converted_size;
181 ok = convert_string_talloc(mem_ctx,
182 CH_UNIX,
183 CH_UTF16,
184 outgoing_old,
185 strlen(outgoing_old),
186 &out_prev_td_buf.AuthInfo.clear.password,
187 &converted_size);
188 if (!ok) {
189 return false;
191 out_prev_td_buf.AuthInfo.clear.size = converted_size;
193 generate_random_buffer(dom_auth_info.confounder,
194 sizeof(dom_auth_info.confounder));
196 ndr_err = ndr_push_struct_blob(
197 &dom_auth_blob,
198 authinfo_internal,
199 &dom_auth_info,
200 (ndr_push_flags_fn_t)ndr_push_trustDomainPasswords);
201 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
202 return false;
204 generate_random_buffer(dom_auth_info.confounder,
205 sizeof(dom_auth_info.confounder));
207 gnutls_cipher_init(&cipher_hnd,
208 GNUTLS_CIPHER_ARCFOUR_128,
209 &_session_key,
210 NULL);
211 gnutls_cipher_encrypt(cipher_hnd,
212 dom_auth_blob.data,
213 dom_auth_blob.length);
214 gnutls_cipher_deinit(cipher_hnd);
216 authinfo_internal->auth_blob.size = dom_auth_blob.length;
217 authinfo_internal->auth_blob.data = dom_auth_blob.data;
219 *_authinfo_internal = authinfo_internal;
221 return true;
224 bool rpc_lsa_encrypt_trustdom_info_aes(
225 TALLOC_CTX *mem_ctx,
226 const char *incoming_old,
227 const char *incoming_new,
228 const char *outgoing_old,
229 const char *outgoing_new,
230 DATA_BLOB session_key,
231 struct lsa_TrustDomainInfoAuthInfoInternalAES **pauthinfo_internal)
233 struct timeval tv_now = timeval_current();
234 NTTIME now = timeval_to_nttime(&tv_now);
236 struct AuthenticationInformation in_cur_td_info = {
237 .AuthType = TRUST_AUTH_TYPE_CLEAR,
238 .LastUpdateTime = now,
240 struct AuthenticationInformation in_prev_td_buf = {
241 .AuthType = TRUST_AUTH_TYPE_CLEAR,
242 .LastUpdateTime = now,
244 struct AuthenticationInformation out_cur_td_info = {
245 .AuthType = TRUST_AUTH_TYPE_CLEAR,
246 .LastUpdateTime = now,
248 struct AuthenticationInformation out_prev_td_buf = {
249 .AuthType = TRUST_AUTH_TYPE_CLEAR,
250 .LastUpdateTime = now,
254 * This corresponds to MS-LSAD 2.2.7.16 LSAPR_TRUSTED_DOMAIN_AUTH_BLOB.
256 struct trustDomainPasswords dom_auth_info = {
257 .incoming = {
258 .count = 1,
259 .previous = {
260 .count = 1,
261 .array = &in_prev_td_buf,
264 .current = {
265 .count = 1,
266 .array = &in_cur_td_info,
270 .outgoing = {
271 .count = 1,
272 .previous = {
273 .count = 1,
274 .array = &out_prev_td_buf,
277 .current = {
278 .count = 1,
279 .array = &out_cur_td_info,
284 struct lsa_TrustDomainInfoAuthInfoInternalAES *authinfo_internal = NULL;
285 size_t converted_size = 0;
286 DATA_BLOB dom_auth_blob = data_blob_null;
287 enum ndr_err_code ndr_err;
288 bool ok;
289 /* Salt */
290 DATA_BLOB iv = {
291 .length = 0,
293 gnutls_datum_t iv_datum = {
294 .size = 0,
296 /* Encrypted ciphertext */
297 DATA_BLOB ciphertext = data_blob_null;
298 NTSTATUS status;
300 authinfo_internal = talloc_zero(
301 mem_ctx, struct lsa_TrustDomainInfoAuthInfoInternalAES);
302 if (authinfo_internal == NULL) {
303 return false;
306 ok = convert_string_talloc(mem_ctx,
307 CH_UNIX,
308 CH_UTF16,
309 incoming_new,
310 strlen(incoming_new),
311 &in_cur_td_info.AuthInfo.clear.password,
312 &converted_size);
313 if (!ok) {
314 return false;
316 in_cur_td_info.AuthInfo.clear.size = converted_size;
318 ok = convert_string_talloc(mem_ctx,
319 CH_UNIX,
320 CH_UTF16,
321 incoming_old,
322 strlen(incoming_old),
323 &in_prev_td_buf.AuthInfo.clear.password,
324 &converted_size);
325 if (!ok) {
326 return false;
328 in_prev_td_buf.AuthInfo.clear.size = converted_size;
330 ok = convert_string_talloc(mem_ctx,
331 CH_UNIX,
332 CH_UTF16,
333 outgoing_new,
334 strlen(outgoing_new),
335 &out_cur_td_info.AuthInfo.clear.password,
336 &converted_size);
337 if (!ok) {
338 return false;
340 out_cur_td_info.AuthInfo.clear.size = converted_size;
342 ok = convert_string_talloc(mem_ctx,
343 CH_UNIX,
344 CH_UTF16,
345 outgoing_old,
346 strlen(outgoing_old),
347 &out_prev_td_buf.AuthInfo.clear.password,
348 &converted_size);
349 if (!ok) {
350 return false;
352 out_prev_td_buf.AuthInfo.clear.size = converted_size;
354 generate_random_buffer(dom_auth_info.confounder,
355 sizeof(dom_auth_info.confounder));
357 ndr_err = ndr_push_struct_blob(
358 &dom_auth_blob,
359 authinfo_internal,
360 &dom_auth_info,
361 (ndr_push_flags_fn_t)ndr_push_trustDomainPasswords);
362 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
363 return false;
366 /* Create salt */
367 iv.data = iv_datum.data = authinfo_internal->salt;
368 iv.length = iv_datum.size = sizeof(authinfo_internal->salt);
369 generate_nonce_buffer(authinfo_internal->salt,
370 sizeof(authinfo_internal->salt));
372 /* Create encryption key */
373 status = samba_gnutls_aead_aes_256_cbc_hmac_sha512_encrypt(
374 authinfo_internal,
375 &dom_auth_blob,
376 &session_key,
377 &lsa_aes256_enc_key_salt,
378 &lsa_aes256_mac_key_salt,
379 &iv,
380 &ciphertext,
381 authinfo_internal->auth_data);
382 if (!NT_STATUS_IS_OK(status)) {
383 return false;
386 if (ciphertext.length < 520) {
387 return false;
390 authinfo_internal->cipher.data = ciphertext.data;
391 authinfo_internal->cipher.size = ciphertext.length;
393 *pauthinfo_internal = authinfo_internal;
395 return true;