mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-24 14:36:13 +01:00
gtlscertificate: Allow any type of private key in PEM files
Allow any type of private key in PEM files by treating PEM guards ending with "PRIVATE KEY-----" as a private key instead of looking for a pre-defined set of PEM guards. This enables the possibility for custom GTlsBackend to add support for new key types. Test cases have been expanded to ensure PEM parsing works for private key when either header or footer is missing. Encrypted PKCS#8 is still rejected. Test case has been added for this to ensure behaviour is the same before and after this change.
This commit is contained in:
parent
73ca761a8d
commit
a437a50694
@ -218,12 +218,11 @@ g_tls_certificate_new_internal (const gchar *certificate_pem,
|
||||
|
||||
#define PEM_CERTIFICATE_HEADER "-----BEGIN CERTIFICATE-----"
|
||||
#define PEM_CERTIFICATE_FOOTER "-----END CERTIFICATE-----"
|
||||
#define PEM_PKCS1_PRIVKEY_HEADER "-----BEGIN RSA PRIVATE KEY-----"
|
||||
#define PEM_PKCS1_PRIVKEY_FOOTER "-----END RSA PRIVATE KEY-----"
|
||||
#define PEM_PKCS8_PRIVKEY_HEADER "-----BEGIN PRIVATE KEY-----"
|
||||
#define PEM_PKCS8_PRIVKEY_FOOTER "-----END PRIVATE KEY-----"
|
||||
#define PEM_PRIVKEY_HEADER_BEGIN "-----BEGIN "
|
||||
#define PEM_PRIVKEY_HEADER_END "PRIVATE KEY-----"
|
||||
#define PEM_PRIVKEY_FOOTER_BEGIN "-----END "
|
||||
#define PEM_PRIVKEY_FOOTER_END "PRIVATE KEY-----"
|
||||
#define PEM_PKCS8_ENCRYPTED_HEADER "-----BEGIN ENCRYPTED PRIVATE KEY-----"
|
||||
#define PEM_PKCS8_ENCRYPTED_FOOTER "-----END ENCRYPTED PRIVATE KEY-----"
|
||||
|
||||
static gchar *
|
||||
parse_private_key (const gchar *data,
|
||||
@ -231,45 +230,47 @@ parse_private_key (const gchar *data,
|
||||
gboolean required,
|
||||
GError **error)
|
||||
{
|
||||
const gchar *start, *end, *footer;
|
||||
const gchar *header_start = NULL, *header_end, *footer_start = NULL, *footer_end;
|
||||
|
||||
start = g_strstr_len (data, data_len, PEM_PKCS1_PRIVKEY_HEADER);
|
||||
if (start)
|
||||
footer = PEM_PKCS1_PRIVKEY_FOOTER;
|
||||
else
|
||||
header_end = g_strstr_len (data, data_len, PEM_PRIVKEY_HEADER_END);
|
||||
if (header_end)
|
||||
header_start = g_strrstr_len (data, header_end - data, PEM_PRIVKEY_HEADER_BEGIN);
|
||||
|
||||
if (!header_start)
|
||||
{
|
||||
start = g_strstr_len (data, data_len, PEM_PKCS8_PRIVKEY_HEADER);
|
||||
if (start)
|
||||
footer = PEM_PKCS8_PRIVKEY_FOOTER;
|
||||
else
|
||||
{
|
||||
start = g_strstr_len (data, data_len, PEM_PKCS8_ENCRYPTED_HEADER);
|
||||
if (start)
|
||||
if (required)
|
||||
g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
|
||||
_("No PEM-encoded private key found"));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
header_end += strlen (PEM_PRIVKEY_HEADER_END);
|
||||
|
||||
if (strncmp (header_start, PEM_PKCS8_ENCRYPTED_HEADER, header_end - header_start) == 0)
|
||||
{
|
||||
g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
|
||||
_("Cannot decrypt PEM-encoded private key"));
|
||||
}
|
||||
else if (required)
|
||||
{
|
||||
g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
|
||||
_("No PEM-encoded private key found"));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
end = g_strstr_len (start, data_len - (start - data), footer);
|
||||
if (!end)
|
||||
footer_end = g_strstr_len (header_end, data_len - (header_end - data), PEM_PRIVKEY_FOOTER_END);
|
||||
if (footer_end)
|
||||
footer_start = g_strrstr_len (header_end, footer_end - header_end, PEM_PRIVKEY_FOOTER_BEGIN);
|
||||
|
||||
if (!footer_start)
|
||||
{
|
||||
g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
|
||||
_("Could not parse PEM-encoded private key"));
|
||||
return NULL;
|
||||
}
|
||||
end += strlen (footer);
|
||||
while (*end == '\r' || *end == '\n')
|
||||
end++;
|
||||
|
||||
return g_strndup (start, end - start);
|
||||
footer_end += strlen (PEM_PRIVKEY_FOOTER_END);
|
||||
|
||||
while (*footer_end == '\r' || *footer_end == '\n')
|
||||
footer_end++;
|
||||
|
||||
return g_strndup (header_start, footer_end - header_start);
|
||||
}
|
||||
|
||||
|
||||
|
@ -232,9 +232,12 @@ cert_tests = \
|
||||
cert-key.pem \
|
||||
cert-list.pem \
|
||||
key8.pem \
|
||||
key8enc.pem \
|
||||
key-cert.pem \
|
||||
key.pem \
|
||||
key-crlf.pem \
|
||||
key_missing-footer.pem \
|
||||
key_missing-header.pem \
|
||||
nothing.pem \
|
||||
$(NULL)
|
||||
|
||||
|
18
gio/tests/cert-tests/key8enc.pem
Normal file
18
gio/tests/cert-tests/key8enc.pem
Normal file
@ -0,0 +1,18 @@
|
||||
-----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||
MIIC3TBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIdjDoEOJTH2ICAggA
|
||||
MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBDNLC2sDVjClaQyT8BfXTt1BIIC
|
||||
gCN4s9Z5bmfKogL7YHIJly2zLX5uILHeCr3iQpoPS8057V9Af1wqB/8AUOJrLY96
|
||||
R2amkXjlxuqA0BebEk4gcR4tWvCNQ2VCOqvQozUt8LnA+2xQRgzNwaW0HPxcAUzf
|
||||
6GVZKL7xfpwFD2ootfLwTHB2zAIVMo8nwgEzdDz93ZwsMmXJmOfSO7vpDQUnVqUX
|
||||
jVlue0i8n7fO4ClQ8fz5J8zyvPj403bR9qxsIJjQZACNVLMIksQXjTDngymy/ziI
|
||||
lZD4JDLXCQwAOgFz6N6vsyD/mHROyL4/4q8ujYFPmVpuAlQzuZJe6TFnmZHiSfoI
|
||||
we6wi1Nee1rbM4VzsGFzMa4Fr0ZhElHEKBXXje4YKWCAOWEo3tLjow4+0dQxNx5W
|
||||
tsbQdRt2fRYNYTgt18O55kq3DVfy93aMQVYIMuXkxwAuCWBeiLQrCfAM5r7kDwfc
|
||||
owp2AQ5Ndf+aAwr89k2fYUpexz9kZzU+eIY2K1cRhpUlLRAr5SG2oVy7n9IvYs1m
|
||||
O7/hjVBvXeAPDADVOtx/YNxPYr9ZI1X2QNDYGxNuSUNF1qGps66Gj+fcRe2NO+Ej
|
||||
YfSyfBvw+0h8sad81ZPepCSpIkYX91p6lCdCmRnJWYBwYyn6V5tXOx6tn5ntKJZ9
|
||||
9OtTGr7CMm7PLs9S8b03MV9IDJH+TBqR7msP1KWZbTxCNOws28EXo75tQ51ywElF
|
||||
FJI6ZU2gBYaX39i8WyvEMXFRRqzYUMzV0Yw2KeVRiGLh0ZX/4rlh2PQqVXGyakvn
|
||||
XttDRKEYPEvXDSRpO+tIvESlq9T0Pfo/rpnD4xJd2JWO6z/CSrn8cujs80e1+YjT
|
||||
HXksoJzsoLGeiYG2DzTK9lY=
|
||||
-----END ENCRYPTED PRIVATE KEY-----
|
14
gio/tests/cert-tests/key_missing-footer.pem
Normal file
14
gio/tests/cert-tests/key_missing-footer.pem
Normal file
@ -0,0 +1,14 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXQIBAAKBgQCslrTl+gp3lQsEGMegjhQMow5yhinpQ7yji36soGuUpUynQPs7
|
||||
P5tm3ojZPeQGNmYof3Csc2yTrMLrCidt8xFkcgtZydOJ9sQSEgwc2of4nlvffIZb
|
||||
dIR+13WOPVRmS5tBVkQWFrlSFtQ70BDhNK3SZfkAb4+QmLSR1MJFaUPWrQIDAQAB
|
||||
AoGAUTnskYAIhRdEQ/1Vlp7HmNr05bl26C3VDjOMvroRZ7gUR3MxykS5YsTBK10R
|
||||
gEsB8XVpFgCMzUO1yODShdCsEg9kCB3fzSWkunK8+TF2TKOM5uWlQwifKJvcNisR
|
||||
Nbg3r8WygMMXaWSFA3xWoRuZ5It0jOX18v+x5RHHon/kaRECQQDl6FSwgJLeNAkR
|
||||
pMNQGdRhmMesHWmNNBv3Wozqm6Wpkwo5ZXPsLt3pprd0GN5jX0IG7clT1/eMD9/G
|
||||
+3UGqTj3AkEAwC0M2gv+QUhbaB+KSlOZDOi4gsnhnsnaM7HQGDJJ5no4y2EvnYI3
|
||||
Y5rPJWedeYlCV3ccMitjnjcIJHInRZBIewJBANgsamVDn9Ua7GQQni1U/COAek7V
|
||||
oQfKNXmRROrbyxr1TSnGwQcU0kf+IIUjVQfu67CEKUeSzAqAapM4oULQHuUCQQC9
|
||||
J9qdiO6DXXAzRdA9pplgHnT2rzV3sSEoft3f4yfgRu8+KHPQqkpQrSE1pQ5YgWUe
|
||||
aGwFabXNFkfab839562fAkBl8jPidQdKWEgSa6h5pm4++sXLdWl7p6jiyetH64W7
|
||||
HnhRryE3ptrRGO0hSV1v4bx3DKzeJiJRlWUWiSl7828t
|
14
gio/tests/cert-tests/key_missing-header.pem
Normal file
14
gio/tests/cert-tests/key_missing-header.pem
Normal file
@ -0,0 +1,14 @@
|
||||
MIICXQIBAAKBgQCslrTl+gp3lQsEGMegjhQMow5yhinpQ7yji36soGuUpUynQPs7
|
||||
P5tm3ojZPeQGNmYof3Csc2yTrMLrCidt8xFkcgtZydOJ9sQSEgwc2of4nlvffIZb
|
||||
dIR+13WOPVRmS5tBVkQWFrlSFtQ70BDhNK3SZfkAb4+QmLSR1MJFaUPWrQIDAQAB
|
||||
AoGAUTnskYAIhRdEQ/1Vlp7HmNr05bl26C3VDjOMvroRZ7gUR3MxykS5YsTBK10R
|
||||
gEsB8XVpFgCMzUO1yODShdCsEg9kCB3fzSWkunK8+TF2TKOM5uWlQwifKJvcNisR
|
||||
Nbg3r8WygMMXaWSFA3xWoRuZ5It0jOX18v+x5RHHon/kaRECQQDl6FSwgJLeNAkR
|
||||
pMNQGdRhmMesHWmNNBv3Wozqm6Wpkwo5ZXPsLt3pprd0GN5jX0IG7clT1/eMD9/G
|
||||
+3UGqTj3AkEAwC0M2gv+QUhbaB+KSlOZDOi4gsnhnsnaM7HQGDJJ5no4y2EvnYI3
|
||||
Y5rPJWedeYlCV3ccMitjnjcIJHInRZBIewJBANgsamVDn9Ua7GQQni1U/COAek7V
|
||||
oQfKNXmRROrbyxr1TSnGwQcU0kf+IIUjVQfu67CEKUeSzAqAapM4oULQHuUCQQC9
|
||||
J9qdiO6DXXAzRdA9pplgHnT2rzV3sSEoft3f4yfgRu8+KHPQqkpQrSE1pQ5YgWUe
|
||||
aGwFabXNFkfab839562fAkBl8jPidQdKWEgSa6h5pm4++sXLdWl7p6jiyetH64W7
|
||||
HnhRryE3ptrRGO0hSV1v4bx3DKzeJiJRlWUWiSl7828t
|
||||
-----END RSA PRIVATE KEY-----
|
@ -260,6 +260,22 @@ from_files (const Reference *ref)
|
||||
g_clear_error (&error);
|
||||
g_assert_null (cert);
|
||||
|
||||
/* Missing header private key */
|
||||
cert = g_tls_certificate_new_from_files (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert1.pem", NULL),
|
||||
g_test_get_filename (G_TEST_DIST, "cert-tests", "key_missing-header.pem", NULL),
|
||||
&error);
|
||||
g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE);
|
||||
g_clear_error (&error);
|
||||
g_assert_null (cert);
|
||||
|
||||
/* Missing footer private key */
|
||||
cert = g_tls_certificate_new_from_files (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert1.pem", NULL),
|
||||
g_test_get_filename (G_TEST_DIST, "cert-tests", "key_missing-footer.pem", NULL),
|
||||
&error);
|
||||
g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE);
|
||||
g_clear_error (&error);
|
||||
g_assert_null (cert);
|
||||
|
||||
/* Missing certificate */
|
||||
cert = g_tls_certificate_new_from_files (g_test_get_filename (G_TEST_DIST, "cert-tests", "key.pem", NULL),
|
||||
g_test_get_filename (G_TEST_DIST, "cert-tests", "key.pem", NULL),
|
||||
@ -333,6 +349,21 @@ from_files_pkcs8 (const Reference *ref)
|
||||
g_object_unref (cert);
|
||||
}
|
||||
|
||||
static void
|
||||
from_files_pkcs8enc (const Reference *ref)
|
||||
{
|
||||
GTlsCertificate *cert;
|
||||
GError *error = NULL;
|
||||
|
||||
/* Mare sure an error is returned for encrypted key */
|
||||
cert = g_tls_certificate_new_from_files (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert1.pem", NULL),
|
||||
g_test_get_filename (G_TEST_DIST, "cert-tests", "key8enc.pem", NULL),
|
||||
&error);
|
||||
g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE);
|
||||
g_clear_error (&error);
|
||||
g_assert_null (cert);
|
||||
}
|
||||
|
||||
static void
|
||||
list_from_file (const Reference *ref)
|
||||
{
|
||||
@ -429,6 +460,8 @@ main (int argc,
|
||||
&ref, (GTestDataFunc)from_files_crlf);
|
||||
g_test_add_data_func ("/tls-certificate/from_files_pkcs8",
|
||||
&ref, (GTestDataFunc)from_files_pkcs8);
|
||||
g_test_add_data_func ("/tls-certificate/from_files_pkcs8enc",
|
||||
&ref, (GTestDataFunc)from_files_pkcs8enc);
|
||||
g_test_add_data_func ("/tls-certificate/list_from_file",
|
||||
&ref, (GTestDataFunc)list_from_file);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user