Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : endpoint server for the backupkey interface
5 :
6 : Copyright (C) Matthieu Patou <mat@samba.org> 2010
7 : Copyright (C) Andreas Schneider <asn@samba.org> 2015
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 : #include "includes.h"
24 : #include "rpc_server/dcerpc_server.h"
25 : #include "rpc_server/common/common.h"
26 : #include "librpc/gen_ndr/ndr_backupkey.h"
27 : #include "dsdb/common/util.h"
28 : #include "dsdb/samdb/samdb.h"
29 : #include "lib/ldb/include/ldb_errors.h"
30 : #include "../lib/util/util_ldb.h"
31 : #include "param/param.h"
32 : #include "auth/session.h"
33 : #include "system/network.h"
34 :
35 : #include "../lib/tsocket/tsocket.h"
36 : #include "../libcli/security/security.h"
37 : #include "librpc/gen_ndr/ndr_security.h"
38 : #include "libds/common/roles.h"
39 :
40 : #include <gnutls/gnutls.h>
41 : #include <gnutls/x509.h>
42 : #include <gnutls/crypto.h>
43 : #include <gnutls/abstract.h>
44 :
45 : #include "lib/crypto/gnutls_helpers.h"
46 :
47 : #undef strncasecmp
48 :
49 : #define DCESRV_INTERFACE_BACKUPKEY_BIND(context, iface) \
50 : dcesrv_interface_backupkey_bind(context, iface)
51 5 : static NTSTATUS dcesrv_interface_backupkey_bind(struct dcesrv_connection_context *context,
52 : const struct dcesrv_interface *iface)
53 : {
54 5 : return dcesrv_interface_bind_require_privacy(context, iface);
55 : }
56 :
57 4 : static NTSTATUS set_lsa_secret(TALLOC_CTX *mem_ctx,
58 : struct ldb_context *ldb,
59 : const char *name,
60 : const DATA_BLOB *lsa_secret)
61 : {
62 4 : TALLOC_CTX *frame = talloc_stackframe();
63 0 : struct ldb_message *msg;
64 0 : struct ldb_result *res;
65 4 : struct ldb_dn *system_dn = NULL;
66 0 : struct ldb_val val;
67 0 : int ret;
68 0 : char *name2;
69 4 : struct timeval now = timeval_current();
70 4 : NTTIME nt_now = timeval_to_nttime(&now);
71 4 : const char *attrs[] = {
72 : NULL
73 : };
74 :
75 4 : msg = ldb_msg_new(frame);
76 4 : if (msg == NULL) {
77 0 : talloc_free(frame);
78 0 : return NT_STATUS_NO_MEMORY;
79 : }
80 :
81 : /*
82 : * This function is a lot like dcesrv_lsa_CreateSecret
83 : * in the rpc_server/lsa directory
84 : * The reason why we duplicate the effort here is that:
85 : * * we want to keep the former function static
86 : * * we want to avoid the burden of doing LSA calls
87 : * when we can just manipulate the secrets directly
88 : * * taillor the function to the particular needs of backup protocol
89 : */
90 :
91 4 : system_dn = samdb_system_container_dn(ldb, frame);
92 4 : if (system_dn == NULL) {
93 0 : talloc_free(frame);
94 0 : return NT_STATUS_NO_MEMORY;
95 : }
96 :
97 4 : name2 = talloc_asprintf(msg, "%s Secret", name);
98 4 : if (name2 == NULL) {
99 0 : talloc_free(frame);
100 0 : return NT_STATUS_NO_MEMORY;
101 : }
102 :
103 4 : ret = ldb_search(ldb, frame, &res, system_dn, LDB_SCOPE_SUBTREE, attrs,
104 : "(&(cn=%s)(objectclass=secret))",
105 : ldb_binary_encode_string(frame, name2));
106 :
107 4 : if (ret != LDB_SUCCESS || res->count != 0 ) {
108 0 : DEBUG(2, ("Secret %s already exists !\n", name2));
109 0 : talloc_free(frame);
110 0 : return NT_STATUS_OBJECT_NAME_COLLISION;
111 : }
112 :
113 : /*
114 : * We don't care about previous value as we are
115 : * here only if the key didn't exists before
116 : */
117 :
118 4 : msg->dn = ldb_dn_copy(frame, system_dn);
119 4 : if (msg->dn == NULL) {
120 0 : talloc_free(frame);
121 0 : return NT_STATUS_NO_MEMORY;
122 : }
123 4 : if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
124 0 : talloc_free(frame);
125 0 : return NT_STATUS_NO_MEMORY;
126 : }
127 :
128 4 : ret = ldb_msg_add_string(msg, "cn", name2);
129 4 : if (ret != LDB_SUCCESS) {
130 0 : talloc_free(frame);
131 0 : return NT_STATUS_NO_MEMORY;
132 : }
133 4 : ret = ldb_msg_add_string(msg, "objectClass", "secret");
134 4 : if (ret != LDB_SUCCESS) {
135 0 : talloc_free(frame);
136 0 : return NT_STATUS_NO_MEMORY;
137 : }
138 4 : ret = samdb_msg_add_uint64(ldb, frame, msg, "priorSetTime", nt_now);
139 4 : if (ret != LDB_SUCCESS) {
140 0 : talloc_free(frame);
141 0 : return NT_STATUS_NO_MEMORY;
142 : }
143 4 : val.data = lsa_secret->data;
144 4 : val.length = lsa_secret->length;
145 4 : ret = ldb_msg_add_value(msg, "currentValue", &val, NULL);
146 4 : if (ret != LDB_SUCCESS) {
147 0 : talloc_free(frame);
148 0 : return NT_STATUS_NO_MEMORY;
149 : }
150 4 : ret = samdb_msg_add_uint64(ldb, frame, msg, "lastSetTime", nt_now);
151 4 : if (ret != LDB_SUCCESS) {
152 0 : talloc_free(frame);
153 0 : return NT_STATUS_NO_MEMORY;
154 : }
155 :
156 : /*
157 : * create the secret with DSDB_MODIFY_RELAX
158 : * otherwise dsdb/samdb/ldb_modules/objectclass.c forbid
159 : * the create of LSA secret object
160 : */
161 4 : ret = dsdb_add(ldb, msg, DSDB_MODIFY_RELAX);
162 4 : if (ret != LDB_SUCCESS) {
163 0 : DEBUG(2,("Failed to create secret record %s: %s\n",
164 : ldb_dn_get_linearized(msg->dn),
165 : ldb_errstring(ldb)));
166 0 : talloc_free(frame);
167 0 : return NT_STATUS_ACCESS_DENIED;
168 : }
169 :
170 4 : talloc_free(frame);
171 4 : return NT_STATUS_OK;
172 : }
173 :
174 : /* This function is pretty much like dcesrv_lsa_QuerySecret */
175 81 : static NTSTATUS get_lsa_secret(TALLOC_CTX *mem_ctx,
176 : struct ldb_context *ldb,
177 : const char *name,
178 : DATA_BLOB *lsa_secret)
179 : {
180 0 : TALLOC_CTX *tmp_mem;
181 0 : struct ldb_result *res;
182 81 : struct ldb_dn *system_dn = NULL;
183 0 : const struct ldb_val *val;
184 0 : uint8_t *data;
185 81 : const char *attrs[] = {
186 : "currentValue",
187 : NULL
188 : };
189 0 : int ret;
190 :
191 81 : lsa_secret->data = NULL;
192 81 : lsa_secret->length = 0;
193 :
194 81 : tmp_mem = talloc_new(mem_ctx);
195 81 : if (tmp_mem == NULL) {
196 0 : return NT_STATUS_NO_MEMORY;
197 : }
198 :
199 81 : system_dn = samdb_system_container_dn(ldb, tmp_mem);
200 81 : if (system_dn == NULL) {
201 0 : talloc_free(tmp_mem);
202 0 : return NT_STATUS_NO_MEMORY;
203 : }
204 :
205 81 : ret = ldb_search(ldb, tmp_mem, &res, system_dn, LDB_SCOPE_SUBTREE, attrs,
206 : "(&(cn=%s Secret)(objectclass=secret))",
207 : ldb_binary_encode_string(tmp_mem, name));
208 :
209 81 : if (ret != LDB_SUCCESS) {
210 0 : talloc_free(tmp_mem);
211 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
212 : }
213 81 : if (res->count == 0) {
214 5 : talloc_free(tmp_mem);
215 5 : return NT_STATUS_RESOURCE_NAME_NOT_FOUND;
216 : }
217 76 : if (res->count > 1) {
218 0 : DEBUG(2, ("Secret %s collision\n", name));
219 0 : talloc_free(tmp_mem);
220 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
221 : }
222 :
223 76 : val = ldb_msg_find_ldb_val(res->msgs[0], "currentValue");
224 76 : if (val == NULL) {
225 : /*
226 : * The secret object is here but we don't have the secret value
227 : * The most common case is a RODC
228 : */
229 0 : *lsa_secret = data_blob_null;
230 0 : talloc_free(tmp_mem);
231 0 : return NT_STATUS_OK;
232 : }
233 :
234 76 : data = val->data;
235 76 : lsa_secret->data = talloc_move(mem_ctx, &data);
236 76 : lsa_secret->length = val->length;
237 :
238 76 : talloc_free(tmp_mem);
239 76 : return NT_STATUS_OK;
240 : }
241 :
242 64 : static int reverse_and_get_bignum(TALLOC_CTX *mem_ctx,
243 : DATA_BLOB blob,
244 : gnutls_datum_t *datum)
245 : {
246 0 : uint32_t i;
247 :
248 64 : datum->data = talloc_array(mem_ctx, uint8_t, blob.length);
249 64 : if (datum->data == NULL) {
250 0 : return -1;
251 : }
252 :
253 9312 : for(i = 0; i < blob.length; i++) {
254 9248 : datum->data[i] = blob.data[blob.length - i - 1];
255 : }
256 64 : datum->size = blob.length;
257 :
258 64 : return 0;
259 : }
260 :
261 8 : static NTSTATUS get_pk_from_raw_keypair_params(TALLOC_CTX *ctx,
262 : struct bkrp_exported_RSA_key_pair *keypair,
263 : gnutls_privkey_t *pk)
264 : {
265 8 : gnutls_x509_privkey_t x509_privkey = NULL;
266 8 : gnutls_privkey_t privkey = NULL;
267 0 : gnutls_datum_t m, e, d, p, q, u, e1, e2;
268 0 : int rc;
269 :
270 8 : rc = reverse_and_get_bignum(ctx, keypair->modulus, &m);
271 8 : if (rc != 0) {
272 0 : return NT_STATUS_INVALID_PARAMETER;
273 : }
274 8 : rc = reverse_and_get_bignum(ctx, keypair->public_exponent, &e);
275 8 : if (rc != 0) {
276 0 : return NT_STATUS_INVALID_PARAMETER;
277 : }
278 8 : rc = reverse_and_get_bignum(ctx, keypair->private_exponent, &d);
279 8 : if (rc != 0) {
280 0 : return NT_STATUS_INVALID_PARAMETER;
281 : }
282 :
283 8 : rc = reverse_and_get_bignum(ctx, keypair->prime1, &p);
284 8 : if (rc != 0) {
285 0 : return NT_STATUS_INVALID_PARAMETER;
286 : }
287 8 : rc = reverse_and_get_bignum(ctx, keypair->prime2, &q);
288 8 : if (rc != 0) {
289 0 : return NT_STATUS_INVALID_PARAMETER;
290 : }
291 :
292 8 : rc = reverse_and_get_bignum(ctx, keypair->coefficient, &u);
293 8 : if (rc != 0) {
294 0 : return NT_STATUS_INVALID_PARAMETER;
295 : }
296 :
297 8 : rc = reverse_and_get_bignum(ctx, keypair->exponent1, &e1);
298 8 : if (rc != 0) {
299 0 : return NT_STATUS_INVALID_PARAMETER;
300 : }
301 8 : rc = reverse_and_get_bignum(ctx, keypair->exponent2, &e2);
302 8 : if (rc != 0) {
303 0 : return NT_STATUS_INVALID_PARAMETER;
304 : }
305 :
306 8 : rc = gnutls_x509_privkey_init(&x509_privkey);
307 8 : if (rc != GNUTLS_E_SUCCESS) {
308 0 : DBG_ERR("gnutls_x509_privkey_init failed - %s\n",
309 : gnutls_strerror(rc));
310 0 : return NT_STATUS_INTERNAL_ERROR;
311 : }
312 :
313 8 : rc = gnutls_x509_privkey_import_rsa_raw2(x509_privkey,
314 : &m,
315 : &e,
316 : &d,
317 : &p,
318 : &q,
319 : &u,
320 : &e1,
321 : &e2);
322 8 : if (rc != GNUTLS_E_SUCCESS) {
323 0 : DBG_ERR("gnutls_x509_privkey_import_rsa_raw2 failed - %s\n",
324 : gnutls_strerror(rc));
325 0 : return NT_STATUS_INTERNAL_ERROR;
326 : }
327 :
328 8 : rc = gnutls_privkey_init(&privkey);
329 8 : if (rc != GNUTLS_E_SUCCESS) {
330 0 : DBG_ERR("gnutls_privkey_init failed - %s\n",
331 : gnutls_strerror(rc));
332 0 : gnutls_x509_privkey_deinit(x509_privkey);
333 0 : return NT_STATUS_INTERNAL_ERROR;
334 : }
335 :
336 8 : rc = gnutls_privkey_import_x509(privkey,
337 : x509_privkey,
338 : GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
339 8 : if (rc != GNUTLS_E_SUCCESS) {
340 0 : DBG_ERR("gnutls_privkey_import_x509 failed - %s\n",
341 : gnutls_strerror(rc));
342 0 : gnutls_x509_privkey_deinit(x509_privkey);
343 0 : return NT_STATUS_INTERNAL_ERROR;
344 : }
345 :
346 8 : *pk = privkey;
347 :
348 8 : return NT_STATUS_OK;
349 : }
350 :
351 6 : static WERROR get_and_verify_access_check(TALLOC_CTX *sub_ctx,
352 : uint32_t version,
353 : uint8_t *key_and_iv,
354 : uint8_t *access_check,
355 : uint32_t access_check_len,
356 : struct auth_session_info *session_info)
357 : {
358 0 : struct bkrp_access_check_v2 uncrypted_accesscheckv2;
359 0 : struct bkrp_access_check_v3 uncrypted_accesscheckv3;
360 6 : gnutls_cipher_hd_t cipher_handle = { 0 };
361 0 : gnutls_cipher_algorithm_t cipher_algo;
362 0 : DATA_BLOB blob_us;
363 0 : enum ndr_err_code ndr_err;
364 0 : gnutls_datum_t key;
365 0 : gnutls_datum_t iv;
366 :
367 6 : struct dom_sid *access_sid = NULL;
368 6 : struct dom_sid *caller_sid = NULL;
369 0 : int rc;
370 :
371 6 : switch (version) {
372 5 : case 2:
373 5 : cipher_algo = GNUTLS_CIPHER_3DES_CBC;
374 5 : break;
375 1 : case 3:
376 1 : cipher_algo = GNUTLS_CIPHER_AES_256_CBC;
377 1 : break;
378 0 : default:
379 0 : return WERR_INVALID_DATA;
380 : }
381 :
382 6 : key.data = key_and_iv;
383 6 : key.size = gnutls_cipher_get_key_size(cipher_algo);
384 :
385 6 : iv.data = key_and_iv + key.size;
386 6 : iv.size = gnutls_cipher_get_iv_size(cipher_algo);
387 :
388 : /* Allocate data structure for the plaintext */
389 6 : blob_us = data_blob_talloc_zero(sub_ctx, access_check_len);
390 6 : if (blob_us.data == NULL) {
391 0 : return WERR_INVALID_DATA;
392 : }
393 :
394 6 : rc = gnutls_cipher_init(&cipher_handle,
395 : cipher_algo,
396 : &key,
397 : &iv);
398 6 : if (rc < 0) {
399 0 : DBG_ERR("gnutls_cipher_init failed: %s\n",
400 : gnutls_strerror(rc));
401 0 : return WERR_INVALID_DATA;
402 : }
403 :
404 6 : rc = gnutls_cipher_decrypt2(cipher_handle,
405 : access_check,
406 : access_check_len,
407 6 : blob_us.data,
408 : blob_us.length);
409 6 : gnutls_cipher_deinit(cipher_handle);
410 6 : if (rc < 0) {
411 0 : DBG_ERR("gnutls_cipher_decrypt2 failed: %s\n",
412 : gnutls_strerror(rc));
413 0 : return WERR_INVALID_DATA;
414 : }
415 :
416 6 : switch (version) {
417 5 : case 2:
418 5 : {
419 5 : uint32_t hash_size = 20;
420 5 : uint8_t hash[hash_size];
421 0 : gnutls_hash_hd_t dig_ctx;
422 :
423 5 : ndr_err = ndr_pull_struct_blob(&blob_us, sub_ctx, &uncrypted_accesscheckv2,
424 : (ndr_pull_flags_fn_t)ndr_pull_bkrp_access_check_v2);
425 5 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
426 : /* Unable to unmarshall */
427 0 : return WERR_INVALID_DATA;
428 : }
429 5 : if (uncrypted_accesscheckv2.magic != 0x1) {
430 : /* wrong magic */
431 1 : return WERR_INVALID_DATA;
432 : }
433 :
434 4 : rc = gnutls_hash_init(&dig_ctx, GNUTLS_DIG_SHA1);
435 4 : if (rc != GNUTLS_E_SUCCESS) {
436 0 : return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
437 : }
438 4 : rc = gnutls_hash(dig_ctx,
439 4 : blob_us.data,
440 4 : blob_us.length - hash_size);
441 4 : gnutls_hash_deinit(dig_ctx, hash);
442 4 : if (rc != GNUTLS_E_SUCCESS) {
443 0 : return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
444 : }
445 :
446 : /*
447 : * We free it after the sha1 calculation because blob.data
448 : * points to the same area
449 : */
450 :
451 4 : if (!mem_equal_const_time(hash, uncrypted_accesscheckv2.hash, hash_size)) {
452 1 : DEBUG(2, ("Wrong hash value in the access check in backup key remote protocol\n"));
453 1 : return WERR_INVALID_DATA;
454 : }
455 3 : access_sid = &(uncrypted_accesscheckv2.sid);
456 3 : break;
457 : }
458 1 : case 3:
459 1 : {
460 1 : uint32_t hash_size = 64;
461 1 : uint8_t hash[hash_size];
462 0 : gnutls_hash_hd_t dig_ctx;
463 :
464 1 : ndr_err = ndr_pull_struct_blob(&blob_us, sub_ctx, &uncrypted_accesscheckv3,
465 : (ndr_pull_flags_fn_t)ndr_pull_bkrp_access_check_v3);
466 1 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
467 : /* Unable to unmarshall */
468 0 : return WERR_INVALID_DATA;
469 : }
470 1 : if (uncrypted_accesscheckv3.magic != 0x1) {
471 : /* wrong magic */
472 0 : return WERR_INVALID_DATA;
473 : }
474 :
475 1 : rc = gnutls_hash_init(&dig_ctx, GNUTLS_DIG_SHA512);
476 1 : if (rc != GNUTLS_E_SUCCESS) {
477 0 : return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
478 : }
479 1 : rc = gnutls_hash(dig_ctx,
480 1 : blob_us.data,
481 1 : blob_us.length - hash_size);
482 1 : gnutls_hash_deinit(dig_ctx, hash);
483 1 : if (rc != GNUTLS_E_SUCCESS) {
484 0 : return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
485 : }
486 :
487 : /*
488 : * We free it after the sha1 calculation because blob.data
489 : * points to the same area
490 : */
491 :
492 1 : if (!mem_equal_const_time(hash, uncrypted_accesscheckv3.hash, hash_size)) {
493 0 : DEBUG(2, ("Wrong hash value in the access check in backup key remote protocol\n"));
494 0 : return WERR_INVALID_DATA;
495 : }
496 1 : access_sid = &(uncrypted_accesscheckv3.sid);
497 1 : break;
498 : }
499 0 : default:
500 : /* Never reached normally as we filtered at the switch / case level */
501 0 : return WERR_INVALID_DATA;
502 : }
503 :
504 4 : caller_sid = &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
505 :
506 4 : if (!dom_sid_equal(caller_sid, access_sid)) {
507 1 : return WERR_INVALID_ACCESS;
508 : }
509 3 : return WERR_OK;
510 : }
511 :
512 : /*
513 : * We have some data, such as saved website or IMAP passwords that the
514 : * client has in profile on-disk. This needs to be decrypted. This
515 : * version gives the server the data over the network (protected by
516 : * the X.509 certificate and public key encryption, and asks that it
517 : * be decrypted returned for short-term use, protected only by the
518 : * negotiated transport encryption.
519 : *
520 : * The data is NOT stored in the LSA, but a X.509 certificate, public
521 : * and private keys used to encrypt the data will be stored. There is
522 : * only one active encryption key pair and certificate per domain, it
523 : * is pointed at with G$BCKUPKEY_PREFERRED in the LSA secrets store.
524 : *
525 : * The potentially multiple valid decrypting key pairs are in turn
526 : * stored in the LSA secrets store as G$BCKUPKEY_keyGuidString.
527 : *
528 : */
529 10 : static WERROR bkrp_client_wrap_decrypt_data(struct dcesrv_call_state *dce_call,
530 : TALLOC_CTX *mem_ctx,
531 : struct bkrp_BackupKey *r,
532 : struct ldb_context *ldb_ctx)
533 : {
534 0 : struct auth_session_info *session_info =
535 10 : dcesrv_call_session_info(dce_call);
536 0 : struct bkrp_client_side_wrapped uncrypt_request;
537 0 : DATA_BLOB blob;
538 0 : enum ndr_err_code ndr_err;
539 0 : char *guid_string;
540 0 : char *cert_secret_name;
541 0 : DATA_BLOB lsa_secret;
542 10 : DATA_BLOB *uncrypted_data = NULL;
543 0 : NTSTATUS status;
544 0 : uint32_t requested_version;
545 :
546 10 : blob.data = r->in.data_in;
547 10 : blob.length = r->in.data_in_len;
548 :
549 10 : if (r->in.data_in_len < 4 || r->in.data_in == NULL) {
550 0 : return WERR_INVALID_PARAMETER;
551 : }
552 :
553 : /*
554 : * We check for the version here, so we can actually print the
555 : * message as we are unlikely to parse it with NDR.
556 : */
557 10 : requested_version = IVAL(r->in.data_in, 0);
558 10 : if ((requested_version != BACKUPKEY_CLIENT_WRAP_VERSION2)
559 4 : && (requested_version != BACKUPKEY_CLIENT_WRAP_VERSION3)) {
560 1 : DEBUG(1, ("Request for unknown BackupKey sub-protocol %d\n", requested_version));
561 1 : return WERR_INVALID_PARAMETER;
562 : }
563 :
564 9 : ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &uncrypt_request,
565 : (ndr_pull_flags_fn_t)ndr_pull_bkrp_client_side_wrapped);
566 9 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
567 0 : return WERR_INVALID_PARAMETER;
568 : }
569 :
570 9 : if ((uncrypt_request.version != BACKUPKEY_CLIENT_WRAP_VERSION2)
571 3 : && (uncrypt_request.version != BACKUPKEY_CLIENT_WRAP_VERSION3)) {
572 0 : DEBUG(1, ("Request for unknown BackupKey sub-protocol %d\n", uncrypt_request.version));
573 0 : return WERR_INVALID_PARAMETER;
574 : }
575 :
576 9 : guid_string = GUID_string(mem_ctx, &uncrypt_request.guid);
577 9 : if (guid_string == NULL) {
578 0 : return WERR_NOT_ENOUGH_MEMORY;
579 : }
580 :
581 9 : cert_secret_name = talloc_asprintf(mem_ctx,
582 : "BCKUPKEY_%s",
583 : guid_string);
584 9 : if (cert_secret_name == NULL) {
585 0 : return WERR_NOT_ENOUGH_MEMORY;
586 : }
587 :
588 9 : status = get_lsa_secret(mem_ctx,
589 : ldb_ctx,
590 : cert_secret_name,
591 : &lsa_secret);
592 9 : if (!NT_STATUS_IS_OK(status)) {
593 1 : DEBUG(10, ("Error while fetching secret %s\n", cert_secret_name));
594 1 : return WERR_INVALID_DATA;
595 8 : } else if (lsa_secret.length == 0) {
596 : /* we do not have the real secret attribute, like if we are an RODC */
597 0 : return WERR_INVALID_PARAMETER;
598 : } else {
599 0 : struct bkrp_exported_RSA_key_pair keypair;
600 8 : gnutls_privkey_t privkey = NULL;
601 0 : gnutls_datum_t reversed_secret;
602 0 : gnutls_datum_t uncrypted_secret;
603 0 : uint32_t i;
604 0 : DATA_BLOB blob_us;
605 0 : WERROR werr;
606 0 : int rc;
607 :
608 8 : ndr_err = ndr_pull_struct_blob(&lsa_secret, mem_ctx, &keypair, (ndr_pull_flags_fn_t)ndr_pull_bkrp_exported_RSA_key_pair);
609 8 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
610 0 : DEBUG(2, ("Unable to parse the ndr encoded cert in key %s\n", cert_secret_name));
611 0 : return WERR_FILE_NOT_FOUND;
612 : }
613 :
614 8 : status = get_pk_from_raw_keypair_params(mem_ctx,
615 : &keypair,
616 : &privkey);
617 8 : if (!NT_STATUS_IS_OK(status)) {
618 0 : return WERR_INTERNAL_ERROR;
619 : }
620 :
621 8 : reversed_secret.data = talloc_array(mem_ctx, uint8_t,
622 : uncrypt_request.encrypted_secret_len);
623 8 : if (reversed_secret.data == NULL) {
624 0 : gnutls_privkey_deinit(privkey);
625 0 : return WERR_NOT_ENOUGH_MEMORY;
626 : }
627 :
628 : /* The secret has to be reversed ... */
629 2056 : for(i=0; i< uncrypt_request.encrypted_secret_len; i++) {
630 2048 : uint8_t *reversed = (uint8_t *)reversed_secret.data;
631 2048 : uint8_t *uncrypt = uncrypt_request.encrypted_secret;
632 2048 : reversed[i] = uncrypt[uncrypt_request.encrypted_secret_len - 1 - i];
633 : }
634 8 : reversed_secret.size = uncrypt_request.encrypted_secret_len;
635 :
636 : /*
637 : * Let's try to decrypt the secret now that
638 : * we have the private key ...
639 : */
640 8 : rc = gnutls_privkey_decrypt_data(privkey,
641 : 0,
642 : &reversed_secret,
643 : &uncrypted_secret);
644 8 : gnutls_privkey_deinit(privkey);
645 8 : if (rc != GNUTLS_E_SUCCESS) {
646 : /* We are not able to decrypt the secret, looks like something is wrong */
647 1 : return WERR_INVALID_PARAMETER;
648 : }
649 7 : blob_us.data = uncrypted_secret.data;
650 7 : blob_us.length = uncrypted_secret.size;
651 :
652 7 : if (uncrypt_request.version == 2) {
653 0 : struct bkrp_encrypted_secret_v2 uncrypted_secretv2;
654 :
655 5 : ndr_err = ndr_pull_struct_blob(&blob_us, mem_ctx, &uncrypted_secretv2,
656 : (ndr_pull_flags_fn_t)ndr_pull_bkrp_encrypted_secret_v2);
657 5 : gnutls_free(uncrypted_secret.data);
658 5 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
659 : /* Unable to unmarshall */
660 0 : return WERR_INVALID_DATA;
661 : }
662 5 : if (uncrypted_secretv2.magic != 0x20) {
663 : /* wrong magic */
664 0 : return WERR_INVALID_DATA;
665 : }
666 :
667 5 : werr = get_and_verify_access_check(mem_ctx, 2,
668 : uncrypted_secretv2.payload_key,
669 : uncrypt_request.access_check,
670 : uncrypt_request.access_check_len,
671 : session_info);
672 5 : if (!W_ERROR_IS_OK(werr)) {
673 3 : return werr;
674 : }
675 2 : uncrypted_data = talloc(mem_ctx, DATA_BLOB);
676 2 : if (uncrypted_data == NULL) {
677 0 : return WERR_INVALID_DATA;
678 : }
679 :
680 2 : uncrypted_data->data = uncrypted_secretv2.secret;
681 2 : uncrypted_data->length = uncrypted_secretv2.secret_len;
682 : }
683 4 : if (uncrypt_request.version == 3) {
684 0 : struct bkrp_encrypted_secret_v3 uncrypted_secretv3;
685 :
686 2 : ndr_err = ndr_pull_struct_blob(&blob_us, mem_ctx, &uncrypted_secretv3,
687 : (ndr_pull_flags_fn_t)ndr_pull_bkrp_encrypted_secret_v3);
688 2 : gnutls_free(uncrypted_secret.data);
689 2 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
690 : /* Unable to unmarshall */
691 0 : return WERR_INVALID_DATA;
692 : }
693 :
694 2 : if (uncrypted_secretv3.magic1 != 0x30 ||
695 1 : uncrypted_secretv3.magic2 != 0x6610 ||
696 1 : uncrypted_secretv3.magic3 != 0x800e) {
697 : /* wrong magic */
698 1 : return WERR_INVALID_DATA;
699 : }
700 :
701 : /*
702 : * Confirm that the caller is permitted to
703 : * read this particular data. Because one key
704 : * pair is used per domain, the caller could
705 : * have stolen the profile data on-disk and
706 : * would otherwise be able to read the
707 : * passwords.
708 : */
709 :
710 1 : werr = get_and_verify_access_check(mem_ctx, 3,
711 : uncrypted_secretv3.payload_key,
712 : uncrypt_request.access_check,
713 : uncrypt_request.access_check_len,
714 : session_info);
715 1 : if (!W_ERROR_IS_OK(werr)) {
716 0 : return werr;
717 : }
718 :
719 1 : uncrypted_data = talloc(mem_ctx, DATA_BLOB);
720 1 : if (uncrypted_data == NULL) {
721 0 : return WERR_INVALID_DATA;
722 : }
723 :
724 1 : uncrypted_data->data = uncrypted_secretv3.secret;
725 1 : uncrypted_data->length = uncrypted_secretv3.secret_len;
726 : }
727 :
728 : /*
729 : * Yeah if we are here all looks pretty good:
730 : * - hash is ok
731 : * - user sid is the same as the one in access check
732 : * - we were able to decrypt the whole stuff
733 : */
734 : }
735 :
736 3 : if (uncrypted_data->data == NULL) {
737 0 : return WERR_INVALID_DATA;
738 : }
739 :
740 : /* There is a magic value at the beginning of the data
741 : * we can use an ad hoc structure but as the
742 : * parent structure is just an array of bytes it is a lot of
743 : * work just prepending 4 bytes
744 : */
745 3 : *(r->out.data_out) = talloc_zero_array(mem_ctx, uint8_t, uncrypted_data->length + 4);
746 3 : W_ERROR_HAVE_NO_MEMORY(*(r->out.data_out));
747 3 : memcpy(4+*(r->out.data_out), uncrypted_data->data, uncrypted_data->length);
748 3 : *(r->out.data_out_len) = uncrypted_data->length + 4;
749 :
750 3 : return WERR_OK;
751 : }
752 :
753 8 : static DATA_BLOB *reverse_and_get_blob(TALLOC_CTX *mem_ctx,
754 : gnutls_datum_t *datum)
755 : {
756 0 : DATA_BLOB *blob;
757 0 : size_t i;
758 :
759 8 : blob = talloc(mem_ctx, DATA_BLOB);
760 8 : if (blob == NULL) {
761 0 : return NULL;
762 : }
763 :
764 8 : blob->length = datum->size;
765 8 : if (datum->data[0] == '\0') {
766 : /* The datum has a leading byte zero, skip it */
767 6 : blob->length = datum->size - 1;
768 : }
769 8 : blob->data = talloc_zero_array(mem_ctx, uint8_t, blob->length);
770 8 : if (blob->data == NULL) {
771 0 : talloc_free(blob);
772 0 : return NULL;
773 : }
774 :
775 1163 : for (i = 0; i < blob->length; i++) {
776 1155 : blob->data[i] = datum->data[datum->size - i - 1];
777 : }
778 :
779 8 : return blob;
780 : }
781 :
782 1 : static WERROR create_privkey_rsa(gnutls_privkey_t *pk)
783 : {
784 1 : int bits = 2048;
785 1 : gnutls_x509_privkey_t x509_privkey = NULL;
786 1 : gnutls_privkey_t privkey = NULL;
787 0 : int rc;
788 :
789 1 : rc = gnutls_x509_privkey_init(&x509_privkey);
790 1 : if (rc != GNUTLS_E_SUCCESS) {
791 0 : DBG_ERR("gnutls_x509_privkey_init failed - %s\n",
792 : gnutls_strerror(rc));
793 0 : return WERR_INTERNAL_ERROR;
794 : }
795 :
796 1 : rc = gnutls_x509_privkey_generate(x509_privkey,
797 : GNUTLS_PK_RSA,
798 : bits,
799 : 0);
800 1 : if (rc != GNUTLS_E_SUCCESS) {
801 0 : DBG_ERR("gnutls_x509_privkey_generate failed - %s\n",
802 : gnutls_strerror(rc));
803 0 : gnutls_x509_privkey_deinit(x509_privkey);
804 0 : return WERR_INTERNAL_ERROR;
805 : }
806 :
807 1 : rc = gnutls_privkey_init(&privkey);
808 1 : if (rc != GNUTLS_E_SUCCESS) {
809 0 : DBG_ERR("gnutls_privkey_init failed - %s\n",
810 : gnutls_strerror(rc));
811 0 : gnutls_x509_privkey_deinit(x509_privkey);
812 0 : return WERR_INTERNAL_ERROR;
813 : }
814 :
815 1 : rc = gnutls_privkey_import_x509(privkey,
816 : x509_privkey,
817 : GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
818 1 : if (rc != GNUTLS_E_SUCCESS) {
819 0 : DBG_ERR("gnutls_privkey_import_x509 failed - %s\n",
820 : gnutls_strerror(rc));
821 0 : gnutls_x509_privkey_deinit(x509_privkey);
822 0 : return WERR_INTERNAL_ERROR;
823 : }
824 :
825 1 : *pk = privkey;
826 :
827 1 : return WERR_OK;
828 : }
829 :
830 1 : static WERROR self_sign_cert(TALLOC_CTX *mem_ctx,
831 : time_t lifetime,
832 : const char *dn,
833 : gnutls_privkey_t issuer_privkey,
834 : gnutls_x509_crt_t *certificate,
835 : DATA_BLOB *guidblob)
836 : {
837 0 : gnutls_datum_t unique_id;
838 0 : gnutls_datum_t serial_number;
839 0 : gnutls_x509_crt_t issuer_cert;
840 0 : gnutls_x509_privkey_t x509_issuer_privkey;
841 1 : time_t activation = time(NULL);
842 1 : time_t expiry = activation + lifetime;
843 0 : const char *error_string;
844 0 : uint8_t *reversed;
845 0 : size_t i;
846 0 : int rc;
847 :
848 1 : unique_id.size = guidblob->length;
849 1 : unique_id.data = talloc_memdup(mem_ctx,
850 : guidblob->data,
851 : guidblob->length);
852 1 : if (unique_id.data == NULL) {
853 0 : return WERR_NOT_ENOUGH_MEMORY;
854 : }
855 :
856 1 : reversed = talloc_array(mem_ctx, uint8_t, guidblob->length);
857 1 : if (reversed == NULL) {
858 0 : talloc_free(unique_id.data);
859 0 : return WERR_NOT_ENOUGH_MEMORY;
860 : }
861 :
862 : /* Native AD generates certificates with serialnumber in reversed notation */
863 17 : for (i = 0; i < guidblob->length; i++) {
864 16 : uint8_t *uncrypt = guidblob->data;
865 16 : reversed[i] = uncrypt[guidblob->length - i - 1];
866 : }
867 1 : serial_number.size = guidblob->length;
868 1 : serial_number.data = reversed;
869 :
870 : /* Create certificate to sign */
871 1 : rc = gnutls_x509_crt_init(&issuer_cert);
872 1 : if (rc != GNUTLS_E_SUCCESS) {
873 0 : DBG_ERR("gnutls_x509_crt_init failed - %s\n",
874 : gnutls_strerror(rc));
875 0 : return WERR_NOT_ENOUGH_MEMORY;
876 : }
877 :
878 1 : rc = gnutls_x509_crt_set_dn(issuer_cert, dn, &error_string);
879 1 : if (rc != GNUTLS_E_SUCCESS) {
880 0 : DBG_ERR("gnutls_x509_crt_set_dn failed - %s (%s)\n",
881 : gnutls_strerror(rc),
882 : error_string);
883 0 : gnutls_x509_crt_deinit(issuer_cert);
884 0 : return WERR_INVALID_PARAMETER;
885 : }
886 :
887 1 : rc = gnutls_x509_crt_set_issuer_dn(issuer_cert, dn, &error_string);
888 1 : if (rc != GNUTLS_E_SUCCESS) {
889 0 : DBG_ERR("gnutls_x509_crt_set_issuer_dn failed - %s (%s)\n",
890 : gnutls_strerror(rc),
891 : error_string);
892 0 : gnutls_x509_crt_deinit(issuer_cert);
893 0 : return WERR_INVALID_PARAMETER;
894 : }
895 :
896 : /* Get x509 privkey for subjectPublicKeyInfo */
897 1 : rc = gnutls_x509_privkey_init(&x509_issuer_privkey);
898 1 : if (rc != GNUTLS_E_SUCCESS) {
899 0 : DBG_ERR("gnutls_x509_privkey_init failed - %s\n",
900 : gnutls_strerror(rc));
901 0 : gnutls_x509_crt_deinit(issuer_cert);
902 0 : return WERR_INVALID_PARAMETER;
903 : }
904 :
905 1 : rc = gnutls_privkey_export_x509(issuer_privkey,
906 : &x509_issuer_privkey);
907 1 : if (rc != GNUTLS_E_SUCCESS) {
908 0 : DBG_ERR("gnutls_x509_privkey_init failed - %s\n",
909 : gnutls_strerror(rc));
910 0 : gnutls_x509_privkey_deinit(x509_issuer_privkey);
911 0 : gnutls_x509_crt_deinit(issuer_cert);
912 0 : return WERR_INVALID_PARAMETER;
913 : }
914 :
915 : /* Set subjectPublicKeyInfo */
916 1 : rc = gnutls_x509_crt_set_key(issuer_cert, x509_issuer_privkey);
917 1 : gnutls_x509_privkey_deinit(x509_issuer_privkey);
918 1 : if (rc != GNUTLS_E_SUCCESS) {
919 0 : DBG_ERR("gnutls_x509_crt_set_pubkey failed - %s\n",
920 : gnutls_strerror(rc));
921 0 : gnutls_x509_crt_deinit(issuer_cert);
922 0 : return WERR_INVALID_PARAMETER;
923 : }
924 :
925 1 : rc = gnutls_x509_crt_set_activation_time(issuer_cert, activation);
926 1 : if (rc != GNUTLS_E_SUCCESS) {
927 0 : DBG_ERR("gnutls_x509_crt_set_activation_time failed - %s\n",
928 : gnutls_strerror(rc));
929 0 : gnutls_x509_crt_deinit(issuer_cert);
930 0 : return WERR_INVALID_PARAMETER;
931 : }
932 :
933 1 : rc = gnutls_x509_crt_set_expiration_time(issuer_cert, expiry);
934 1 : if (rc != GNUTLS_E_SUCCESS) {
935 0 : DBG_ERR("gnutls_x509_crt_set_expiration_time failed - %s\n",
936 : gnutls_strerror(rc));
937 0 : gnutls_x509_crt_deinit(issuer_cert);
938 0 : return WERR_INVALID_PARAMETER;
939 : }
940 :
941 1 : rc = gnutls_x509_crt_set_version(issuer_cert, 3);
942 1 : if (rc != GNUTLS_E_SUCCESS) {
943 0 : DBG_ERR("gnutls_x509_crt_set_version failed - %s\n",
944 : gnutls_strerror(rc));
945 0 : gnutls_x509_crt_deinit(issuer_cert);
946 0 : return WERR_INVALID_PARAMETER;
947 : }
948 :
949 1 : rc = gnutls_x509_crt_set_subject_unique_id(issuer_cert,
950 1 : unique_id.data,
951 1 : unique_id.size);
952 1 : if (rc != GNUTLS_E_SUCCESS) {
953 0 : DBG_ERR("gnutls_x509_crt_set_subject_key_id failed - %s\n",
954 : gnutls_strerror(rc));
955 0 : gnutls_x509_crt_deinit(issuer_cert);
956 0 : return WERR_INVALID_PARAMETER;
957 : }
958 :
959 1 : rc = gnutls_x509_crt_set_issuer_unique_id(issuer_cert,
960 1 : unique_id.data,
961 1 : unique_id.size);
962 1 : if (rc != GNUTLS_E_SUCCESS) {
963 0 : DBG_ERR("gnutls_x509_crt_set_issuer_unique_id failed - %s\n",
964 : gnutls_strerror(rc));
965 0 : gnutls_x509_crt_deinit(issuer_cert);
966 0 : return WERR_INVALID_PARAMETER;
967 : }
968 :
969 1 : rc = gnutls_x509_crt_set_serial(issuer_cert,
970 1 : serial_number.data,
971 1 : serial_number.size);
972 1 : if (rc != GNUTLS_E_SUCCESS) {
973 0 : DBG_ERR("gnutls_x509_crt_set_serial failed - %s\n",
974 : gnutls_strerror(rc));
975 0 : gnutls_x509_crt_deinit(issuer_cert);
976 0 : return WERR_INVALID_PARAMETER;
977 : }
978 :
979 1 : rc = gnutls_x509_crt_privkey_sign(issuer_cert,
980 : issuer_cert,
981 : issuer_privkey,
982 : GNUTLS_DIG_SHA1,
983 : 0);
984 1 : if (rc != GNUTLS_E_SUCCESS) {
985 0 : DBG_ERR("gnutls_x509_crt_privkey_sign failed - %s\n",
986 : gnutls_strerror(rc));
987 0 : return WERR_INVALID_PARAMETER;
988 : }
989 :
990 1 : *certificate = issuer_cert;
991 :
992 1 : return WERR_OK;
993 : }
994 :
995 : /* Return an error when we fail to generate a certificate */
996 1 : static WERROR generate_bkrp_cert(TALLOC_CTX *mem_ctx,
997 : struct dcesrv_call_state *dce_call,
998 : struct ldb_context *ldb_ctx,
999 : const char *dn)
1000 : {
1001 0 : WERROR werr;
1002 1 : gnutls_privkey_t issuer_privkey = NULL;
1003 1 : gnutls_x509_crt_t cert = NULL;
1004 0 : gnutls_datum_t cert_blob;
1005 0 : gnutls_datum_t m, e, d, p, q, u, e1, e2;
1006 0 : DATA_BLOB blob;
1007 0 : DATA_BLOB blobkeypair;
1008 0 : DATA_BLOB *tmp;
1009 1 : bool ok = true;
1010 1 : struct GUID guid = GUID_random();
1011 0 : NTSTATUS status;
1012 0 : char *secret_name;
1013 0 : struct bkrp_exported_RSA_key_pair keypair;
1014 0 : enum ndr_err_code ndr_err;
1015 1 : time_t nb_seconds_validity = 3600 * 24 * 365;
1016 0 : int rc;
1017 :
1018 1 : DEBUG(6, ("Trying to generate a certificate\n"));
1019 1 : werr = create_privkey_rsa(&issuer_privkey);
1020 1 : if (!W_ERROR_IS_OK(werr)) {
1021 0 : return werr;
1022 : }
1023 :
1024 1 : status = GUID_to_ndr_blob(&guid, mem_ctx, &blob);
1025 1 : if (!NT_STATUS_IS_OK(status)) {
1026 0 : gnutls_privkey_deinit(issuer_privkey);
1027 0 : return WERR_INVALID_DATA;
1028 : }
1029 :
1030 1 : werr = self_sign_cert(mem_ctx,
1031 : nb_seconds_validity,
1032 : dn,
1033 : issuer_privkey,
1034 : &cert,
1035 : &blob);
1036 1 : if (!W_ERROR_IS_OK(werr)) {
1037 0 : gnutls_privkey_deinit(issuer_privkey);
1038 0 : return WERR_INVALID_DATA;
1039 : }
1040 :
1041 1 : rc = gnutls_x509_crt_export2(cert, GNUTLS_X509_FMT_DER, &cert_blob);
1042 1 : if (rc != GNUTLS_E_SUCCESS) {
1043 0 : DBG_ERR("gnutls_x509_crt_export2 failed - %s\n",
1044 : gnutls_strerror(rc));
1045 0 : gnutls_privkey_deinit(issuer_privkey);
1046 0 : gnutls_x509_crt_deinit(cert);
1047 0 : return WERR_INVALID_DATA;
1048 : }
1049 :
1050 1 : keypair.cert.length = cert_blob.size;
1051 1 : keypair.cert.data = talloc_memdup(mem_ctx, cert_blob.data, cert_blob.size);
1052 1 : gnutls_x509_crt_deinit(cert);
1053 1 : gnutls_free(cert_blob.data);
1054 1 : if (keypair.cert.data == NULL) {
1055 0 : gnutls_privkey_deinit(issuer_privkey);
1056 0 : return WERR_NOT_ENOUGH_MEMORY;
1057 : }
1058 :
1059 1 : rc = gnutls_privkey_export_rsa_raw(issuer_privkey,
1060 : &m,
1061 : &e,
1062 : &d,
1063 : &p,
1064 : &q,
1065 : &u,
1066 : &e1,
1067 : &e2);
1068 1 : if (rc != GNUTLS_E_SUCCESS) {
1069 0 : gnutls_privkey_deinit(issuer_privkey);
1070 0 : return WERR_INVALID_DATA;
1071 : }
1072 :
1073 : /*
1074 : * Heimdal's bignum are big endian and the
1075 : * structure expect it to be in little endian
1076 : * so we reverse the buffer to make it work
1077 : */
1078 1 : tmp = reverse_and_get_blob(mem_ctx, &e);
1079 1 : if (tmp == NULL) {
1080 0 : ok = false;
1081 : } else {
1082 1 : SMB_ASSERT(tmp->length <= 4);
1083 1 : keypair.public_exponent = *tmp;
1084 : }
1085 :
1086 1 : tmp = reverse_and_get_blob(mem_ctx, &d);
1087 1 : if (tmp == NULL) {
1088 0 : ok = false;
1089 : } else {
1090 1 : keypair.private_exponent = *tmp;
1091 : }
1092 :
1093 1 : tmp = reverse_and_get_blob(mem_ctx, &m);
1094 1 : if (tmp == NULL) {
1095 0 : ok = false;
1096 : } else {
1097 1 : keypair.modulus = *tmp;
1098 : }
1099 :
1100 1 : tmp = reverse_and_get_blob(mem_ctx, &p);
1101 1 : if (tmp == NULL) {
1102 0 : ok = false;
1103 : } else {
1104 1 : keypair.prime1 = *tmp;
1105 : }
1106 :
1107 1 : tmp = reverse_and_get_blob(mem_ctx, &q);
1108 1 : if (tmp == NULL) {
1109 0 : ok = false;
1110 : } else {
1111 1 : keypair.prime2 = *tmp;
1112 : }
1113 :
1114 1 : tmp = reverse_and_get_blob(mem_ctx, &e1);
1115 1 : if (tmp == NULL) {
1116 0 : ok = false;
1117 : } else {
1118 1 : keypair.exponent1 = *tmp;
1119 : }
1120 :
1121 1 : tmp = reverse_and_get_blob(mem_ctx, &e2);
1122 1 : if (tmp == NULL) {
1123 0 : ok = false;
1124 : } else {
1125 1 : keypair.exponent2 = *tmp;
1126 : }
1127 :
1128 1 : tmp = reverse_and_get_blob(mem_ctx, &u);
1129 1 : if (tmp == NULL) {
1130 0 : ok = false;
1131 : } else {
1132 1 : keypair.coefficient = *tmp;
1133 : }
1134 :
1135 : /* One of the keypair allocation was wrong */
1136 1 : if (ok == false) {
1137 0 : gnutls_privkey_deinit(issuer_privkey);
1138 0 : return WERR_INVALID_DATA;
1139 : }
1140 :
1141 1 : keypair.certificate_len = keypair.cert.length;
1142 1 : ndr_err = ndr_push_struct_blob(&blobkeypair,
1143 : mem_ctx,
1144 : &keypair,
1145 : (ndr_push_flags_fn_t)ndr_push_bkrp_exported_RSA_key_pair);
1146 1 : gnutls_privkey_deinit(issuer_privkey);
1147 1 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1148 0 : return WERR_INVALID_DATA;
1149 : }
1150 :
1151 1 : secret_name = talloc_asprintf(mem_ctx, "BCKUPKEY_%s", GUID_string(mem_ctx, &guid));
1152 1 : if (secret_name == NULL) {
1153 0 : return WERR_OUTOFMEMORY;
1154 : }
1155 :
1156 1 : status = set_lsa_secret(mem_ctx, ldb_ctx, secret_name, &blobkeypair);
1157 1 : if (!NT_STATUS_IS_OK(status)) {
1158 0 : DEBUG(2, ("Failed to save the secret %s\n", secret_name));
1159 : }
1160 1 : talloc_free(secret_name);
1161 :
1162 1 : GUID_to_ndr_blob(&guid, mem_ctx, &blob);
1163 1 : status = set_lsa_secret(mem_ctx, ldb_ctx, "BCKUPKEY_PREFERRED", &blob);
1164 1 : if (!NT_STATUS_IS_OK(status)) {
1165 0 : DEBUG(2, ("Failed to save the secret BCKUPKEY_PREFERRED\n"));
1166 : }
1167 :
1168 1 : return WERR_OK;
1169 : }
1170 :
1171 13 : static WERROR bkrp_retrieve_client_wrap_key(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1172 : struct bkrp_BackupKey *r, struct ldb_context *ldb_ctx)
1173 : {
1174 0 : struct GUID guid;
1175 0 : char *guid_string;
1176 0 : DATA_BLOB lsa_secret;
1177 0 : enum ndr_err_code ndr_err;
1178 0 : NTSTATUS status;
1179 :
1180 : /*
1181 : * here we basically need to return our certificate
1182 : * search for lsa secret BCKUPKEY_PREFERRED first
1183 : */
1184 :
1185 13 : status = get_lsa_secret(mem_ctx,
1186 : ldb_ctx,
1187 : "BCKUPKEY_PREFERRED",
1188 : &lsa_secret);
1189 13 : if (NT_STATUS_EQUAL(status, NT_STATUS_RESOURCE_NAME_NOT_FOUND)) {
1190 : /* Ok we can be in this case if there was no certs */
1191 1 : struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1192 1 : char *dn = talloc_asprintf(mem_ctx, "CN=%s",
1193 : lpcfg_realm(lp_ctx));
1194 :
1195 1 : WERROR werr = generate_bkrp_cert(mem_ctx, dce_call, ldb_ctx, dn);
1196 1 : if (!W_ERROR_IS_OK(werr)) {
1197 0 : return WERR_INVALID_PARAMETER;
1198 : }
1199 1 : status = get_lsa_secret(mem_ctx,
1200 : ldb_ctx,
1201 : "BCKUPKEY_PREFERRED",
1202 : &lsa_secret);
1203 :
1204 1 : if (!NT_STATUS_IS_OK(status)) {
1205 : /* Ok we really don't manage to get this certs ...*/
1206 0 : DEBUG(2, ("Unable to locate BCKUPKEY_PREFERRED after cert generation\n"));
1207 0 : return WERR_FILE_NOT_FOUND;
1208 : }
1209 12 : } else if (!NT_STATUS_IS_OK(status)) {
1210 0 : return WERR_INTERNAL_ERROR;
1211 : }
1212 :
1213 13 : if (lsa_secret.length == 0) {
1214 0 : DEBUG(1, ("No secret in BCKUPKEY_PREFERRED, are we an undetected RODC?\n"));
1215 0 : return WERR_INTERNAL_ERROR;
1216 : } else {
1217 0 : char *cert_secret_name;
1218 :
1219 13 : status = GUID_from_ndr_blob(&lsa_secret, &guid);
1220 13 : if (!NT_STATUS_IS_OK(status)) {
1221 0 : return WERR_FILE_NOT_FOUND;
1222 : }
1223 :
1224 13 : guid_string = GUID_string(mem_ctx, &guid);
1225 13 : if (guid_string == NULL) {
1226 : /* We return file not found because the client
1227 : * expect this error
1228 : */
1229 0 : return WERR_FILE_NOT_FOUND;
1230 : }
1231 :
1232 13 : cert_secret_name = talloc_asprintf(mem_ctx,
1233 : "BCKUPKEY_%s",
1234 : guid_string);
1235 13 : status = get_lsa_secret(mem_ctx,
1236 : ldb_ctx,
1237 : cert_secret_name,
1238 : &lsa_secret);
1239 13 : if (!NT_STATUS_IS_OK(status)) {
1240 0 : return WERR_FILE_NOT_FOUND;
1241 : }
1242 :
1243 13 : if (lsa_secret.length != 0) {
1244 0 : struct bkrp_exported_RSA_key_pair keypair;
1245 13 : ndr_err = ndr_pull_struct_blob(&lsa_secret, mem_ctx, &keypair,
1246 : (ndr_pull_flags_fn_t)ndr_pull_bkrp_exported_RSA_key_pair);
1247 13 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1248 0 : return WERR_FILE_NOT_FOUND;
1249 : }
1250 13 : *(r->out.data_out_len) = keypair.cert.length;
1251 13 : *(r->out.data_out) = talloc_memdup(mem_ctx, keypair.cert.data, keypair.cert.length);
1252 13 : W_ERROR_HAVE_NO_MEMORY(*(r->out.data_out));
1253 13 : return WERR_OK;
1254 : } else {
1255 0 : DEBUG(1, ("No or broken secret called %s\n", cert_secret_name));
1256 0 : return WERR_INTERNAL_ERROR;
1257 : }
1258 : }
1259 :
1260 : return WERR_NOT_SUPPORTED;
1261 : }
1262 :
1263 1 : static WERROR generate_bkrp_server_wrap_key(TALLOC_CTX *ctx, struct ldb_context *ldb_ctx)
1264 : {
1265 1 : struct GUID guid = GUID_random();
1266 0 : enum ndr_err_code ndr_err;
1267 0 : DATA_BLOB blob_wrap_key, guid_blob;
1268 0 : struct bkrp_dc_serverwrap_key wrap_key;
1269 0 : NTSTATUS status;
1270 0 : char *secret_name;
1271 1 : TALLOC_CTX *frame = talloc_stackframe();
1272 :
1273 1 : generate_random_buffer(wrap_key.key, sizeof(wrap_key.key));
1274 :
1275 1 : ndr_err = ndr_push_struct_blob(&blob_wrap_key, ctx, &wrap_key, (ndr_push_flags_fn_t)ndr_push_bkrp_dc_serverwrap_key);
1276 1 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1277 0 : TALLOC_FREE(frame);
1278 0 : return WERR_INVALID_DATA;
1279 : }
1280 :
1281 1 : secret_name = talloc_asprintf(frame, "BCKUPKEY_%s", GUID_string(ctx, &guid));
1282 1 : if (secret_name == NULL) {
1283 0 : TALLOC_FREE(frame);
1284 0 : return WERR_NOT_ENOUGH_MEMORY;
1285 : }
1286 :
1287 1 : status = set_lsa_secret(frame, ldb_ctx, secret_name, &blob_wrap_key);
1288 1 : if (!NT_STATUS_IS_OK(status)) {
1289 0 : DEBUG(2, ("Failed to save the secret %s\n", secret_name));
1290 0 : TALLOC_FREE(frame);
1291 0 : return WERR_INTERNAL_ERROR;
1292 : }
1293 :
1294 1 : status = GUID_to_ndr_blob(&guid, frame, &guid_blob);
1295 1 : if (!NT_STATUS_IS_OK(status)) {
1296 0 : DEBUG(2, ("Failed to save the secret %s\n", secret_name));
1297 0 : TALLOC_FREE(frame);
1298 : }
1299 :
1300 1 : status = set_lsa_secret(frame, ldb_ctx, "BCKUPKEY_P", &guid_blob);
1301 1 : if (!NT_STATUS_IS_OK(status)) {
1302 0 : DEBUG(2, ("Failed to save the secret %s\n", secret_name));
1303 0 : TALLOC_FREE(frame);
1304 0 : return WERR_INTERNAL_ERROR;
1305 : }
1306 :
1307 1 : TALLOC_FREE(frame);
1308 :
1309 1 : return WERR_OK;
1310 : }
1311 :
1312 : /*
1313 : * Find the specified decryption keys from the LSA secrets store as
1314 : * G$BCKUPKEY_keyGuidString.
1315 : */
1316 :
1317 31 : static WERROR bkrp_do_retrieve_server_wrap_key(TALLOC_CTX *mem_ctx, struct ldb_context *ldb_ctx,
1318 : struct bkrp_dc_serverwrap_key *server_key,
1319 : struct GUID *guid)
1320 : {
1321 0 : NTSTATUS status;
1322 0 : DATA_BLOB lsa_secret;
1323 0 : char *secret_name;
1324 0 : char *guid_string;
1325 0 : enum ndr_err_code ndr_err;
1326 :
1327 31 : guid_string = GUID_string(mem_ctx, guid);
1328 31 : if (guid_string == NULL) {
1329 : /* We return file not found because the client
1330 : * expect this error
1331 : */
1332 0 : return WERR_FILE_NOT_FOUND;
1333 : }
1334 :
1335 31 : secret_name = talloc_asprintf(mem_ctx, "BCKUPKEY_%s", guid_string);
1336 31 : if (secret_name == NULL) {
1337 0 : return WERR_NOT_ENOUGH_MEMORY;
1338 : }
1339 :
1340 31 : status = get_lsa_secret(mem_ctx, ldb_ctx, secret_name, &lsa_secret);
1341 31 : if (!NT_STATUS_IS_OK(status)) {
1342 2 : DEBUG(10, ("Error while fetching secret %s\n", secret_name));
1343 2 : return WERR_INVALID_DATA;
1344 : }
1345 29 : if (lsa_secret.length == 0) {
1346 : /* RODC case, we do not have secrets locally */
1347 0 : DEBUG(1, ("Unable to fetch value for secret %s, are we an undetected RODC?\n",
1348 : secret_name));
1349 0 : return WERR_INTERNAL_ERROR;
1350 : }
1351 29 : ndr_err = ndr_pull_struct_blob(&lsa_secret, mem_ctx, server_key,
1352 : (ndr_pull_flags_fn_t)ndr_pull_bkrp_dc_serverwrap_key);
1353 29 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1354 0 : DEBUG(2, ("Unable to parse the ndr encoded server wrap key %s\n", secret_name));
1355 0 : return WERR_INVALID_DATA;
1356 : }
1357 :
1358 29 : return WERR_OK;
1359 : }
1360 :
1361 : /*
1362 : * Find the current, preferred ServerWrap Key by looking at
1363 : * G$BCKUPKEY_P in the LSA secrets store.
1364 : *
1365 : * Then find the current decryption keys from the LSA secrets store as
1366 : * G$BCKUPKEY_keyGuidString.
1367 : */
1368 :
1369 14 : static WERROR bkrp_do_retrieve_default_server_wrap_key(TALLOC_CTX *mem_ctx,
1370 : struct ldb_context *ldb_ctx,
1371 : struct bkrp_dc_serverwrap_key *server_key,
1372 : struct GUID *returned_guid)
1373 : {
1374 0 : NTSTATUS status;
1375 0 : DATA_BLOB guid_binary;
1376 :
1377 14 : status = get_lsa_secret(mem_ctx, ldb_ctx, "BCKUPKEY_P", &guid_binary);
1378 14 : if (!NT_STATUS_IS_OK(status)) {
1379 1 : DEBUG(10, ("Error while fetching secret BCKUPKEY_P to find current GUID\n"));
1380 1 : return WERR_FILE_NOT_FOUND;
1381 13 : } else if (guid_binary.length == 0) {
1382 : /* RODC case, we do not have secrets locally */
1383 0 : DEBUG(1, ("Unable to fetch value for secret BCKUPKEY_P, are we an undetected RODC?\n"));
1384 0 : return WERR_INTERNAL_ERROR;
1385 : }
1386 :
1387 13 : status = GUID_from_ndr_blob(&guid_binary, returned_guid);
1388 13 : if (!NT_STATUS_IS_OK(status)) {
1389 0 : return WERR_FILE_NOT_FOUND;
1390 : }
1391 :
1392 13 : return bkrp_do_retrieve_server_wrap_key(mem_ctx, ldb_ctx,
1393 : server_key, returned_guid);
1394 : }
1395 :
1396 30 : static WERROR bkrp_server_wrap_decrypt_data(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1397 : struct bkrp_BackupKey *r ,struct ldb_context *ldb_ctx)
1398 : {
1399 0 : struct auth_session_info *session_info =
1400 30 : dcesrv_call_session_info(dce_call);
1401 0 : WERROR werr;
1402 0 : struct bkrp_server_side_wrapped decrypt_request;
1403 0 : DATA_BLOB sid_blob, encrypted_blob;
1404 0 : DATA_BLOB blob;
1405 0 : enum ndr_err_code ndr_err;
1406 0 : struct bkrp_dc_serverwrap_key server_key;
1407 0 : struct bkrp_rc4encryptedpayload rc4payload;
1408 0 : struct dom_sid *caller_sid;
1409 0 : uint8_t symkey[20]; /* SHA-1 hash len */
1410 0 : uint8_t mackey[20]; /* SHA-1 hash len */
1411 0 : uint8_t mac[20]; /* SHA-1 hash len */
1412 0 : gnutls_hmac_hd_t hmac_hnd;
1413 0 : gnutls_cipher_hd_t cipher_hnd;
1414 0 : gnutls_datum_t cipher_key;
1415 0 : int rc;
1416 :
1417 30 : blob.data = r->in.data_in;
1418 30 : blob.length = r->in.data_in_len;
1419 :
1420 30 : if (r->in.data_in_len == 0 || r->in.data_in == NULL) {
1421 1 : return WERR_INVALID_PARAMETER;
1422 : }
1423 :
1424 29 : ndr_err = ndr_pull_struct_blob_all(&blob, mem_ctx, &decrypt_request,
1425 : (ndr_pull_flags_fn_t)ndr_pull_bkrp_server_side_wrapped);
1426 29 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1427 10 : return WERR_INVALID_PARAMETER;
1428 : }
1429 :
1430 19 : if (decrypt_request.magic != BACKUPKEY_SERVER_WRAP_VERSION) {
1431 1 : return WERR_INVALID_PARAMETER;
1432 : }
1433 :
1434 18 : werr = bkrp_do_retrieve_server_wrap_key(mem_ctx, ldb_ctx, &server_key,
1435 : &decrypt_request.guid);
1436 18 : if (!W_ERROR_IS_OK(werr)) {
1437 2 : return werr;
1438 : }
1439 :
1440 16 : dump_data_pw("server_key: \n", server_key.key, sizeof(server_key.key));
1441 :
1442 16 : dump_data_pw("r2: \n", decrypt_request.r2, sizeof(decrypt_request.r2));
1443 :
1444 : /*
1445 : * This is *not* the leading 64 bytes, as indicated in MS-BKRP 3.1.4.1.1
1446 : * BACKUPKEY_BACKUP_GUID, it really is the whole key
1447 : */
1448 :
1449 16 : rc = gnutls_hmac_init(&hmac_hnd,
1450 : GNUTLS_MAC_SHA1,
1451 : server_key.key,
1452 : sizeof(server_key.key));
1453 16 : if (rc != GNUTLS_E_SUCCESS) {
1454 0 : return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
1455 : }
1456 :
1457 16 : rc = gnutls_hmac(hmac_hnd,
1458 : decrypt_request.r2,
1459 : sizeof(decrypt_request.r2));
1460 :
1461 16 : if (rc != GNUTLS_E_SUCCESS) {
1462 0 : return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
1463 : }
1464 :
1465 16 : gnutls_hmac_output(hmac_hnd, symkey);
1466 16 : dump_data_pw("symkey: \n", symkey, sizeof(symkey));
1467 :
1468 : /* rc4 decrypt sid and secret using sym key */
1469 16 : cipher_key.data = symkey;
1470 16 : cipher_key.size = sizeof(symkey);
1471 :
1472 16 : encrypted_blob = data_blob_const(decrypt_request.rc4encryptedpayload,
1473 16 : decrypt_request.ciphertext_length);
1474 :
1475 16 : rc = gnutls_cipher_init(&cipher_hnd,
1476 : GNUTLS_CIPHER_ARCFOUR_128,
1477 : &cipher_key,
1478 : NULL);
1479 16 : if (rc != GNUTLS_E_SUCCESS) {
1480 0 : return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
1481 : }
1482 16 : rc = gnutls_cipher_encrypt2(cipher_hnd,
1483 16 : encrypted_blob.data,
1484 : encrypted_blob.length,
1485 16 : encrypted_blob.data,
1486 : encrypted_blob.length);
1487 16 : gnutls_cipher_deinit(cipher_hnd);
1488 16 : if (rc != GNUTLS_E_SUCCESS) {
1489 0 : return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
1490 : }
1491 :
1492 16 : ndr_err = ndr_pull_struct_blob_all(&encrypted_blob, mem_ctx, &rc4payload,
1493 : (ndr_pull_flags_fn_t)ndr_pull_bkrp_rc4encryptedpayload);
1494 16 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1495 2 : return WERR_INVALID_PARAMETER;
1496 : }
1497 :
1498 14 : if (decrypt_request.payload_length != rc4payload.secret_data.length) {
1499 8 : return WERR_INVALID_PARAMETER;
1500 : }
1501 :
1502 6 : dump_data_pw("r3: \n", rc4payload.r3, sizeof(rc4payload.r3));
1503 :
1504 : /*
1505 : * This is *not* the leading 64 bytes, as indicated in MS-BKRP 3.1.4.1.1
1506 : * BACKUPKEY_BACKUP_GUID, it really is the whole key
1507 : */
1508 6 : rc = gnutls_hmac(hmac_hnd,
1509 : rc4payload.r3,
1510 : sizeof(rc4payload.r3));
1511 6 : if (rc != GNUTLS_E_SUCCESS) {
1512 0 : return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
1513 : }
1514 :
1515 6 : gnutls_hmac_deinit(hmac_hnd, mackey);
1516 :
1517 6 : dump_data_pw("mackey: \n", mackey, sizeof(mackey));
1518 :
1519 6 : ndr_err = ndr_push_struct_blob(&sid_blob, mem_ctx, &rc4payload.sid,
1520 : (ndr_push_flags_fn_t)ndr_push_dom_sid);
1521 6 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1522 0 : return WERR_INTERNAL_ERROR;
1523 : }
1524 :
1525 6 : rc = gnutls_hmac_init(&hmac_hnd,
1526 : GNUTLS_MAC_SHA1,
1527 : mackey,
1528 : sizeof(mackey));
1529 6 : if (rc != GNUTLS_E_SUCCESS) {
1530 0 : return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
1531 : }
1532 :
1533 : /* SID field */
1534 6 : rc = gnutls_hmac(hmac_hnd,
1535 6 : sid_blob.data,
1536 : sid_blob.length);
1537 6 : if (rc != GNUTLS_E_SUCCESS) {
1538 0 : return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
1539 : }
1540 :
1541 : /* Secret field */
1542 6 : rc = gnutls_hmac(hmac_hnd,
1543 6 : rc4payload.secret_data.data,
1544 : rc4payload.secret_data.length);
1545 6 : if (rc != GNUTLS_E_SUCCESS) {
1546 0 : return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
1547 : }
1548 :
1549 6 : gnutls_hmac_deinit(hmac_hnd, mac);
1550 6 : dump_data_pw("mac: \n", mac, sizeof(mac));
1551 6 : dump_data_pw("rc4payload.mac: \n", rc4payload.mac, sizeof(rc4payload.mac));
1552 :
1553 6 : if (!mem_equal_const_time(mac, rc4payload.mac, sizeof(mac))) {
1554 0 : return WERR_INVALID_ACCESS;
1555 : }
1556 :
1557 6 : caller_sid = &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
1558 :
1559 6 : if (!dom_sid_equal(&rc4payload.sid, caller_sid)) {
1560 2 : return WERR_INVALID_ACCESS;
1561 : }
1562 :
1563 4 : *(r->out.data_out) = rc4payload.secret_data.data;
1564 4 : *(r->out.data_out_len) = rc4payload.secret_data.length;
1565 :
1566 4 : return WERR_OK;
1567 : }
1568 :
1569 : /*
1570 : * For BACKUPKEY_RESTORE_GUID we need to check the first 4 bytes to
1571 : * determine what type of restore is wanted.
1572 : *
1573 : * See MS-BKRP 3.1.4.1.4 BACKUPKEY_RESTORE_GUID point 1.
1574 : */
1575 :
1576 27 : static WERROR bkrp_generic_decrypt_data(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1577 : struct bkrp_BackupKey *r, struct ldb_context *ldb_ctx)
1578 : {
1579 27 : if (r->in.data_in_len < 4 || r->in.data_in == NULL) {
1580 3 : return WERR_INVALID_PARAMETER;
1581 : }
1582 :
1583 24 : if (IVAL(r->in.data_in, 0) == BACKUPKEY_SERVER_WRAP_VERSION) {
1584 14 : return bkrp_server_wrap_decrypt_data(dce_call, mem_ctx, r, ldb_ctx);
1585 : }
1586 :
1587 10 : return bkrp_client_wrap_decrypt_data(dce_call, mem_ctx, r, ldb_ctx);
1588 : }
1589 :
1590 : /*
1591 : * We have some data, such as saved website or IMAP passwords that the
1592 : * client would like to put into the profile on-disk. This needs to
1593 : * be encrypted. This version gives the server the data over the
1594 : * network (protected only by the negotiated transport encryption),
1595 : * and asks that it be encrypted and returned for long-term storage.
1596 : *
1597 : * The data is NOT stored in the LSA, but a key to encrypt the data
1598 : * will be stored. There is only one active encryption key per domain,
1599 : * it is pointed at with G$BCKUPKEY_P in the LSA secrets store.
1600 : *
1601 : * The potentially multiple valid decryption keys (and the encryption
1602 : * key) are in turn stored in the LSA secrets store as
1603 : * G$BCKUPKEY_keyGuidString.
1604 : *
1605 : */
1606 :
1607 13 : static WERROR bkrp_server_wrap_encrypt_data(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1608 : struct bkrp_BackupKey *r ,struct ldb_context *ldb_ctx)
1609 : {
1610 0 : struct auth_session_info *session_info =
1611 13 : dcesrv_call_session_info(dce_call);
1612 0 : DATA_BLOB sid_blob, encrypted_blob, server_wrapped_blob;
1613 0 : WERROR werr;
1614 0 : struct dom_sid *caller_sid;
1615 0 : uint8_t symkey[20]; /* SHA-1 hash len */
1616 0 : uint8_t mackey[20]; /* SHA-1 hash len */
1617 0 : struct bkrp_rc4encryptedpayload rc4payload;
1618 0 : gnutls_hmac_hd_t hmac_hnd;
1619 0 : struct bkrp_dc_serverwrap_key server_key;
1620 0 : enum ndr_err_code ndr_err;
1621 0 : struct bkrp_server_side_wrapped server_side_wrapped;
1622 0 : struct GUID guid;
1623 0 : gnutls_cipher_hd_t cipher_hnd;
1624 0 : gnutls_datum_t cipher_key;
1625 0 : int rc;
1626 :
1627 13 : if (r->in.data_in_len == 0 || r->in.data_in == NULL) {
1628 0 : return WERR_INVALID_PARAMETER;
1629 : }
1630 :
1631 13 : werr = bkrp_do_retrieve_default_server_wrap_key(mem_ctx,
1632 : ldb_ctx, &server_key,
1633 : &guid);
1634 :
1635 13 : if (!W_ERROR_IS_OK(werr)) {
1636 1 : if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
1637 : /* Generate the server wrap key since one wasn't found */
1638 1 : werr = generate_bkrp_server_wrap_key(mem_ctx,
1639 : ldb_ctx);
1640 1 : if (!W_ERROR_IS_OK(werr)) {
1641 0 : return WERR_INVALID_PARAMETER;
1642 : }
1643 1 : werr = bkrp_do_retrieve_default_server_wrap_key(mem_ctx,
1644 : ldb_ctx,
1645 : &server_key,
1646 : &guid);
1647 :
1648 1 : if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
1649 : /* Ok we really don't manage to get this secret ...*/
1650 0 : return WERR_FILE_NOT_FOUND;
1651 : }
1652 : } else {
1653 : /* In theory we should NEVER reach this point as it
1654 : should only appear in a rodc server */
1655 : /* we do not have the real secret attribute */
1656 0 : return WERR_INVALID_PARAMETER;
1657 : }
1658 : }
1659 :
1660 13 : caller_sid = &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
1661 :
1662 13 : dump_data_pw("server_key: \n", server_key.key, sizeof(server_key.key));
1663 :
1664 : /*
1665 : * This is the key derivation step, so that the HMAC and RC4
1666 : * operations over the user-supplied data are not able to
1667 : * disclose the master key. By using random data, the symkey
1668 : * and mackey values are unique for this operation, and
1669 : * discovering these (by reversing the RC4 over the
1670 : * attacker-controlled data) does not return something able to
1671 : * be used to decrypt the encrypted data of other users
1672 : */
1673 13 : generate_random_buffer(server_side_wrapped.r2, sizeof(server_side_wrapped.r2));
1674 :
1675 13 : dump_data_pw("r2: \n", server_side_wrapped.r2, sizeof(server_side_wrapped.r2));
1676 :
1677 13 : generate_random_buffer(rc4payload.r3, sizeof(rc4payload.r3));
1678 :
1679 13 : dump_data_pw("r3: \n", rc4payload.r3, sizeof(rc4payload.r3));
1680 :
1681 :
1682 : /*
1683 : * This is *not* the leading 64 bytes, as indicated in MS-BKRP 3.1.4.1.1
1684 : * BACKUPKEY_BACKUP_GUID, it really is the whole key
1685 : */
1686 13 : rc = gnutls_hmac_init(&hmac_hnd,
1687 : GNUTLS_MAC_SHA1,
1688 : server_key.key,
1689 : sizeof(server_key.key));
1690 13 : if (rc != GNUTLS_E_SUCCESS) {
1691 0 : return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
1692 : }
1693 :
1694 13 : rc = gnutls_hmac(hmac_hnd,
1695 : server_side_wrapped.r2,
1696 : sizeof(server_side_wrapped.r2));
1697 13 : if (rc != GNUTLS_E_SUCCESS) {
1698 0 : return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
1699 : }
1700 13 : gnutls_hmac_output(hmac_hnd, symkey);
1701 13 : dump_data_pw("symkey: \n", symkey, sizeof(symkey));
1702 :
1703 : /*
1704 : * This is *not* the leading 64 bytes, as indicated in MS-BKRP 3.1.4.1.1
1705 : * BACKUPKEY_BACKUP_GUID, it really is the whole key
1706 : */
1707 13 : rc = gnutls_hmac(hmac_hnd,
1708 : rc4payload.r3,
1709 : sizeof(rc4payload.r3));
1710 13 : if (rc != GNUTLS_E_SUCCESS) {
1711 0 : return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
1712 : }
1713 13 : gnutls_hmac_deinit(hmac_hnd, mackey);
1714 13 : dump_data_pw("mackey: \n", mackey, sizeof(mackey));
1715 :
1716 13 : ndr_err = ndr_push_struct_blob(&sid_blob, mem_ctx, caller_sid,
1717 : (ndr_push_flags_fn_t)ndr_push_dom_sid);
1718 13 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1719 0 : return WERR_INTERNAL_ERROR;
1720 : }
1721 :
1722 13 : rc4payload.secret_data.data = r->in.data_in;
1723 13 : rc4payload.secret_data.length = r->in.data_in_len;
1724 :
1725 13 : rc = gnutls_hmac_init(&hmac_hnd,
1726 : GNUTLS_MAC_SHA1,
1727 : mackey,
1728 : sizeof(mackey));
1729 13 : if (rc != GNUTLS_E_SUCCESS) {
1730 0 : return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
1731 : }
1732 :
1733 : /* SID field */
1734 13 : rc = gnutls_hmac(hmac_hnd,
1735 13 : sid_blob.data,
1736 : sid_blob.length);
1737 13 : if (rc != GNUTLS_E_SUCCESS) {
1738 0 : return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
1739 : }
1740 :
1741 : /* Secret field */
1742 13 : rc = gnutls_hmac(hmac_hnd,
1743 13 : rc4payload.secret_data.data,
1744 : rc4payload.secret_data.length);
1745 13 : if (rc != GNUTLS_E_SUCCESS) {
1746 0 : return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
1747 : }
1748 :
1749 13 : gnutls_hmac_deinit(hmac_hnd, rc4payload.mac);
1750 13 : dump_data_pw("rc4payload.mac: \n", rc4payload.mac, sizeof(rc4payload.mac));
1751 :
1752 13 : rc4payload.sid = *caller_sid;
1753 :
1754 13 : ndr_err = ndr_push_struct_blob(&encrypted_blob, mem_ctx, &rc4payload,
1755 : (ndr_push_flags_fn_t)ndr_push_bkrp_rc4encryptedpayload);
1756 13 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1757 0 : return WERR_INTERNAL_ERROR;
1758 : }
1759 :
1760 : /* rc4 encrypt sid and secret using sym key */
1761 13 : cipher_key.data = symkey;
1762 13 : cipher_key.size = sizeof(symkey);
1763 :
1764 13 : rc = gnutls_cipher_init(&cipher_hnd,
1765 : GNUTLS_CIPHER_ARCFOUR_128,
1766 : &cipher_key,
1767 : NULL);
1768 13 : if (rc != GNUTLS_E_SUCCESS) {
1769 0 : return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
1770 : }
1771 13 : rc = gnutls_cipher_encrypt2(cipher_hnd,
1772 13 : encrypted_blob.data,
1773 : encrypted_blob.length,
1774 13 : encrypted_blob.data,
1775 : encrypted_blob.length);
1776 13 : gnutls_cipher_deinit(cipher_hnd);
1777 13 : if (rc != GNUTLS_E_SUCCESS) {
1778 0 : return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
1779 : }
1780 :
1781 : /* create server wrap structure */
1782 :
1783 13 : server_side_wrapped.payload_length = rc4payload.secret_data.length;
1784 13 : server_side_wrapped.ciphertext_length = encrypted_blob.length;
1785 13 : server_side_wrapped.guid = guid;
1786 13 : server_side_wrapped.rc4encryptedpayload = encrypted_blob.data;
1787 :
1788 13 : ndr_err = ndr_push_struct_blob(&server_wrapped_blob, mem_ctx, &server_side_wrapped,
1789 : (ndr_push_flags_fn_t)ndr_push_bkrp_server_side_wrapped);
1790 13 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1791 0 : return WERR_INTERNAL_ERROR;
1792 : }
1793 :
1794 13 : *(r->out.data_out) = server_wrapped_blob.data;
1795 13 : *(r->out.data_out_len) = server_wrapped_blob.length;
1796 :
1797 13 : return WERR_OK;
1798 : }
1799 :
1800 69 : static WERROR dcesrv_bkrp_BackupKey(struct dcesrv_call_state *dce_call,
1801 : TALLOC_CTX *mem_ctx, struct bkrp_BackupKey *r)
1802 : {
1803 69 : WERROR error = WERR_INVALID_PARAMETER;
1804 0 : struct ldb_context *ldb_ctx;
1805 0 : bool is_rodc;
1806 69 : const char *addr = "unknown";
1807 : /* At which level we start to add more debug of what is done in the protocol */
1808 69 : const int debuglevel = 4;
1809 :
1810 69 : if (DEBUGLVL(debuglevel)) {
1811 0 : const struct tsocket_address *remote_address;
1812 0 : remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1813 0 : if (tsocket_address_is_inet(remote_address, "ip")) {
1814 0 : addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1815 0 : W_ERROR_HAVE_NO_MEMORY(addr);
1816 : }
1817 : }
1818 :
1819 69 : if (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx) != ROLE_ACTIVE_DIRECTORY_DC) {
1820 0 : return WERR_NOT_SUPPORTED;
1821 : }
1822 :
1823 : /*
1824 : * Save the current remote session details so they can used by the
1825 : * audit logging module. This allows the audit logging to report the
1826 : * remote users details, rather than the system users details.
1827 : */
1828 69 : ldb_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
1829 :
1830 69 : if (samdb_rodc(ldb_ctx, &is_rodc) != LDB_SUCCESS) {
1831 0 : talloc_unlink(mem_ctx, ldb_ctx);
1832 0 : return WERR_INVALID_PARAMETER;
1833 : }
1834 :
1835 69 : if (!is_rodc) {
1836 69 : if(strncasecmp(GUID_string(mem_ctx, r->in.guidActionAgent),
1837 : BACKUPKEY_RESTORE_GUID, strlen(BACKUPKEY_RESTORE_GUID)) == 0) {
1838 27 : DEBUG(debuglevel, ("Client %s requested to decrypt a wrapped secret\n", addr));
1839 27 : error = bkrp_generic_decrypt_data(dce_call, mem_ctx, r, ldb_ctx);
1840 : }
1841 :
1842 69 : if (strncasecmp(GUID_string(mem_ctx, r->in.guidActionAgent),
1843 : BACKUPKEY_RETRIEVE_BACKUP_KEY_GUID, strlen(BACKUPKEY_RETRIEVE_BACKUP_KEY_GUID)) == 0) {
1844 13 : DEBUG(debuglevel, ("Client %s requested certificate for client wrapped secret\n", addr));
1845 13 : error = bkrp_retrieve_client_wrap_key(dce_call, mem_ctx, r, ldb_ctx);
1846 : }
1847 :
1848 69 : if (strncasecmp(GUID_string(mem_ctx, r->in.guidActionAgent),
1849 : BACKUPKEY_RESTORE_GUID_WIN2K, strlen(BACKUPKEY_RESTORE_GUID_WIN2K)) == 0) {
1850 16 : DEBUG(debuglevel, ("Client %s requested to decrypt a server side wrapped secret\n", addr));
1851 16 : error = bkrp_server_wrap_decrypt_data(dce_call, mem_ctx, r, ldb_ctx);
1852 : }
1853 :
1854 69 : if (strncasecmp(GUID_string(mem_ctx, r->in.guidActionAgent),
1855 : BACKUPKEY_BACKUP_GUID, strlen(BACKUPKEY_BACKUP_GUID)) == 0) {
1856 13 : DEBUG(debuglevel, ("Client %s requested a server wrapped secret\n", addr));
1857 13 : error = bkrp_server_wrap_encrypt_data(dce_call, mem_ctx, r, ldb_ctx);
1858 : }
1859 : }
1860 : /*else: I am a RODC so I don't handle backup key protocol */
1861 :
1862 69 : talloc_unlink(mem_ctx, ldb_ctx);
1863 69 : return error;
1864 : }
1865 :
1866 : /* include the generated boilerplate */
1867 : #include "librpc/gen_ndr/ndr_backupkey_s.c"
|