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