Files
Open_Ultra_SAST/benchmarks/pairs/vfc/openssl-cve-2026-2673/fixed.c
T

277 lines
11 KiB
C
Raw Normal View History

/* Provenance: openssl/openssl gid_cb (fixed).
* repo: openssl/openssl
* commit: 85977e013f32ceb96aa034c0e741adddc1a05e34
* parent: 21d525dc846aed171fc886f3da614a6645948f13
* commit_url: https://github.com/openssl/openssl/commit/85977e013f32ceb96aa034c0e741adddc1a05e34
* cve: CVE-2026-2673
* license: Apache-2.0
* function: gid_cb
* relpath: ssl/t1_lib.c
*/
static int gid_cb(const char *elem, int len, void *arg)
{
gid_cb_st *garg = arg;
size_t i, j, k;
uint16_t gid = 0;
int found_group = 0;
char etmp[GROUP_NAME_BUFFER_LENGTH];
int retval = 1; /* We assume success */
const char *current_prefix;
int ignore_unknown = 0;
int add_keyshare = 0;
int remove_group = 0;
size_t restored_prefix_index = 0;
char *restored_default_group_string;
int continue_while_loop = 1;
/* Sanity checks */
if (garg == NULL || elem == NULL || len <= 0) {
ERR_raise(ERR_LIB_SSL, SSL_R_UNSUPPORTED_CONFIG_VALUE);
return 0;
}
/* Check the possible prefixes (remark: Leading and trailing spaces already cleared) */
while (continue_while_loop && len > 0
&& ((current_prefix = strchr(prefixes, elem[0])) != NULL
|| OPENSSL_strncasecmp(current_prefix = (char *)DEFAULT_GROUPNAME_FIRST_CHARACTER, elem, 1) == 0)) {
switch (*current_prefix) {
case TUPLE_DELIMITER_CHARACTER:
/* tuple delimiter not allowed here -> syntax error */
return -1;
break;
case GROUP_DELIMITER_CHARACTER:
return -1; /* Not a valid prefix for a single group name-> syntax error */
break;
case KEY_SHARE_INDICATOR_CHARACTER:
if (add_keyshare)
return -1; /* Only single key share prefix allowed -> syntax error */
add_keyshare = 1;
++elem;
--len;
break;
case REMOVE_GROUP_INDICATOR_CHARACTER:
if (remove_group)
return -1; /* Only single remove group prefix allowed -> syntax error */
remove_group = 1;
++elem;
--len;
break;
case IGNORE_UNKNOWN_GROUP_CHARACTER:
if (ignore_unknown)
return -1; /* Only single ? allowed -> syntax error */
ignore_unknown = 1;
++elem;
--len;
break;
default:
/*
* Check whether a DEFAULT[_XYZ] 'pseudo group' (= a built-in
* list of groups) should be added
*/
for (i = 0; i < OSSL_NELEM(default_group_strings); i++) {
if ((size_t)len == (strlen(default_group_strings[i].list_name))
&& OPENSSL_strncasecmp(default_group_strings[i].list_name, elem, len) == 0) {
int saved_first;
/*
* We're asked to insert an entire list of groups from a
* DEFAULT[_XYZ] 'pseudo group' which we do by
* recursively calling this function (indirectly via
* CONF_parse_list and tuple_cb); essentially, we treat a DEFAULT
* group string like a tuple which is appended to the current tuple
* rather then starting a new tuple.
*/
if (ignore_unknown || remove_group)
return -1; /* removal or ignore not allowed here -> syntax error */
/*
* First, we restore any keyshare prefix in a new zero-terminated string
* (if not already present)
*/
restored_default_group_string = OPENSSL_malloc((1 /* max prefix length */ + strlen(default_group_strings[i].group_string) + 1 /* \0 */) * sizeof(char));
if (restored_default_group_string == NULL)
return 0;
if (add_keyshare
/* Remark: we tolerate a duplicated keyshare indicator here */
&& default_group_strings[i].group_string[0]
!= KEY_SHARE_INDICATOR_CHARACTER)
restored_default_group_string[restored_prefix_index++] = KEY_SHARE_INDICATOR_CHARACTER;
memcpy(restored_default_group_string + restored_prefix_index,
default_group_strings[i].group_string,
strlen(default_group_strings[i].group_string));
restored_default_group_string[strlen(default_group_strings[i].group_string) + restored_prefix_index] = '\0';
/*
* Append first tuple of result to current tuple, and don't
* terminate the last tuple until we return to a top-level
* tuple_cb.
*/
saved_first = garg->first;
garg->inner = garg->first = 1;
retval = CONF_parse_list(restored_default_group_string,
TUPLE_DELIMITER_CHARACTER, 1, tuple_cb, garg);
garg->inner = 0;
garg->first = saved_first;
/* We don't need the \0-terminated string anymore */
OPENSSL_free(restored_default_group_string);
return retval;
}
}
/*
* If we reached this point, a group name started with a 'd' or 'D', but no request
* for a DEFAULT[_XYZ] 'pseudo group' was detected, hence processing of the group
* name can continue as usual (= the while loop checking prefixes can end)
*/
continue_while_loop = 0;
break;
}
}
if (len == 0)
return -1; /* Seems we have prefxes without a group name -> syntax error */
/* Memory management in case more groups are present compared to initial allocation */
if (garg->gidcnt == garg->gidmax) {
uint16_t *tmp = OPENSSL_realloc(garg->gid_arr,
(garg->gidmax + GROUPLIST_INCREMENT) * sizeof(*garg->gid_arr));
if (tmp == NULL)
return 0;
garg->gidmax += GROUPLIST_INCREMENT;
garg->gid_arr = tmp;
}
/* Memory management for key share groups */
if (garg->ksidcnt == garg->ksidmax) {
uint16_t *tmp = OPENSSL_realloc(garg->ksid_arr,
(garg->ksidmax + GROUPLIST_INCREMENT) * sizeof(*garg->ksid_arr));
if (tmp == NULL)
return 0;
garg->ksidmax += GROUPLIST_INCREMENT;
garg->ksid_arr = tmp;
}
if (len > (int)(sizeof(etmp) - 1))
return -1; /* group name to long -> syntax error */
/*
* Prepare addition or removal of a single group by converting
* a group name into its groupID equivalent
*/
/* Create a \0-terminated string and get the gid for this group if possible */
memcpy(etmp, elem, len);
etmp[len] = 0;
/* Get the groupID */
gid = tls1_group_name2id(garg->ctx, etmp);
/*
* Handle the case where no valid groupID was returned
* e.g. for an unknown group, which we'd ignore (only) if relevant prefix was set
*/
if (gid == 0) {
/* Is it one of the GOST groups ? */
for (i = 0; i < OSSL_NELEM(name2id_arr); i++) {
if (OPENSSL_strcasecmp(etmp, name2id_arr[i].group_name) == 0) {
gid = name2id_arr[i].groupID;
break;
}
}
if (gid == 0) { /* still not found */
/* Unknown group - ignore if ignore_unknown; trigger error otherwise */
retval = ignore_unknown;
goto done;
}
}
/* Make sure that at least one provider is supporting this groupID */
found_group = 0;
for (j = 0; j < garg->ctx->group_list_len; j++)
if (garg->ctx->group_list[j].group_id == gid) {
found_group = 1;
break;
}
/*
* No provider supports this group - ignore if
* ignore_unknown; trigger error otherwise
*/
if (found_group == 0) {
retval = ignore_unknown;
goto done;
}
/* Remove group (and keyshare) from anywhere in the list if present, ignore if not present */
if (remove_group) {
/* Is the current group specified anywhere in the entire list so far? */
found_group = 0;
for (i = 0; i < garg->gidcnt; i++)
if (garg->gid_arr[i] == gid) {
found_group = 1;
break;
}
/* The group to remove is at position i in the list of (zero indexed) groups */
if (found_group) {
/* We remove that group from its position (which is at i)... */
for (j = i; j < (garg->gidcnt - 1); j++)
garg->gid_arr[j] = garg->gid_arr[j + 1]; /* ...shift remaining groups left ... */
garg->gidcnt--; /* ..and update the book keeping for the number of groups */
/*
* We also must update the number of groups either in a previous tuple (which we
* must identify and check whether it becomes empty due to the deletion) or in
* the current tuple, pending where the deleted group resides
*/
k = 0;
for (j = 0; j < garg->tplcnt; j++) {
k += garg->tuplcnt_arr[j];
/* Remark: i is zero-indexed, k is one-indexed */
if (k > i) { /* remove from one of the previous tuples */
garg->tuplcnt_arr[j]--;
break; /* We took care not to have group duplicates, hence we can stop here */
}
}
if (k <= i) /* remove from current tuple */
garg->tuplcnt_arr[j]--;
/* We also remove the group from the list of keyshares (if present) */
found_group = 0;
for (i = 0; i < garg->ksidcnt; i++)
if (garg->ksid_arr[i] == gid) {
found_group = 1;
break;
}
if (found_group) {
/* Found, hence we remove that keyshare from its position (which is at i)... */
for (j = i; j < (garg->ksidcnt - 1); j++)
garg->ksid_arr[j] = garg->ksid_arr[j + 1]; /* shift remaining key shares */
/* ... and update the book keeping */
garg->ksidcnt--;
}
}
} else { /* Processing addition of a single new group */
/* Check for duplicates */
for (i = 0; i < garg->gidcnt; i++)
if (garg->gid_arr[i] == gid) {
/* Duplicate group anywhere in the list of groups - ignore */
goto done;
}
/* Add the current group to the 'flat' list of groups */
garg->gid_arr[garg->gidcnt++] = gid;
/* and update the book keeping for the number of groups in current tuple */
garg->tuplcnt_arr[garg->tplcnt]++;
/* We want to add a key share for the current group */
if (add_keyshare)
garg->ksid_arr[garg->ksidcnt++] = gid;
}
done:
return retval;
}