summaryrefslogtreecommitdiff
path: root/lib/priority.c
diff options
context:
space:
mode:
authorTom Vrancken <dev@tomvrancken.nl>2018-08-15 18:29:32 +0200
committerTom Vrancken <dev@tomvrancken.nl>2018-08-20 17:08:01 +0200
commit07180a416731749883234f931ac18831ff38abbb (patch)
tree0b9d13b9ad394477d566f01ba8e279c33711cc7c /lib/priority.c
parenta42db538c3f01aa76e2c1a2affc39237840c2522 (diff)
downloadgnutls-07180a416731749883234f931ac18831ff38abbb.tar.gz
Implemented RFC7250 certificate type negotiation extensions.
Signed-off-by: Tom Vrancken <dev@tomvrancken.nl>
Diffstat (limited to 'lib/priority.c')
-rw-r--r--lib/priority.c100
1 files changed, 92 insertions, 8 deletions
diff --git a/lib/priority.c b/lib/priority.c
index 1d495d0e67..00681c53e8 100644
--- a/lib/priority.c
+++ b/lib/priority.c
@@ -517,6 +517,12 @@ static const int cert_type_priority_default[] = {
0
};
+static const int cert_type_priority_all[] = {
+ GNUTLS_CRT_X509,
+ GNUTLS_CRT_RAWPK,
+ 0
+};
+
typedef void (rmadd_func) (priority_st * priority_list, unsigned int alg);
static void prio_remove(priority_st * priority_list, unsigned int algo)
@@ -1621,7 +1627,9 @@ gnutls_priority_init(gnutls_priority_t * priority_cache,
if (strcasecmp(broken_list[0], LEVEL_NONE) != 0) {
_set_priority(&(*priority_cache)->protocol,
protocol_priority);
- _set_priority(&(*priority_cache)->cert_type,
+ _set_priority(&(*priority_cache)->client_ctype,
+ cert_type_priority_default);
+ _set_priority(&(*priority_cache)->server_ctype,
cert_type_priority_default);
_set_priority(&(*priority_cache)->_sign_algo,
sign_priority_default);
@@ -1755,8 +1763,39 @@ gnutls_priority_init(gnutls_priority_t * priority_cache,
goto error;
}
} else if (strncasecmp
- (&broken_list[i][1], "CTYPE-", 6) == 0) {
- continue;
+ (&broken_list[i][1], "CTYPE-", 6) == 0) { // Certificate types
+ if (strncasecmp(&broken_list[i][1], "CTYPE-ALL", 9) == 0)
+ { // Symmetric cert types, all types allowed
+ bulk_fn(&(*priority_cache)->client_ctype, cert_type_priority_all);
+ bulk_fn(&(*priority_cache)->server_ctype, cert_type_priority_all);
+ } else if (strncasecmp(&broken_list[i][1], "CTYPE-CLI-", 10) == 0)
+ { // Client certificate types
+ if (strncasecmp(&broken_list[i][1], "CTYPE-CLI-ALL", 13) == 0)
+ { // All client cert types allowed
+ bulk_fn(&(*priority_cache)->client_ctype, cert_type_priority_all);
+ } else if ((algo = gnutls_certificate_type_get_id
+ (&broken_list[i][11])) != GNUTLS_CRT_UNKNOWN)
+ { // Specific client cert type allowed
+ fn(&(*priority_cache)->client_ctype, algo);
+ } else goto error;
+ } else if (strncasecmp(&broken_list[i][1], "CTYPE-SRV-", 10) == 0)
+ { // Server certificate types
+ if (strncasecmp(&broken_list[i][1], "CTYPE-SRV-ALL", 13) == 0)
+ { // All server cert types allowed
+ bulk_fn(&(*priority_cache)->server_ctype, cert_type_priority_all);
+ } else if ((algo = gnutls_certificate_type_get_id
+ (&broken_list[i][11])) != GNUTLS_CRT_UNKNOWN)
+ { // Specific server cert type allowed
+ fn(&(*priority_cache)->server_ctype, algo);
+ } else goto error;
+ } else { // Symmetric certificate type
+ if ((algo = gnutls_certificate_type_get_id
+ (&broken_list[i][7])) != GNUTLS_CRT_UNKNOWN)
+ {
+ fn(&(*priority_cache)->client_ctype, algo);
+ fn(&(*priority_cache)->server_ctype, algo);
+ } else goto error;
+ }
} else if (strncasecmp
(&broken_list[i][1], "SIGN-", 5) == 0) {
if (strncasecmp
@@ -2207,7 +2246,13 @@ gnutls_priority_sign_list(gnutls_priority_t pcache,
* @list: will point to an integer list
*
* Get a list of available certificate types in the priority
- * structure.
+ * structure.
+ *
+ * As of version 3.6.4 this function is an alias for
+ * gnutls_priority_certificate_type_list2 with the target parameter
+ * set to:
+ * - GNUTLS_CTYPE_SERVER, if the %SERVER_PRECEDENCE option is set
+ * - GNUTLS_CTYPE_CLIENT, otherwise.
*
* Returns: the number of certificate types, or an error code.
* Since: 3.0
@@ -2216,11 +2261,50 @@ int
gnutls_priority_certificate_type_list(gnutls_priority_t pcache,
const unsigned int **list)
{
- if (pcache->cert_type.algorithms == 0)
- return 0;
+ gnutls_ctype_target_t target =
+ pcache->server_precedence ? GNUTLS_CTYPE_SERVER : GNUTLS_CTYPE_CLIENT;
- *list = pcache->cert_type.priority;
- return pcache->cert_type.algorithms;
+ return gnutls_priority_certificate_type_list2(pcache, list, target);
+}
+
+/**
+ * gnutls_priority_certificate_type_list2:
+ * @pcache: is a #gnutls_prioritity_t type.
+ * @list: will point to an integer list.
+ * @target: is a #gnutls_ctype_target_t type. Valid arguments are
+ * GNUTLS_CTYPE_CLIENT and GNUTLS_CTYPE_SERVER
+ *
+ * Get a list of available certificate types for the given target
+ * in the priority structure.
+ *
+ * Returns: the number of certificate types, or an error code.
+ *
+ * Since: 3.6.4
+ **/
+int
+gnutls_priority_certificate_type_list2(gnutls_priority_t pcache,
+ const unsigned int **list, gnutls_ctype_target_t target)
+{
+ switch (target) {
+ case GNUTLS_CTYPE_CLIENT:
+ if(pcache->client_ctype.algorithms > 0) {
+ *list = pcache->client_ctype.priority;
+ return pcache->client_ctype.algorithms;
+ }
+ break;
+ case GNUTLS_CTYPE_SERVER:
+ if(pcache->server_ctype.algorithms > 0) {
+ *list = pcache->server_ctype.priority;
+ return pcache->server_ctype.algorithms;
+ }
+ break;
+ default:
+ // Invalid target given
+ gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ }
+
+ // Found a matching target but non of them had any ctypes set
+ return 0;
}
/**