s4:rpc_server/backupkey: add "backupkey:cert_dn_utf16 = yes"
authorStefan Metzmacher <metze@samba.org>
Tue, 19 Jul 2022 06:25:01 +0000 (08:25 +0200)
committerStefan Metzmacher <metze@samba.org>
Wed, 20 Jul 2022 13:21:18 +0000 (15:21 +0200)
source4/rpc_server/backupkey/dcesrv_backupkey.c

index 12fd0b0a390f0a87493d40e8558d1f675216820a..2ce551caa41b6c5ffa3b91f6a84a35379683f344 100644 (file)
@@ -750,7 +750,109 @@ static WERROR bkrp_client_wrap_decrypt_data(struct dcesrv_call_state *dce_call,
 static char *bkrp_generate_cert_dn(TALLOC_CTX *mem_ctx,
                                   struct loadparm_context *lp_ctx)
 {
-       return talloc_asprintf(mem_ctx, "CN=%s", lpcfg_realm(lp_ctx));
+       TALLOC_CTX *frame = talloc_stackframe();
+       char *dn = NULL;
+
+       if (lpcfg_parm_bool(lp_ctx, NULL, "backupkey", "cert_dn_utf16", false)) {
+               const char *domain = lpcfg_dnsdomain(lp_ctx);
+               DATA_BLOB domain_utf8 = data_blob_string_const_null(domain);
+               DATA_BLOB domain_utf16 = data_blob_null;
+               char *domain_hex = NULL;
+               char ber_length[(1+8)*2+1] = {0,};
+               bool ok;
+
+               /*
+                * Windows uses a null terminated utf16-le string
+                * for the CN and it is the lower case dns domain name.
+                *
+                * It's encoded as PrintableString.
+                *
+                * In order to pass this with embedded '\0' to via
+                * const char *dn to gnutls_x509_crt_set_[issuer_]dn(),
+                * we need to pass the full asn1 encoded value as
+                * # followed by a hexstring
+                */
+
+               ok = convert_string_talloc(frame, CH_UNIX, CH_UTF16LE,
+                                          domain_utf8.data,
+                                          domain_utf8.length,
+                                          &domain_utf16.data,
+                                          &domain_utf16.length);
+               if (!ok) {
+                       TALLOC_FREE(frame);
+                       return NULL;
+               }
+
+               domain_hex = data_blob_hex_string_lower(frame, &domain_utf16);
+               if (domain_hex == NULL) {
+                       TALLOC_FREE(frame);
+                       return NULL;
+               }
+
+               if (domain_utf16.length <= INT8_MAX) {
+                       uint8_t lbe[1] = {0,};
+                       PUSH_BE_U8(lbe, 0, domain_utf16.length);
+                       snprintf(ber_length, sizeof(ber_length),
+                                "%02x",
+                                lbe[0]);
+               } else if (domain_utf16.length <= UINT8_MAX) {
+                       uint8_t lbe[1] = {0,};
+                       PUSH_BE_U8(lbe, 0, domain_utf16.length);
+                       snprintf(ber_length, sizeof(ber_length),
+                                "%02x%02x",
+                                0x81,
+                                lbe[0]);
+               } else if (domain_utf16.length <= UINT16_MAX) {
+                       uint8_t lbe[2] = {0,};
+                       PUSH_BE_U16(lbe, 0, domain_utf16.length);
+                       snprintf(ber_length, sizeof(ber_length),
+                                "%02x%02x%02x",
+                                0x82,
+                                lbe[0],
+                                lbe[1]);
+               } else if (domain_utf16.length <= UINT32_MAX) {
+                       uint8_t lbe[4] = {0,};
+                       PUSH_BE_U32(lbe, 0, domain_utf16.length);
+                       snprintf(ber_length, sizeof(ber_length),
+                                "%02x%02x%02x%02x%02x",
+                                0x84,
+                                lbe[0],
+                                lbe[1],
+                                lbe[2],
+                                lbe[3]);
+               } else {
+                       uint8_t lbe[8] = {0,};
+                       PUSH_BE_U64(lbe, 0, domain_utf16.length);
+                       snprintf(ber_length, sizeof(ber_length),
+                                "%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+                                0x88,
+                                lbe[0],
+                                lbe[1],
+                                lbe[2],
+                                lbe[3],
+                                lbe[4],
+                                lbe[5],
+                                lbe[6],
+                                lbe[7]);
+               }
+               dn = talloc_asprintf(mem_ctx, "CN=#%02x%s%s",
+                                    0x13, /* PrintableString */
+                                    ber_length,
+                                    domain_hex);
+               if (dn == NULL) {
+                       TALLOC_FREE(frame);
+                       return NULL;
+               }
+       } else {
+               dn = talloc_asprintf(mem_ctx, "CN=%s", lpcfg_realm(lp_ctx));
+               if (dn == NULL) {
+                       TALLOC_FREE(frame);
+                       return NULL;
+               }
+       }
+
+       TALLOC_FREE(frame);
+       return dn;
 }
 
 static DATA_BLOB *reverse_and_get_blob(TALLOC_CTX *mem_ctx,