Skip to content

Use ASN1_STRING functions for OpenSSL 4.0 compat#5841

Open
antoniotorresm wants to merge 1 commit into
FreeRADIUS:v3.2.xfrom
antoniotorresm:openssl4
Open

Use ASN1_STRING functions for OpenSSL 4.0 compat#5841
antoniotorresm wants to merge 1 commit into
FreeRADIUS:v3.2.xfrom
antoniotorresm:openssl4

Conversation

@antoniotorresm
Copy link
Copy Markdown

Use ASN1_STRING accessor functions instead of direct field access for ASN1_IA5STRING, ASN1_INTEGER, and ASN1_TIME structures.

This fixes compatibility with OpenSSL 4.0.

Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@arr2036
Copy link
Copy Markdown
Member

arr2036 commented May 5, 2026

@claude review. Are these accessors available in previous versions? Have you verified they're available on the minimum version we support.

@claude
Copy link
Copy Markdown

claude Bot commented May 5, 2026

Claude finished @arr2036's task in 1m 58s —— View job


Claude Code Review

  • Gathering context and reading changed files
  • Check minimum supported OpenSSL version for this project
  • Identify the ASN1_STRING accessor functions used in the PR
  • Research when these accessors were introduced in OpenSSL
  • Provide review feedback

Review: OpenSSL Accessor Availability

The short answer is: ASN1_STRING_get0_data() is NOT available in the project's stated minimum OpenSSL version.

Minimum supported version

configure.ac checks for OPENSSL_VERSION_NUMBER >= 0x10002000L (OpenSSL 1.0.2) and fails if the version is older.

Functions used in this PR

Function Introduced in Available at min (1.0.2)?
ASN1_STRING_get0_data() OpenSSL 1.1.0 (0x10100000L) No
ASN1_STRING_length() OpenSSL 0.9.x (old macro) Yes

ASN1_STRING_get0_data() was added in OpenSSL 1.1.0 as the non-deprecated accessor that returns const unsigned char *. The old API was ASN1_STRING_data() (returns a non-const pointer). On OpenSSL 1.0.x, ASN1_STRING_get0_data does not exist and the build will fail.

Pre-existing issue in the base branch

The base branch (v3.2.x) already uses ASN1_STRING_get0_data in several places without version guards:

  • src/main/tls.c:2923get_cdp_url()
  • src/main/tls.c:3178,3185,3196,3209 — SAN processing in cbtls_verify()

This suggests the effective minimum may have already drifted to OpenSSL 1.1.0, even though the configure check still permits 1.0.2. It's worth clarifying whether support for 1.0.x is still a goal.

The existing correct pattern (already in the file)

The file at src/main/tls.c:3300–3308 already demonstrates the right approach:

#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
    const ASN1_STRING *srcasn1p = X509_EXTENSION_get_data(ext);
    srcp = ASN1_STRING_get0_data(srcasn1p);
#else
    ASN1_STRING *srcasn1p = X509_EXTENSION_get_data(ext);
    srcp = ASN1_STRING_data(srcasn1p);
#endif

If 1.0.x support must be preserved, this PR's new uses of ASN1_STRING_get0_data (at tls.c:2571, 3057, 3075, 3090) need the same treatment. For the ASN1_IA5STRING case, the fallback would be (char *) ad->location->d.ia5->data; for ASN1_INTEGER and ASN1_TIME, sn->data / asn_time->data.

Bottom line

  • If the project's real minimum is now 1.1.0: these calls are fine, the configure check should be updated to reflect reality, and the pre-existing unguarded usages are also fine.
  • If 1.0.2 must still compile: the new ASN1_STRING_get0_data calls need #if guards matching the pattern at line 3300, and the pre-existing unguarded calls should be fixed too.

Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, both accessors are safe on supported versions: ASN1_STRING_length has existed since OpenSSL 0.9.x, and ASN1_STRING_get0_data is covered by the existing fallback shim in src/include/missing-h (lines 464-480, gated on HAVE_ASN1_STRING_GET0_DATA from configure). The same pattern is already used elsewhere in tls.c (e.g. lines 2923, 3178, 3185, 3196, 3209, 3303), so this PR is consistent with existing code. Deferring final approval to you since you asked for verification.

Extended reasoning...

Overview

The PR replaces three sets of direct field accesses on ASN1_IA5STRING / ASN1_INTEGER / ASN1_TIME (->data, ->length) with the accessor functions ASN1_STRING_get0_data() and ASN1_STRING_length() in src/main/tls.c. This is needed because OpenSSL 4.0 makes the underlying ASN1_STRING struct opaque, so direct member access stops compiling.

Security risks

None. This is a pure refactor — no behavioral changes, no new allocations, no input validation changes. The new locals (sn_len, sn_data, time_len, time_data) just hoist the accessor calls; the bounds checks against sizeof(buf) are preserved correctly.

Level of scrutiny

