mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-18 20:49:28 +00:00
Harvest 176 isolated vuln-vs-fix functions (109 CVEs, 352 training rows) into benchmarks/pairs/vfc with provenance and a JSONL training manifest. Score the slice as an honesty dashboard (ousast pairs --slice vfc); keep the pair gate on the local fixtures only.
277 lines
11 KiB
C
277 lines
11 KiB
C
/* 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;
|
|
}
|