Skip to content

Commit 2f86e78

Browse files
authored
Merge pull request #313 from cconlon/altName
Add WolfSSLAltName class for extended SAN parsing and MS AD UPN support
2 parents 07317be + 0322ba5 commit 2f86e78

27 files changed

Lines changed: 3631 additions & 21 deletions

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ jobs:
197197
matrix:
198198
os: [ 'ubuntu-latest' ]
199199
jdk_version: [ '21' ]
200-
wolfssl_configure: [ '--enable-jni' ]
200+
wolfssl_configure: [ '--enable-jni --enable-debug' ]
201201
name: AddressSanitizer (${{ matrix.os }} Zulu JDK ${{ matrix.jdk_version }})
202202
uses: ./.github/workflows/address-sanitizer.yml
203203
with:
Lines changed: 366 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,366 @@
1+
#!/bin/bash
2+
3+
# SAN Test Certificate Generation Script
4+
#
5+
# Copyright (C) 2006-2026 wolfSSL Inc.
6+
#
7+
# This script generates test certificates with various Subject Alternative Name
8+
# (SAN) types for testing WolfSSLAltName functionality.
9+
#
10+
# Script should be run from the <wolfssljni>/examples/certs directory.
11+
#
12+
# Generated certificates:
13+
# - san-test-ca-key.pem / san-test-ca-cert.pem: Self-signed CA
14+
# - san-test-all-types.pem: Certificate with all supported SAN types
15+
# - san-test-dns-ip.pem: Certificate with DNS and IP SANs
16+
# - san-test-email-uri.pem: Certificate with email and URI SANs
17+
# - san-test-othername-upn.pem: Certificate with Microsoft UPN otherName
18+
# - san-test-dirname-rid.pem: Certificate with directoryName and registeredID
19+
#
20+
# SAN Types (RFC 5280 GeneralName):
21+
# 0 = otherName (Microsoft UPN: OID 1.3.6.1.4.1.311.20.2.3)
22+
# 1 = rfc822Name (email)
23+
# 2 = dNSName
24+
# 4 = directoryName
25+
# 6 = uniformResourceIdentifier (URI)
26+
# 7 = iPAddress (IPv4 and IPv6)
27+
# 8 = registeredID
28+
29+
set -e
30+
31+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
32+
cd "$SCRIPT_DIR"
33+
34+
# Certificate validity (10 years)
35+
DAYS=3650
36+
37+
# Output directory for SAN test certs
38+
SAN_DIR="san-test"
39+
mkdir -p "$SAN_DIR"
40+
41+
printf "Generating SAN test certificates in %s/\n" "$SAN_DIR"
42+
43+
# =============================================================================
44+
# Generate CA key and self-signed certificate
45+
# =============================================================================
46+
printf "\n[1/7] Generating SAN test CA...\n"
47+
48+
openssl genrsa -out "$SAN_DIR/san-test-ca-key.pem" 2048
49+
50+
openssl req -x509 -new -nodes \
51+
-key "$SAN_DIR/san-test-ca-key.pem" \
52+
-sha256 -days $DAYS \
53+
-subj "/C=US/ST=Montana/L=Bozeman/O=wolfSSL/OU=Testing/CN=SAN Test CA" \
54+
-out "$SAN_DIR/san-test-ca-cert.pem"
55+
56+
printf " Created: san-test-ca-key.pem, san-test-ca-cert.pem\n"
57+
58+
# =============================================================================
59+
# Helper function to generate a certificate with SANs
60+
# =============================================================================
61+
generate_cert() {
62+
local name=$1
63+
local cn=$2
64+
local san_config=$3
65+
local extra_sections=$4
66+
67+
printf "\n[%s] Generating %s...\n" "$5" "$name"
68+
69+
# Generate key
70+
openssl genrsa -out "$SAN_DIR/${name}-key.pem" 2048
71+
72+
# Create CSR
73+
openssl req -new \
74+
-key "$SAN_DIR/${name}-key.pem" \
75+
-subj "/C=US/ST=Montana/L=Bozeman/O=wolfSSL/OU=Testing/CN=${cn}" \
76+
-out "$SAN_DIR/${name}.csr"
77+
78+
# Create extension config file
79+
cat > "$SAN_DIR/${name}-ext.cnf" << EOF
80+
[req]
81+
distinguished_name = req_distinguished_name
82+
83+
[req_distinguished_name]
84+
85+
[san_ext]
86+
subjectAltName = ${san_config}
87+
${extra_sections}
88+
EOF
89+
90+
# Sign with CA
91+
openssl x509 -req \
92+
-in "$SAN_DIR/${name}.csr" \
93+
-CA "$SAN_DIR/san-test-ca-cert.pem" \
94+
-CAkey "$SAN_DIR/san-test-ca-key.pem" \
95+
-CAcreateserial \
96+
-out "$SAN_DIR/${name}.pem" \
97+
-days $DAYS \
98+
-sha256 \
99+
-extfile "$SAN_DIR/${name}-ext.cnf" \
100+
-extensions san_ext
101+
102+
# Also create DER format
103+
openssl x509 -in "$SAN_DIR/${name}.pem" -outform DER -out "$SAN_DIR/${name}.der"
104+
105+
# Cleanup CSR and config
106+
rm -f "$SAN_DIR/${name}.csr" "$SAN_DIR/${name}-ext.cnf"
107+
108+
printf " Created: %s.pem, %s.der\n" "$name" "$name"
109+
}
110+
111+
# =============================================================================
112+
# Certificate 1: DNS and IP addresses (most common case)
113+
# =============================================================================
114+
generate_cert "san-test-dns-ip" "DNS and IP Test" \
115+
"DNS:localhost,DNS:example.com,DNS:*.wildcard.com,IP:127.0.0.1,IP:192.168.1.1,IP:::1,IP:fe80::1" \
116+
"" "2/7"
117+
118+
# =============================================================================
119+
# Certificate 2: Email and URI
120+
# =============================================================================
121+
generate_cert "san-test-email-uri" "Email and URI Test" \
122+
"email:test@example.com,email:admin@wolfssl.com,URI:https://www.wolfssl.com,URI:ldap://ldap.example.com/cn=test" \
123+
"" "3/7"
124+
125+
# =============================================================================
126+
# Certificate 3: Microsoft UPN otherName (for Active Directory)
127+
# Microsoft UPN OID: 1.3.6.1.4.1.311.20.2.3
128+
# =============================================================================
129+
printf "\n[4/7] Generating san-test-othername-upn...\n"
130+
131+
# Generate key
132+
openssl genrsa -out "$SAN_DIR/san-test-othername-upn-key.pem" 2048
133+
134+
# Create CSR
135+
openssl req -new \
136+
-key "$SAN_DIR/san-test-othername-upn-key.pem" \
137+
-subj "/C=US/ST=Montana/L=Bozeman/O=wolfSSL/OU=Testing/CN=UPN Test User" \
138+
-out "$SAN_DIR/san-test-othername-upn.csr"
139+
140+
# Create extension config with otherName for UPN
141+
# The format is: otherName:OID;encoding:value
142+
# For UPN, OID is 1.3.6.1.4.1.311.20.2.3 and value is UTF8String
143+
cat > "$SAN_DIR/san-test-othername-upn-ext.cnf" << 'EOF'
144+
[req]
145+
distinguished_name = req_distinguished_name
146+
147+
[req_distinguished_name]
148+
149+
[san_ext]
150+
subjectAltName = @san_names
151+
152+
[san_names]
153+
otherName.0 = 1.3.6.1.4.1.311.20.2.3;UTF8:testuser@example.com
154+
otherName.1 = 1.3.6.1.4.1.311.20.2.3;UTF8:admin@wolfssl.local
155+
email = testuser@example.com
156+
EOF
157+
158+
# Sign with CA
159+
openssl x509 -req \
160+
-in "$SAN_DIR/san-test-othername-upn.csr" \
161+
-CA "$SAN_DIR/san-test-ca-cert.pem" \
162+
-CAkey "$SAN_DIR/san-test-ca-key.pem" \
163+
-CAcreateserial \
164+
-out "$SAN_DIR/san-test-othername-upn.pem" \
165+
-days $DAYS \
166+
-sha256 \
167+
-extfile "$SAN_DIR/san-test-othername-upn-ext.cnf" \
168+
-extensions san_ext
169+
170+
# Also create DER format
171+
openssl x509 -in "$SAN_DIR/san-test-othername-upn.pem" -outform DER \
172+
-out "$SAN_DIR/san-test-othername-upn.der"
173+
174+
# Cleanup
175+
rm -f "$SAN_DIR/san-test-othername-upn.csr" "$SAN_DIR/san-test-othername-upn-ext.cnf"
176+
177+
printf " Created: san-test-othername-upn.pem, san-test-othername-upn.der\n"
178+
179+
# =============================================================================
180+
# Certificate 4: directoryName and registeredID
181+
# =============================================================================
182+
printf "\n[5/7] Generating san-test-dirname-rid...\n"
183+
184+
# Generate key
185+
openssl genrsa -out "$SAN_DIR/san-test-dirname-rid-key.pem" 2048
186+
187+
# Create CSR
188+
openssl req -new \
189+
-key "$SAN_DIR/san-test-dirname-rid-key.pem" \
190+
-subj "/C=US/ST=Montana/L=Bozeman/O=wolfSSL/OU=Testing/CN=DirName RID Test" \
191+
-out "$SAN_DIR/san-test-dirname-rid.csr"
192+
193+
# Create extension config with directoryName and registeredID
194+
cat > "$SAN_DIR/san-test-dirname-rid-ext.cnf" << 'EOF'
195+
[req]
196+
distinguished_name = req_distinguished_name
197+
198+
[req_distinguished_name]
199+
200+
[san_ext]
201+
subjectAltName = @san_names
202+
203+
[san_names]
204+
dirName.0 = dir_sect_1
205+
dirName.1 = dir_sect_2
206+
RID = 1.2.3.4.5.6.7.8.9
207+
208+
[dir_sect_1]
209+
C = US
210+
ST = California
211+
L = San Francisco
212+
O = Test Organization
213+
CN = Directory Name Test 1
214+
215+
[dir_sect_2]
216+
C = DE
217+
O = German Organization
218+
CN = Directory Name Test 2
219+
EOF
220+
221+
# Sign with CA
222+
openssl x509 -req \
223+
-in "$SAN_DIR/san-test-dirname-rid.csr" \
224+
-CA "$SAN_DIR/san-test-ca-cert.pem" \
225+
-CAkey "$SAN_DIR/san-test-ca-key.pem" \
226+
-CAcreateserial \
227+
-out "$SAN_DIR/san-test-dirname-rid.pem" \
228+
-days $DAYS \
229+
-sha256 \
230+
-extfile "$SAN_DIR/san-test-dirname-rid-ext.cnf" \
231+
-extensions san_ext
232+
233+
# Also create DER format
234+
openssl x509 -in "$SAN_DIR/san-test-dirname-rid.pem" -outform DER \
235+
-out "$SAN_DIR/san-test-dirname-rid.der"
236+
237+
# Cleanup
238+
rm -f "$SAN_DIR/san-test-dirname-rid.csr" "$SAN_DIR/san-test-dirname-rid-ext.cnf"
239+
240+
printf " Created: san-test-dirname-rid.pem, san-test-dirname-rid.der\n"
241+
242+
# =============================================================================
243+
# Certificate 5: ALL SAN types in one certificate (comprehensive test)
244+
# =============================================================================
245+
printf "\n[6/7] Generating san-test-all-types (comprehensive)...\n"
246+
247+
# Generate key
248+
openssl genrsa -out "$SAN_DIR/san-test-all-types-key.pem" 2048
249+
250+
# Create CSR
251+
openssl req -new \
252+
-key "$SAN_DIR/san-test-all-types-key.pem" \
253+
-subj "/C=US/ST=Montana/L=Bozeman/O=wolfSSL/OU=Testing/CN=All SAN Types Test" \
254+
-out "$SAN_DIR/san-test-all-types.csr"
255+
256+
# Create extension config with ALL SAN types
257+
# Note: registeredID (type 8) is excluded as it can cause issues with some
258+
# wolfSSL builds when parsing
259+
cat > "$SAN_DIR/san-test-all-types-ext.cnf" << 'EOF'
260+
[req]
261+
distinguished_name = req_distinguished_name
262+
263+
[req_distinguished_name]
264+
265+
[san_ext]
266+
subjectAltName = @san_names
267+
268+
[san_names]
269+
# Type 0: otherName (Microsoft UPN)
270+
otherName.0 = 1.3.6.1.4.1.311.20.2.3;UTF8:allsantypes@wolfssl.com
271+
272+
# Type 1: rfc822Name (email)
273+
email.0 = test@example.com
274+
email.1 = admin@wolfssl.com
275+
276+
# Type 2: dNSName
277+
DNS.0 = localhost
278+
DNS.1 = www.example.com
279+
DNS.2 = *.wildcard.example.com
280+
281+
# Type 4: directoryName
282+
dirName.0 = dir_sect
283+
284+
# Type 6: uniformResourceIdentifier
285+
URI.0 = https://www.wolfssl.com
286+
URI.1 = ldap://ldap.example.com/cn=test
287+
288+
# Type 7: iPAddress (IPv4 and IPv6)
289+
IP.0 = 127.0.0.1
290+
IP.1 = 192.168.1.100
291+
IP.2 = ::1
292+
IP.3 = fe80::1234:5678:abcd:ef00
293+
294+
# Note: registeredID (type 8) excluded - can cause issues with wolfSSL parsing
295+
296+
[dir_sect]
297+
C = US
298+
ST = Montana
299+
L = Bozeman
300+
O = wolfSSL Inc.
301+
OU = Engineering
302+
CN = Directory Name Entry
303+
EOF
304+
305+
# Sign with CA
306+
openssl x509 -req \
307+
-in "$SAN_DIR/san-test-all-types.csr" \
308+
-CA "$SAN_DIR/san-test-ca-cert.pem" \
309+
-CAkey "$SAN_DIR/san-test-ca-key.pem" \
310+
-CAcreateserial \
311+
-out "$SAN_DIR/san-test-all-types.pem" \
312+
-days $DAYS \
313+
-sha256 \
314+
-extfile "$SAN_DIR/san-test-all-types-ext.cnf" \
315+
-extensions san_ext
316+
317+
# Also create DER format
318+
openssl x509 -in "$SAN_DIR/san-test-all-types.pem" -outform DER \
319+
-out "$SAN_DIR/san-test-all-types.der"
320+
321+
# Cleanup
322+
rm -f "$SAN_DIR/san-test-all-types.csr" "$SAN_DIR/san-test-all-types-ext.cnf"
323+
324+
printf " Created: san-test-all-types.pem, san-test-all-types.der\n"
325+
326+
# =============================================================================
327+
# Cleanup and summary
328+
# =============================================================================
329+
printf "\n[7/7] Cleanup and verification...\n"
330+
331+
# Remove CA serial file
332+
rm -f "$SAN_DIR/san-test-ca-cert.srl"
333+
334+
# Remove all private keys except CA (tests only need certs)
335+
# Uncomment if you want to keep keys minimal:
336+
# rm -f "$SAN_DIR/san-test-dns-ip-key.pem"
337+
# rm -f "$SAN_DIR/san-test-email-uri-key.pem"
338+
# rm -f "$SAN_DIR/san-test-othername-upn-key.pem"
339+
# rm -f "$SAN_DIR/san-test-dirname-rid-key.pem"
340+
# rm -f "$SAN_DIR/san-test-all-types-key.pem"
341+
342+
printf "\n========================================\n"
343+
printf "SAN Test Certificate Generation Complete\n"
344+
printf "========================================\n"
345+
printf "\nGenerated files in %s/:\n" "$SAN_DIR"
346+
ls -la "$SAN_DIR"/*.pem "$SAN_DIR"/*.der 2>/dev/null | awk '{print " " $NF}'
347+
348+
printf "\nVerifying SAN extensions in generated certificates:\n"
349+
350+
printf "\n--- san-test-dns-ip.pem ---\n"
351+
openssl x509 -in "$SAN_DIR/san-test-dns-ip.pem" -noout -text | grep -A20 "Subject Alternative Name" | head -10
352+
353+
printf "\n--- san-test-email-uri.pem ---\n"
354+
openssl x509 -in "$SAN_DIR/san-test-email-uri.pem" -noout -text | grep -A20 "Subject Alternative Name" | head -10
355+
356+
printf "\n--- san-test-othername-upn.pem ---\n"
357+
openssl x509 -in "$SAN_DIR/san-test-othername-upn.pem" -noout -text | grep -A20 "Subject Alternative Name" | head -10
358+
359+
printf "\n--- san-test-dirname-rid.pem ---\n"
360+
openssl x509 -in "$SAN_DIR/san-test-dirname-rid.pem" -noout -text | grep -A20 "Subject Alternative Name" | head -15
361+
362+
printf "\n--- san-test-all-types.pem (comprehensive) ---\n"
363+
openssl x509 -in "$SAN_DIR/san-test-all-types.pem" -noout -text | grep -A50 "Subject Alternative Name" | head -30
364+
365+
printf "\nDone! Certificates are ready for testing WolfSSLAltName functionality.\n"
366+

0 commit comments

Comments
 (0)