Low scrutiny on the code change itself — it's a one-for-one mechanical translation. The only real question is the one the reviewer raised: backward compatibility on the minimum supported OpenSSL.

  • ASN1_STRING_length() has been part of OpenSSL since 0.9.x — universally available.
  • ASN1_STRING_get0_data() was introduced in OpenSSL 1.1.0, but the project already ships a static-inline fallback in src/include/missing-h (gated on HAVE_ASN1_STRING_GET0_DATA, set by configure). That shim wraps ASN1_STRING_data() and is already relied upon by ~6 other call sites in this same file (2923, 3178, 3185, 3196, 3209, 3303).

Other factors

The maintainer (arr2036) explicitly asked for version verification rather than just rubber-stamping. Since they engaged directly and asked a specific question, I'm deferring the final approve to them rather than approving over the open question. Once they're satisfied with the answer, this is a trivial merge.

@arr2036
Copy link
Copy Markdown
Member

arr2036 commented May 5, 2026

@claude what's up with the CI failures?

@claude
Copy link
Copy Markdown

claude Bot commented May 5, 2026

Claude finished @arr2036's task in 1m 44s —— View job


CI Failure Analysis

  • Fetch CI status
  • Identify failing jobs
  • Analyze failure logs

8 jobs fail, all at "Build FreeRADIUS" with -Werror=cast-qual errors in src/main/tls.c. The build is configured with -Werror, so these warnings become errors. The root cause: ASN1_STRING_get0_data() correctly returns const unsigned char *, but the PR's new code casts it to non-const char *, dropping the const qualifier.

Three specific errors:

tls.c:2571: error: cast discards 'const' qualifier [-Werror=cast-qual]
  OCSP_parse_url((char *) ASN1_STRING_get0_data(ad->location->d.ia5), ...)
  → fix: (const char *)

tls.c:3076: error: same
  memcpy(buf, (char*) time_data, time_len)
  → fix: remove cast entirely (memcpy takes const void* as src)

tls.c:3091: same as 3076

Note: Two lean builds (linux-clang-lean, linux-gcc-lean) pass because they compile without TLS support.

I've prepared a fix commit locally, but I can't push to this fork's branch directly (the GitHub App doesn't have write access to forks). The needed changes are:

- if (OCSP_parse_url((char *) ASN1_STRING_get0_data(ad->location->d.ia5), host_out,
+ if (OCSP_parse_url((const char *) ASN1_STRING_get0_data(ad->location->d.ia5), host_out,

- memcpy(buf, (char*) time_data, time_len);   // two occurrences
+ memcpy(buf, time_data, time_len);

Fix this →%20At%20line%202571%2C%20change%20%22(char%20*)%22%20to%20%22(const%20char%20*)%22%20in%20the%20OCSP_parse_url%20call%3B%202)%20At%20lines%203076%20and%203091%2C%20remove%20the%20%22(char*)%22%20cast%20from%20the%20two%20memcpy(buf%2C%20(char*)%20time_data%2C%20time_len)%20calls%20since%20memcpy%27s%20src%20is%20already%20const%20void*.&repo=FreeRADIUS/freeradius-server)

View CI run |

@arr2036
Copy link
Copy Markdown
Member

arr2036 commented May 5, 2026

@claude those seem simple enough, can you fix the const issues. If it goes beyond simple casting and typing, can you come back and ask what the fix is.

@claude
Copy link
Copy Markdown

claude Bot commented May 5, 2026

Claude finished @arr2036's task in 51s —— View job


Const cast fixes

  • Identify the three const cast errors from CI
  • Apply fixes to src/main/tls.c
  • Commit locally
  • Push to branch — blocked (GitHub App lacks write access to this fork)

The three fixes are straightforward — here's the diff:

-		if (OCSP_parse_url((char *) ASN1_STRING_get0_data(ad->location->d.ia5), host_out,
+		if (OCSP_parse_url((const char *) ASN1_STRING_get0_data(ad->location->d.ia5), host_out,

-		memcpy(buf, (char*) time_data, time_len);  // line ~3076 (notAfter)
+		memcpy(buf, time_data, time_len);

-		memcpy(buf, (char*) time_data, time_len);  // line ~3091 (notBefore)
+		memcpy(buf, time_data, time_len);

OCSP_parse_url takes const char * so the cast just needs the const qualifier. memcpy's source parameter is const void * so no cast is needed at all — dropping it is cleaner.

Unfortunately I can't push directly to this fork's branch. You (or the PR author) will need to apply these three changes manually.

@arr2036
Copy link
Copy Markdown
Member

arr2036 commented May 5, 2026

@antoniotorresm can you fix the const issues and then we can merge.

Use ASN1_STRING accessor functions instead of direct field access
for ASN1_IA5STRING, ASN1_INTEGER, and ASN1_TIME structures.

This fixes compatibility with OpenSSL 4.0.

Signed-off-by: Antonio Torres <antorres@redhat.com>
@antoniotorresm
Copy link
Copy Markdown
Author

Done.

@arr2036 arr2036 force-pushed the v3.2.x branch 2 times, most recently from 1817b50 to fdf4d93 Compare May 16, 2026 16:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants