s4 torture: add new rpc torture tests for backup key remote protocol
[samba.git] / source4 / torture / rpc / backupkey.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for backupkey remote protocol rpc operations
4
5    Copyright (C) Matthieu Patou 2010-2011
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "../libcli/security/security.h"
23 #include "librpc/gen_ndr/ndr_backupkey_c.h"
24 #include "librpc/gen_ndr/ndr_backupkey.h"
25 #include "librpc/gen_ndr/ndr_lsa_c.h"
26 #include "torture/rpc/torture_rpc.h"
27 #include "lib/cmdline/popt_common.h"
28 #include "heimdal/lib/hx509/hx_locl.h"
29
30 /* Our very special and valued secret */
31 /* No need to put const as we cast the array in uint8_t
32  * we will get a warning about the discared const
33  */
34 static const char secret[] = "tata yoyo mais qu'est ce qu'il y a sous ton grand chapeau ?";
35
36 /* Get the SID from a user */
37 static const struct dom_sid *get_user_sid(struct torture_context *tctx,
38                                         struct dcerpc_pipe *p,
39                                         TALLOC_CTX *mem_ctx,
40                                         const char *user)
41 {
42         struct lsa_ObjectAttribute attr;
43         struct lsa_QosInfo qos;
44         struct lsa_OpenPolicy2 r;
45         struct lsa_Close c;
46         NTSTATUS status;
47         struct policy_handle handle;
48         struct lsa_LookupNames l;
49         struct lsa_TransSidArray sids;
50         struct lsa_RefDomainList *domains = NULL;
51         struct lsa_String lsa_name;
52         uint32_t count = 0;
53         struct dom_sid *result;
54         TALLOC_CTX *tmp_ctx;
55         struct dcerpc_pipe *p2;
56         struct dcerpc_binding_handle *b;
57
58         const char *domain = cli_credentials_get_domain(cmdline_credentials);
59
60         torture_assert_ntstatus_ok(tctx,
61                                 torture_rpc_connection(tctx, &p2, &ndr_table_lsarpc),
62                                 "could not open lsarpc pipe");
63         b = p2->binding_handle;
64
65         if (!(tmp_ctx = talloc_new(mem_ctx))) {
66                 return NULL;
67         }
68         qos.len = 0;
69         qos.impersonation_level = 2;
70         qos.context_mode = 1;
71         qos.effective_only = 0;
72
73         attr.len = 0;
74         attr.root_dir = NULL;
75         attr.object_name = NULL;
76         attr.attributes = 0;
77         attr.sec_desc = NULL;
78         attr.sec_qos = &qos;
79
80         r.in.system_name = "\\";
81         r.in.attr = &attr;
82         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
83         r.out.handle = &handle;
84
85         status = dcerpc_lsa_OpenPolicy2_r(b, tmp_ctx, &r);
86         if (!NT_STATUS_IS_OK(status)) {
87                 torture_comment(tctx,
88                                 "OpenPolicy2 failed - %s\n",
89                                 nt_errstr(status));
90                 talloc_free(tmp_ctx);
91                 return NULL;
92         }
93         if (!NT_STATUS_IS_OK(r.out.result)) {
94                 torture_comment(tctx,
95                                 "OpenPolicy2_ failed - %s\n",
96                                 nt_errstr(r.out.result));
97                 talloc_free(tmp_ctx);
98                 return NULL;
99         }
100
101         sids.count = 0;
102         sids.sids = NULL;
103
104         lsa_name.string = talloc_asprintf(tmp_ctx, "%s\\%s", domain, user);
105
106         l.in.handle = &handle;
107         l.in.num_names = 1;
108         l.in.names = &lsa_name;
109         l.in.sids = &sids;
110         l.in.level = 1;
111         l.in.count = &count;
112         l.out.count = &count;
113         l.out.sids = &sids;
114         l.out.domains = &domains;
115
116         status = dcerpc_lsa_LookupNames_r(b, tmp_ctx, &l);
117         if (!NT_STATUS_IS_OK(status)) {
118                 torture_comment(tctx,
119                                 "LookupNames of %s failed - %s\n",
120                                 lsa_name.string,
121                                 nt_errstr(status));
122                 talloc_free(tmp_ctx);
123                 return NULL;
124         }
125
126         if (domains->count == 0) {
127                 return NULL;
128         }
129
130         result = dom_sid_add_rid(mem_ctx,
131                                  domains->domains[0].sid,
132                                  l.out.sids->sids[0].rid);
133         c.in.handle = &handle;
134         c.out.handle = &handle;
135
136         status = dcerpc_lsa_Close_r(b, tmp_ctx, &c);
137
138         if (!NT_STATUS_IS_OK(status)) {
139                 torture_comment(tctx,
140                                 "dcerpc_lsa_Close failed - %s\n",
141                                 nt_errstr(status));
142                 talloc_free(tmp_ctx);
143                 return NULL;
144         }
145
146         if (!NT_STATUS_IS_OK(c.out.result)) {
147                 torture_comment(tctx,
148                                 "dcerpc_lsa_Close failed - %s\n",
149                                 nt_errstr(c.out.result));
150                 talloc_free(tmp_ctx);
151                 return NULL;
152         }
153
154         talloc_free(tmp_ctx);
155         talloc_free(p2);
156
157         torture_comment(tctx, "Get_user_sid finished\n");
158         return result;
159 }
160
161 /*
162  * Create a bkrp_encrypted_secret_vX structure
163  * the version depends on the version parameter
164  * the structure is returned as a blob.
165  * The broken flag is to indicate if we want
166  * to create a non conform to specification structre
167  */
168 static DATA_BLOB *create_unencryptedsecret(TALLOC_CTX *mem_ctx,
169                                            bool broken,
170                                            int version)
171 {
172         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
173         DATA_BLOB *blob = talloc_zero(mem_ctx, DATA_BLOB);
174         enum ndr_err_code ndr_err;
175
176         if (version == 2) {
177                 struct bkrp_encrypted_secret_v2 unenc_sec;
178
179                 ZERO_STRUCT(unenc_sec);
180                 unenc_sec.secret_len = sizeof(secret);
181                 unenc_sec.secret = discard_const_p(uint8_t, secret);
182                 generate_random_buffer(unenc_sec.payload_key,
183                                        sizeof(unenc_sec.payload_key));
184
185                 ndr_err = ndr_push_struct_blob(blob, blob, &unenc_sec,
186                                 (ndr_push_flags_fn_t)ndr_push_bkrp_encrypted_secret_v2);
187                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
188                         return NULL;
189                 }
190
191                 if (broken) {
192                         /* The magic value is correctly set by the NDR push
193                          * but we want to test the behavior of the server
194                          * if a differrent value is provided
195                          */
196                         ((uint8_t*)blob->data)[4] = 79; /* A great year !!! */
197                 }
198         }
199
200         if (version == 3) {
201                 struct bkrp_encrypted_secret_v3 unenc_sec;
202
203                 ZERO_STRUCT(unenc_sec);
204                 unenc_sec.secret_len = sizeof(secret);
205                 unenc_sec.secret = discard_const_p(uint8_t, secret);
206                 generate_random_buffer(unenc_sec.payload_key,
207                                        sizeof(unenc_sec.payload_key));
208
209                 ndr_err = ndr_push_struct_blob(blob, blob, &unenc_sec,
210                                         (ndr_push_flags_fn_t)ndr_push_bkrp_encrypted_secret_v3);
211                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
212                         return NULL;
213                 }
214
215                 if (broken) {
216                         /*
217                          * The magic value is correctly set by the NDR push
218                          * but we want to test the behavior of the server
219                          * if a differrent value is provided
220                          */
221                         ((uint8_t*)blob->data)[4] = 79; /* A great year !!! */
222                 }
223         }
224         talloc_free(tmp_ctx);
225         return blob;
226 }
227
228 /*
229  * Create an access check structure, the format depends on the version parameter.
230  * If broken is specified then we create a stucture that isn't conform to the 
231  * specification.
232  *
233  * If the structure can't be created then NULL is returned.
234  */
235 static DATA_BLOB *create_access_check(struct torture_context *tctx,
236                                       struct dcerpc_pipe *p,
237                                       TALLOC_CTX *mem_ctx,
238                                       const char *user,
239                                       bool broken,
240                                       uint32_t version)
241 {
242         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
243         DATA_BLOB *blob = talloc_zero(mem_ctx, DATA_BLOB);
244         enum ndr_err_code ndr_err;
245         const struct dom_sid *sid = get_user_sid(tctx, p, tmp_ctx, user);
246
247         if (sid == NULL) {
248                 return NULL;
249         }
250
251         if (version == 2) {
252                 struct bkrp_access_check_v2 access_struct;
253                 struct sha sctx;
254                 uint8_t nonce[32];
255
256                 ZERO_STRUCT(access_struct);
257                 generate_random_buffer(nonce, sizeof(nonce));
258                 access_struct.nonce_len = sizeof(nonce);
259                 access_struct.nonce = nonce;
260                 access_struct.sid = *sid;
261
262                 ndr_err = ndr_push_struct_blob(blob, blob, &access_struct,
263                                 (ndr_push_flags_fn_t)ndr_push_bkrp_access_check_v2);
264                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
265                         return NULL;
266                 }
267
268                 /*
269                  * We pushed the whole structure including a null hash
270                  * but the hash need to be calculated only up to the hash field
271                  * so we reduce the size of what has to be calculated
272                  */
273
274                 SHA1_Init(&sctx);
275                 SHA1_Update(&sctx, blob->data,
276                             blob->length - sizeof(access_struct.hash));
277                 SHA1_Final(blob->data + blob->length - sizeof(access_struct.hash),
278                            &sctx);
279
280                 /* Altering the SHA */
281                 if (broken) {
282                         blob->data[blob->length - 1]++;
283                 }
284         }
285
286         if (version == 3) {
287                 struct bkrp_access_check_v3 access_struct;
288                 struct hc_sha512state sctx;
289                 uint8_t nonce[32];
290
291                 ZERO_STRUCT(access_struct);
292                 generate_random_buffer(nonce, sizeof(nonce));
293                 access_struct.nonce_len = sizeof(nonce);
294                 access_struct.nonce = nonce;
295                 access_struct.sid = *sid;
296
297                 ndr_err = ndr_push_struct_blob(blob, blob, &access_struct,
298                                 (ndr_push_flags_fn_t)ndr_push_bkrp_access_check_v3);
299                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
300                         return NULL;
301                 }
302
303                 /*We pushed the whole structure including a null hash
304                 * but the hash need to be calculated only up to the hash field
305                 * so we reduce the size of what has to be calculated
306                 */
307
308                 SHA512_Init(&sctx);
309                 SHA512_Update(&sctx, blob->data,
310                               blob->length - sizeof(access_struct.hash));
311                 SHA512_Final(blob->data + blob->length - sizeof(access_struct.hash),
312                              &sctx);
313
314                 /* Altering the SHA */
315                 if (broken) {
316                         blob->data[blob->length -1]++;
317                 }
318         }
319         talloc_free(tmp_ctx);
320         return blob;
321 }
322
323
324 static DATA_BLOB *encrypt_blob(struct torture_context *tctx,
325                                     TALLOC_CTX *mem_ctx,
326                                     DATA_BLOB *key,
327                                     DATA_BLOB *iv,
328                                     DATA_BLOB *to_encrypt,
329                                     const AlgorithmIdentifier *alg)
330 {
331         hx509_crypto crypto;
332         hx509_context hctx;
333         heim_octet_string ivos;
334         heim_octet_string *encrypted;
335         DATA_BLOB *blob = talloc_zero(mem_ctx, DATA_BLOB);
336         int res;
337
338         ivos.data = talloc_array(mem_ctx, uint8_t, iv->length);
339         ivos.length = iv->length;
340         memcpy(ivos.data, iv->data, iv->length);
341
342         hx509_context_init(&hctx);
343         res = hx509_crypto_init(hctx, NULL, &alg->algorithm, &crypto);
344         if (res) {
345                 torture_comment(tctx,
346                                 "error while doing the init of the crypto object\n");
347                 hx509_context_free(&hctx);
348                 return NULL;
349         }
350         res = hx509_crypto_set_key_data(crypto, key->data, key->length);
351         if (res) {
352                 torture_comment(tctx,
353                                 "error while setting the key of the crypto object\n");
354                 hx509_context_free(&hctx);
355                 return NULL;
356         }
357
358         hx509_crypto_set_padding(crypto, HX509_CRYPTO_PADDING_NONE);
359         res = hx509_crypto_encrypt(crypto,
360                                    to_encrypt->data,
361                                    to_encrypt->length,
362                                    &ivos,
363                                    &encrypted);
364         if (res) {
365                 torture_comment(tctx, "error while encrypting\n");
366                 hx509_crypto_destroy(crypto);
367                 hx509_context_free(&hctx);
368                 return NULL;
369         }
370
371         *blob = data_blob_talloc(blob, encrypted->data, encrypted->length);
372         der_free_octet_string(encrypted);
373         free(encrypted);
374         hx509_crypto_destroy(crypto);
375         hx509_context_free(&hctx);
376         return blob;
377 }
378
379 /*
380  * Certs used for this protocol have a GUID in the issuer_uniq_id field.
381  * This function fetch it.
382  */
383 static struct GUID *get_cert_guid(struct torture_context *tctx,
384                                   TALLOC_CTX *mem_ctx,
385                                   uint8_t *cert_data,
386                                   uint32_t cert_len)
387 {
388         hx509_context hctx;
389         hx509_cert cert;
390         heim_bit_string subjectuniqid;
391         DATA_BLOB data;
392         int hret;
393         uint32_t size;
394         struct GUID *guid = talloc_zero(mem_ctx, struct GUID);
395         NTSTATUS status;
396
397         hx509_context_init(&hctx);
398
399         hret = hx509_cert_init_data(hctx, cert_data, cert_len, &cert);
400         if (hret) {
401                 torture_comment(tctx, "error while loading the cert\n");
402                 hx509_context_free(&hctx);
403                 return NULL;
404         }
405         hret = hx509_cert_get_issuer_unique_id(hctx, cert, &subjectuniqid);
406         if (hret) {
407                 torture_comment(tctx, "error while getting the issuer_uniq_id\n");
408                 hx509_cert_free(cert);
409                 hx509_context_free(&hctx);
410                 return NULL;
411         }
412
413         /* The subjectuniqid is a bit string,
414          * which means that the real size has to be divided by 8
415          * to have the number of bytes
416          */
417         hx509_cert_free(cert);
418         hx509_context_free(&hctx);
419         size = subjectuniqid.length / 8;
420         data = data_blob_const(subjectuniqid.data, size);
421
422         status = GUID_from_data_blob(&data, guid);
423         der_free_bit_string(&subjectuniqid);
424         if (!NT_STATUS_IS_OK(status)) {
425                 return NULL;
426         }
427
428         return guid;
429 }
430
431 /*
432  * Encrypt a blob with the private key of the certificate
433  * passed as a parameter.
434  */
435 static DATA_BLOB *encrypt_blob_pk(struct torture_context *tctx,
436                                   TALLOC_CTX *mem_ctx,
437                                   uint8_t *cert_data,
438                                   uint32_t cert_len,
439                                   DATA_BLOB *to_encrypt)
440 {
441         hx509_context hctx;
442         hx509_cert cert;
443         heim_octet_string secretdata;
444         heim_octet_string encrypted;
445         heim_oid encryption_oid;
446         DATA_BLOB *blob;
447         int hret;
448
449         hx509_context_init(&hctx);
450
451         hret = hx509_cert_init_data(hctx, cert_data, cert_len, &cert);
452         if (hret) {
453                 torture_comment(tctx, "error while loading the cert\n");
454                 hx509_context_free(&hctx);
455                 return NULL;
456         }
457
458         secretdata.data = to_encrypt->data;
459         secretdata.length = to_encrypt->length;
460         hret = _hx509_cert_public_encrypt(hctx, &secretdata,
461                                           cert, &encryption_oid,
462                                           &encrypted);
463         hx509_cert_free(cert);
464         hx509_context_free(&hctx);
465         if (hret) {
466                 torture_comment(tctx, "error while encrypting\n");
467                 return NULL;
468         }
469
470         blob = talloc_zero(mem_ctx, DATA_BLOB);
471         if (blob == NULL) {
472                 der_free_oid(&encryption_oid);
473                 der_free_octet_string(&encrypted);
474                 return NULL;
475         }
476
477         *blob = data_blob_talloc(blob, encrypted.data, encrypted.length);
478         der_free_octet_string(&encrypted);
479         der_free_oid(&encryption_oid);
480         if (blob->data == NULL) {
481                 return NULL;
482         }
483
484         return blob;
485 }
486
487
488 static struct bkrp_BackupKey *createRetreiveBackupKeyGUIDStruct(struct torture_context *tctx,
489                                 struct dcerpc_pipe *p, int version, DATA_BLOB *out)
490 {
491         struct dcerpc_binding *binding = p->binding;
492         struct bkrp_client_side_wrapped data;
493         struct GUID *g = talloc(tctx, struct GUID);
494         struct bkrp_BackupKey *r = talloc_zero(tctx, struct bkrp_BackupKey);
495         enum ndr_err_code ndr_err;
496         DATA_BLOB blob;
497         NTSTATUS status;
498
499         if (r == NULL) {
500                 return NULL;
501         }
502
503         binding->flags = binding->flags & (DCERPC_SEAL|DCERPC_AUTH_SPNEGO);
504         ZERO_STRUCT(data);
505         status = GUID_from_string(BACKUPKEY_RETRIEVE_BACKUP_KEY_GUID, g);
506         if (!NT_STATUS_IS_OK(status)) {
507                 return NULL;
508         }
509
510         r->in.guidActionAgent = g;
511         data.version = version;
512         ndr_err = ndr_push_struct_blob(&blob, tctx, &data,
513                         (ndr_push_flags_fn_t)ndr_push_bkrp_client_side_wrapped);
514         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
515                 return NULL;
516         }
517         r->in.data_in = blob.data;
518         r->in.data_in_len = blob.length;
519         r->out.data_out = &out->data;
520         r->out.data_out_len = talloc(r, uint32_t);
521         return r;
522 }
523
524 static struct bkrp_BackupKey *createRestoreGUIDStruct(struct torture_context *tctx,
525                                 struct dcerpc_pipe *p, int version, DATA_BLOB *out,
526                                 bool norevert,
527                                 bool broken_version,
528                                 bool broken_user,
529                                 bool broken_magic_secret,
530                                 bool broken_magic_access,
531                                 bool broken_hash_access,
532                                 bool broken_cert_guid)
533 {
534         struct dcerpc_binding_handle *b = p->binding_handle;
535         struct bkrp_client_side_wrapped data;
536         DATA_BLOB *xs;
537         DATA_BLOB *sec;
538         DATA_BLOB *enc_sec;
539         DATA_BLOB *enc_xs;
540         DATA_BLOB *blob2;
541         DATA_BLOB enc_sec_reverted;
542         DATA_BLOB des3_key;
543         DATA_BLOB aes_key;
544         DATA_BLOB iv;
545         DATA_BLOB out_blob;
546         struct GUID *guid, *g;
547         int t;
548         uint32_t size;
549         enum ndr_err_code ndr_err;
550         NTSTATUS status;
551         const char *user;
552         struct bkrp_BackupKey *r = createRetreiveBackupKeyGUIDStruct(tctx, p, version, &out_blob);
553         if (r == NULL) {
554                 return NULL;
555         }
556
557         if (broken_user) {
558                 /* we take a fake user*/
559                 user = "guest";
560         } else {
561                 user = cli_credentials_get_username(cmdline_credentials);
562         }
563
564
565         torture_assert_ntstatus_ok(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r),
566                                         "Get GUID");
567         /*
568          * We have to set it outside of the function createRetreiveBackupKeyGUIDStruct
569          * the len of the blob, this is due to the fact that they don't have the
570          * same size (one is 32bits the other 64bits)
571          */
572         out_blob.length = *r->out.data_out_len;
573
574         sec = create_unencryptedsecret(tctx, broken_magic_secret, version);
575         if (sec == NULL) {
576                 return NULL;
577         }
578
579         xs = create_access_check(tctx, p, tctx, user, broken_hash_access, version);
580         if (xs == NULL) {
581                 return NULL;
582         }
583
584         if (broken_magic_access){
585                 /* The start of the access_check structure contains the 
586                  * GUID of the certificate
587                  */
588                 xs->data[0]++;
589         }
590
591         enc_sec = encrypt_blob_pk(tctx, tctx, out_blob.data, out_blob.length, sec);
592         if (!enc_sec) {
593                 return NULL;
594         }
595         enc_sec_reverted.data = talloc_array(tctx, uint8_t, enc_sec->length);
596         if (enc_sec_reverted.data == NULL) {
597                 return NULL;
598         }
599         enc_sec_reverted.length = enc_sec->length;
600
601         /*
602         * We DO NOT revert the array on purpose it's in order to check that
603         * when the server is not able to decrypt then it answer the correct error
604         */
605         if (norevert) {
606                 for(t=0; t< enc_sec->length; t++) {
607                         enc_sec_reverted.data[t] = ((uint8_t*)enc_sec->data)[t];
608                 }
609         } else {
610                 for(t=0; t< enc_sec->length; t++) {
611                         enc_sec_reverted.data[t] = ((uint8_t*)enc_sec->data)[enc_sec->length - t -1];
612                 }
613         }
614
615         size = sec->length;
616         if (version ==2) {
617                 const AlgorithmIdentifier *alg = hx509_crypto_des_rsdi_ede3_cbc();
618                 iv.data = sec->data+(size - 8);
619                 iv.length = 8;
620
621                 des3_key.data = sec->data+(size - 32);
622                 des3_key.length = 24;
623
624                 enc_xs = encrypt_blob(tctx, tctx, &des3_key, &iv, xs, alg);
625         }
626         if (version == 3) {
627                 const AlgorithmIdentifier *alg = hx509_crypto_aes256_cbc();
628                 iv.data = sec->data+(size-16);
629                 iv.length = 16;
630
631                 aes_key.data = sec->data+(size-48);
632                 aes_key.length = 32;
633
634                 enc_xs = encrypt_blob(tctx, tctx, &aes_key, &iv, xs, alg);
635         }
636
637         if (!enc_xs) {
638                 return NULL;
639         }
640
641         /* To cope with the fact that heimdal do padding at the end for the moment */
642         enc_xs->length = xs->length;
643
644         guid = get_cert_guid(tctx, tctx, out_blob.data, out_blob.length);
645         if (guid == NULL) {
646                 return NULL;
647         }
648
649         if (broken_version) {
650                 data.version = 1;
651         } else {
652                 data.version = version;
653         }
654
655         data.guid = *guid;
656         data.encrypted_secret = enc_sec_reverted.data;
657         data.access_check = enc_xs->data;
658         data.encrypted_secret_len = enc_sec->length;
659         data.access_check_len = enc_xs->length;
660
661         /* We want the blob to persist after this function so we don't
662          * allocate it in the stack
663          */
664         blob2 = talloc(tctx, DATA_BLOB);
665         if (blob2 == NULL) {
666                 return NULL;
667         }
668
669         ndr_err = ndr_push_struct_blob(blob2, tctx, &data,
670                         (ndr_push_flags_fn_t)ndr_push_bkrp_client_side_wrapped);
671         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
672                 return NULL;
673         }
674
675         if (broken_cert_guid) {
676                 blob2->data[12]++;
677         }
678
679         ZERO_STRUCT(*r);
680
681         g = talloc(tctx, struct GUID);
682         if (g == NULL) {
683                 return NULL;
684         }
685
686         status = GUID_from_string(BACKUPKEY_RESTORE_GUID, g);
687         if (!NT_STATUS_IS_OK(status)) {
688                 return NULL;
689         }
690
691         r->in.guidActionAgent = g;
692         r->in.data_in = blob2->data;
693         r->in.data_in_len = blob2->length;
694         r->in.param = 0;
695         r->out.data_out = &(out->data);
696         r->out.data_out_len = talloc(r, uint32_t);
697         return r;
698 }
699
700 /* Check that we are able to receive the certificate of the DCs
701  * used for client wrap version of the backup key protocol
702  */
703 static bool test_RetreiveBackupKeyGUID(struct torture_context *tctx,
704                                         struct dcerpc_pipe *p)
705 {
706         struct dcerpc_binding_handle *b = p->binding_handle;
707         DATA_BLOB out_blob;
708         struct bkrp_BackupKey *r = createRetreiveBackupKeyGUIDStruct(tctx, p, 2, &out_blob);
709
710         if (r == NULL) {
711                 return false;
712         }
713
714         if (p->conn->security_state.auth_info != NULL &&
715             p->conn->security_state.auth_info->auth_level == 6) {
716                 torture_assert_ntstatus_ok(tctx,
717                                 dcerpc_bkrp_BackupKey_r(b, tctx, r),
718                                 "Get GUID");
719
720                 out_blob.length = *r->out.data_out_len;
721                 torture_assert_werr_equal(tctx,
722                                                 r->out.result,
723                                                 WERR_OK,
724                                                 "Wrong dce/rpc error code");
725         } else {
726                 torture_assert_ntstatus_equal(tctx,
727                                                 dcerpc_bkrp_BackupKey_r(b, tctx, r),
728                                                 NT_STATUS_ACCESS_DENIED,
729                                                 "Get GUID");
730         }
731         return true;
732 }
733
734 /* Test to check the failure to recover a secret because the 
735  * secret blob is not reversed
736  */
737 static bool test_RestoreGUID_ko(struct torture_context *tctx,
738                                 struct dcerpc_pipe *p)
739 {
740         enum ndr_err_code ndr_err;
741         struct dcerpc_binding_handle *b = p->binding_handle;
742         DATA_BLOB out_blob;
743         struct bkrp_client_side_unwrapped resp;
744
745         if (p->conn->security_state.auth_info != NULL &&
746             p->conn->security_state.auth_info->auth_level == 6) {
747                 struct bkrp_BackupKey *r = createRestoreGUIDStruct(tctx, p, 2, &out_blob,
748                                         true, false, false, false, false, false, false);
749                 torture_assert_ntstatus_ok(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r), "Restore GUID");
750                 out_blob.length = *r->out.data_out_len;
751                 ndr_err = ndr_pull_struct_blob(&out_blob, tctx, &resp, (ndr_pull_flags_fn_t)ndr_pull_bkrp_client_side_unwrapped);
752                 torture_assert_int_equal(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), 0, "Unable to unmarshall bkrp_client_side_unwrapped");
753                 torture_assert_werr_equal(tctx, r->out.result, WERR_INVALID_DATA, "Wrong error code");
754         } else {
755                 struct bkrp_BackupKey *r = createRetreiveBackupKeyGUIDStruct(tctx, p, 2, &out_blob);
756                 torture_assert_ntstatus_equal(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r),
757                         NT_STATUS_ACCESS_DENIED, "Get GUID");
758         }
759         return true;
760 }
761
762 static bool test_RestoreGUID_wrongversion(struct torture_context *tctx,
763                                           struct dcerpc_pipe *p)
764 {
765         enum ndr_err_code ndr_err;
766         struct dcerpc_binding_handle *b = p->binding_handle;
767         DATA_BLOB out_blob;
768         struct bkrp_client_side_unwrapped resp;
769
770         if (p->conn->security_state.auth_info != NULL &&
771             p->conn->security_state.auth_info->auth_level == 6) {
772                 struct bkrp_BackupKey *r = createRestoreGUIDStruct(tctx, p, 2, &out_blob,
773                                         false, true, false, false, false, false, false);
774                 torture_assert_ntstatus_ok(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r), "Restore GUID");
775                 out_blob.length = *r->out.data_out_len;
776                 ndr_err = ndr_pull_struct_blob(&out_blob, tctx, &resp, (ndr_pull_flags_fn_t)ndr_pull_bkrp_client_side_unwrapped);
777                 torture_assert_int_equal(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), 0, "Unable to unmarshall bkrp_client_side_unwrapped");
778                 torture_assert_werr_equal(tctx, r->out.result, WERR_INVALID_PARAM, "Wrong error code on wrong version");
779         } else {
780                 struct bkrp_BackupKey *r = createRetreiveBackupKeyGUIDStruct(tctx, p, 2, &out_blob);
781                 torture_assert_ntstatus_equal(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r),
782                         NT_STATUS_ACCESS_DENIED, "Get GUID");
783         }
784         return true;
785 }
786
787 static bool test_RestoreGUID_wronguser(struct torture_context *tctx,
788                                        struct dcerpc_pipe *p)
789 {
790         enum ndr_err_code ndr_err;
791         struct dcerpc_binding_handle *b = p->binding_handle;
792         DATA_BLOB out_blob;
793         struct bkrp_client_side_unwrapped resp;
794
795         if (p->conn->security_state.auth_info != NULL &&
796             p->conn->security_state.auth_info->auth_level == 6) {
797                 struct bkrp_BackupKey *r = createRestoreGUIDStruct(tctx, p, 2, &out_blob,
798                                         false, false, true, false, false, false, false);
799                 torture_assert_ntstatus_ok(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r), "Restore GUID");
800                 out_blob.length = *r->out.data_out_len;
801                 ndr_err = ndr_pull_struct_blob(&out_blob, tctx, &resp, (ndr_pull_flags_fn_t)ndr_pull_bkrp_client_side_unwrapped);
802                 torture_assert_int_equal(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), 0, "Unable to unmarshall bkrp_client_side_unwrapped");
803                 torture_assert_werr_equal(tctx, r->out.result, WERR_INVALID_ACCESS, "Restore GUID");
804         } else {
805                 struct bkrp_BackupKey *r = createRetreiveBackupKeyGUIDStruct(tctx, p, 2, &out_blob);
806                 torture_assert_ntstatus_equal(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r),
807                         NT_STATUS_ACCESS_DENIED, "Get GUID");
808         }
809         return true;
810 }
811
812 static bool test_RestoreGUID_v3(struct torture_context *tctx,
813                                 struct dcerpc_pipe *p)
814 {
815         enum ndr_err_code ndr_err;
816         struct dcerpc_binding_handle *b = p->binding_handle;
817         DATA_BLOB out_blob;
818         struct bkrp_client_side_unwrapped resp;
819
820         if (p->conn->security_state.auth_info != NULL &&
821             p->conn->security_state.auth_info->auth_level == 6) {
822                 struct bkrp_BackupKey *r = createRestoreGUIDStruct(tctx, p, 3, &out_blob,
823                                         false, false, false, false, false, false, false);
824                 torture_assert_ntstatus_ok(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r), "Restore GUID");
825                 out_blob.length = *r->out.data_out_len;
826                 ndr_err = ndr_pull_struct_blob(&out_blob, tctx, &resp, (ndr_pull_flags_fn_t)ndr_pull_bkrp_client_side_unwrapped);
827                 torture_assert_int_equal(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), 1, "Unable to unmarshall bkrp_client_side_unwrapped");
828                 torture_assert_werr_equal(tctx, r->out.result, WERR_OK, "Restore GUID");
829                 torture_assert_str_equal(tctx, (char*)resp.secret.data, secret, "Wrong secret");
830         } else {
831                 struct bkrp_BackupKey *r = createRetreiveBackupKeyGUIDStruct(tctx, p, 2, &out_blob);
832                 torture_assert_ntstatus_equal(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r),
833                         NT_STATUS_ACCESS_DENIED, "Get GUID");
834         }
835         return true;
836 }
837
838 static bool test_RestoreGUID(struct torture_context *tctx,
839                              struct dcerpc_pipe *p)
840 {
841         enum ndr_err_code ndr_err;
842         struct dcerpc_binding_handle *b = p->binding_handle;
843         DATA_BLOB out_blob;
844         struct bkrp_client_side_unwrapped resp;
845
846         if (p->conn->security_state.auth_info != NULL &&
847             p->conn->security_state.auth_info->auth_level == 6) {
848                 struct bkrp_BackupKey *r = createRestoreGUIDStruct(tctx, p, 2, &out_blob,
849                                         false, false, false, false, false, false, false);
850                 torture_assert_ntstatus_ok(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r), "Restore GUID");
851                 out_blob.length = *r->out.data_out_len;
852                 ndr_err = ndr_pull_struct_blob(&out_blob, tctx, &resp, (ndr_pull_flags_fn_t)ndr_pull_bkrp_client_side_unwrapped);
853                 torture_assert_int_equal(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), 1, "Unable to unmarshall bkrp_client_side_unwrapped");
854                 torture_assert_werr_equal(tctx, r->out.result, WERR_OK, "Restore GUID");
855                 torture_assert_str_equal(tctx, (char*)resp.secret.data, secret, "Wrong secret");
856         } else {
857                 struct bkrp_BackupKey *r = createRetreiveBackupKeyGUIDStruct(tctx, p, 2, &out_blob);
858                 torture_assert_ntstatus_equal(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r),
859                         NT_STATUS_ACCESS_DENIED, "Get GUID");
860         }
861         return true;
862 }
863
864 static bool test_RestoreGUID_badmagiconsecret(struct torture_context *tctx,
865                                               struct dcerpc_pipe *p)
866 {
867         enum ndr_err_code ndr_err;
868         struct dcerpc_binding_handle *b = p->binding_handle;
869         DATA_BLOB out_blob;
870         struct bkrp_client_side_unwrapped resp;
871
872         if (p->conn->security_state.auth_info != NULL &&
873             p->conn->security_state.auth_info->auth_level == 6) {
874                 struct bkrp_BackupKey *r = createRestoreGUIDStruct(tctx, p, 3, &out_blob,
875                                         false, false, false, true, false, false, false);
876                 torture_assert_ntstatus_ok(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r), "Restore GUID");
877                 out_blob.length = *r->out.data_out_len;
878                 ndr_err = ndr_pull_struct_blob(&out_blob, tctx, &resp, (ndr_pull_flags_fn_t)ndr_pull_bkrp_client_side_unwrapped);
879                 torture_assert_int_equal(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), 0, "Unable to unmarshall bkrp_client_side_unwrapped");
880                 torture_assert_werr_equal(tctx, r->out.result, WERR_INVALID_DATA, "Wrong error code while providing bad magic in secret");
881         } else {
882                 struct bkrp_BackupKey *r = createRetreiveBackupKeyGUIDStruct(tctx, p, 2, &out_blob);
883                 torture_assert_ntstatus_equal(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r),
884                         NT_STATUS_ACCESS_DENIED, "Get GUID");
885         }
886         return true;
887 }
888
889 static bool test_RestoreGUID_emptyrequest(struct torture_context *tctx,
890                                           struct dcerpc_pipe *p)
891 {
892         struct dcerpc_binding_handle *b = p->binding_handle;
893         DATA_BLOB out_blob;
894
895         if (p->conn->security_state.auth_info != NULL &&
896             p->conn->security_state.auth_info->auth_level == 6) {
897                 struct bkrp_BackupKey *r = createRestoreGUIDStruct(tctx, p, 3, &out_blob,
898                                         false, false, false, true, false, false, true);
899
900                 torture_assert_int_equal(tctx, r != NULL, 1, "Error while creating the restoreGUID struct");
901                 r->in.data_in = talloc(tctx, uint8_t);
902                 r->in.data_in_len = 0;
903                 r->in.param = 0;
904                 torture_assert_ntstatus_ok(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r), "Restore GUID");
905                 out_blob.length = *r->out.data_out_len;
906                 torture_assert_werr_equal(tctx, r->out.result, WERR_INVALID_PARAM, "Bad error code on wrong has in access check");
907         } else {
908                 struct bkrp_BackupKey *r = createRetreiveBackupKeyGUIDStruct(tctx, p, 2, &out_blob);
909                 torture_assert_ntstatus_equal(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r),
910                         NT_STATUS_ACCESS_DENIED, "Get GUID");
911         }
912         return true;
913 }
914
915 static bool test_RestoreGUID_badcertguid(struct torture_context *tctx,
916                                          struct dcerpc_pipe *p)
917 {
918         enum ndr_err_code ndr_err;
919         struct dcerpc_binding_handle *b = p->binding_handle;
920         DATA_BLOB out_blob;
921         struct bkrp_client_side_unwrapped resp;
922
923         if (p->conn->security_state.auth_info != NULL &&
924             p->conn->security_state.auth_info->auth_level == 6) {
925                 struct bkrp_BackupKey *r = createRestoreGUIDStruct(tctx, p, 3, &out_blob,
926                                         false, false, false, false, false, false, true);
927                 torture_assert_ntstatus_ok(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r), "Restore GUID");
928                 out_blob.length = *r->out.data_out_len;
929                 ndr_err = ndr_pull_struct_blob(&out_blob, tctx, &resp, (ndr_pull_flags_fn_t)ndr_pull_bkrp_client_side_unwrapped);
930                 torture_assert_int_equal(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), 0, "Unable to unmarshall bkrp_client_side_unwrapped");
931                 torture_assert_werr_equal(tctx, r->out.result, WERR_FILE_NOT_FOUND, "Bad error code on wrong has in access check");
932         } else {
933                 struct bkrp_BackupKey *r = createRetreiveBackupKeyGUIDStruct(tctx, p, 2, &out_blob);
934                 torture_assert_ntstatus_equal(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r),
935                         NT_STATUS_ACCESS_DENIED, "Get GUID");
936         }
937         return true;
938 }
939
940 static bool test_RestoreGUID_badmagicaccesscheck(struct torture_context *tctx,
941                                                  struct dcerpc_pipe *p)
942 {
943         enum ndr_err_code ndr_err;
944         struct dcerpc_binding_handle *b = p->binding_handle;
945         DATA_BLOB out_blob;
946         struct bkrp_client_side_unwrapped resp;
947
948         if (p->conn->security_state.auth_info != NULL &&
949             p->conn->security_state.auth_info->auth_level == 6) {
950                 struct bkrp_BackupKey *r = createRestoreGUIDStruct(tctx, p, 2, &out_blob,
951                                         false, false, false, false, true, false, false);
952                 torture_assert_ntstatus_ok(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r), "Restore GUID");
953                 out_blob.length = *r->out.data_out_len;
954                 ndr_err = ndr_pull_struct_blob(&out_blob, tctx, &resp, (ndr_pull_flags_fn_t)ndr_pull_bkrp_client_side_unwrapped);
955                 torture_assert_int_equal(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), 0, "Unable to unmarshall bkrp_client_side_unwrapped");
956                 torture_assert_werr_equal(tctx, r->out.result, WERR_INVALID_DATA, "Bad error code on wrong has in access check");
957         } else {
958                 struct bkrp_BackupKey *r = createRetreiveBackupKeyGUIDStruct(tctx, p, 2, &out_blob);
959                 torture_assert_ntstatus_equal(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r),
960                         NT_STATUS_ACCESS_DENIED, "Get GUID");
961         }
962         return true;
963 }
964
965 static bool test_RestoreGUID_badhashaccesscheck(struct torture_context *tctx,
966                                                 struct dcerpc_pipe *p)
967 {
968         enum ndr_err_code ndr_err;
969         struct dcerpc_binding_handle *b = p->binding_handle;
970         DATA_BLOB out_blob;
971         struct bkrp_client_side_unwrapped resp;
972
973         if (p->conn->security_state.auth_info != NULL &&
974             p->conn->security_state.auth_info->auth_level == 6) {
975                 struct bkrp_BackupKey *r = createRestoreGUIDStruct(tctx, p, 2, &out_blob,
976                                         false, false, false, false, false, true, false);
977                 torture_assert_ntstatus_ok(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r), "Restore GUID");
978                 out_blob.length = *r->out.data_out_len;
979                 ndr_err = ndr_pull_struct_blob(&out_blob, tctx, &resp, (ndr_pull_flags_fn_t)ndr_pull_bkrp_client_side_unwrapped);
980                 torture_assert_int_equal(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), 0, "Unable to unmarshall bkrp_client_side_unwrapped");
981                 torture_assert_werr_equal(tctx, r->out.result, WERR_INVALID_DATA, "Bad error code on wrong has in access check");
982         } else {
983                 struct bkrp_BackupKey *r = createRetreiveBackupKeyGUIDStruct(tctx, p, 2, &out_blob);
984                 torture_assert_ntstatus_equal(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r),
985                         NT_STATUS_ACCESS_DENIED, "Get GUID");
986         }
987         return true;
988 }
989
990 struct torture_suite *torture_rpc_backupkey(TALLOC_CTX *mem_ctx)
991 {
992         struct torture_rpc_tcase *tcase;
993         struct torture_suite *suite = torture_suite_create(mem_ctx, "backupkey");
994         struct torture_test *test;
995
996         tcase = torture_suite_add_rpc_iface_tcase(suite, "backupkey",
997                                                   &ndr_table_backupkey);
998
999         test = torture_rpc_tcase_add_test(tcase, "retreive_backup_key_guid",
1000                                           test_RetreiveBackupKeyGUID);
1001
1002         test = torture_rpc_tcase_add_test(tcase, "restore_guid",
1003                                           test_RestoreGUID);
1004
1005         test = torture_rpc_tcase_add_test(tcase, "restore_guid version 3",
1006                                           test_RestoreGUID_v3);
1007
1008 /* We double the test in order to be sure that we don't mess stuff (ie. freeing static stuff */
1009
1010         test = torture_rpc_tcase_add_test(tcase, "restore_guid_2nd",
1011                                           test_RestoreGUID);
1012
1013         test = torture_rpc_tcase_add_test(tcase, "unable_to_decrypt_secret",
1014                                           test_RestoreGUID_ko);
1015
1016         test = torture_rpc_tcase_add_test(tcase, "wrong_user_restore_guid",
1017                                           test_RestoreGUID_wronguser);
1018
1019         test = torture_rpc_tcase_add_test(tcase, "wrong_version_restore_guid",
1020                                           test_RestoreGUID_wrongversion);
1021
1022         test = torture_rpc_tcase_add_test(tcase, "bad_magic_on_secret_restore_guid",
1023                                           test_RestoreGUID_badmagiconsecret);
1024
1025         test = torture_rpc_tcase_add_test(tcase, "bad_hash_on_secret_restore_guid",
1026                                           test_RestoreGUID_badhashaccesscheck);
1027
1028         test = torture_rpc_tcase_add_test(tcase, "bad_magic_on_accesscheck_restore_guid",
1029                                           test_RestoreGUID_badmagicaccesscheck);
1030
1031         test = torture_rpc_tcase_add_test(tcase, "bad_cert_guid_restore_guid",
1032                                           test_RestoreGUID_badcertguid);
1033
1034         test = torture_rpc_tcase_add_test(tcase, "empty_request_restore_guid",
1035                                           test_RestoreGUID_emptyrequest);
1036
1037         return suite;
1038 }