367 lines
12 KiB
C
367 lines
12 KiB
C
/* com_wolfssl_WolfSSLNameConstraints.c
|
|
*
|
|
* Copyright (C) 2006-2026 wolfSSL Inc.
|
|
*
|
|
* This file is part of wolfSSL.
|
|
*
|
|
* wolfSSL is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* wolfSSL is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
|
|
#ifdef WOLFSSL_USER_SETTINGS
|
|
#include <wolfssl/wolfcrypt/settings.h>
|
|
#else
|
|
#include <wolfssl/options.h>
|
|
#endif
|
|
#include <wolfssl/ssl.h>
|
|
#include <wolfssl/version.h>
|
|
#include <wolfssl/openssl/x509v3.h>
|
|
|
|
#include "com_wolfssl_globals.h"
|
|
#include "com_wolfssl_WolfSSLNameConstraints.h"
|
|
|
|
/* Maximum reasonable string length to prevent excessive allocation (64KB) */
|
|
#define NC_MAX_STRING_LEN 65536
|
|
|
|
/* Name Constraints API was added after wolfSSL 5.8.4 in PR 9705. Version
|
|
* check must be greater than 5.8.4 or patch from PR 9705 must be applied
|
|
* and WOLFSSL_PR9705_PATCH_APPLIED defined when compiling this JNI wrapper. */
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLNameConstraints_wolfSSL_1NAME_1CONSTRAINTS_1free
|
|
(JNIEnv* jenv, jclass jcl, jlong ncPtr)
|
|
{
|
|
#if defined(OPENSSL_EXTRA) && !defined(IGNORE_NAME_CONSTRAINTS) && \
|
|
((LIBWOLFSSL_VERSION_HEX > 0x05008004) || \
|
|
defined(WOLFSSL_PR9705_PATCH_APPLIED))
|
|
(void)jenv;
|
|
(void)jcl;
|
|
|
|
if (ncPtr != 0) {
|
|
wolfSSL_NAME_CONSTRAINTS_free(
|
|
(WOLFSSL_NAME_CONSTRAINTS*)(uintptr_t)ncPtr);
|
|
}
|
|
#else
|
|
(void)jenv;
|
|
(void)jcl;
|
|
(void)ncPtr;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLNameConstraints_wolfSSL_1NAME_1CONSTRAINTS_1permittedNum
|
|
(JNIEnv* jenv, jclass jcl, jlong ncPtr)
|
|
{
|
|
#if defined(OPENSSL_EXTRA) && !defined(IGNORE_NAME_CONSTRAINTS) && \
|
|
((LIBWOLFSSL_VERSION_HEX > 0x05008004) || \
|
|
defined(WOLFSSL_PR9705_PATCH_APPLIED))
|
|
WOLFSSL_NAME_CONSTRAINTS* nc =
|
|
(WOLFSSL_NAME_CONSTRAINTS*)(uintptr_t)ncPtr;
|
|
(void)jenv;
|
|
(void)jcl;
|
|
|
|
if (nc == NULL || nc->permittedSubtrees == NULL) {
|
|
return 0;
|
|
}
|
|
return (jint)wolfSSL_sk_GENERAL_SUBTREE_num(nc->permittedSubtrees);
|
|
#else
|
|
(void)jenv;
|
|
(void)jcl;
|
|
(void)ncPtr;
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLNameConstraints_wolfSSL_1NAME_1CONSTRAINTS_1excludedNum
|
|
(JNIEnv* jenv, jclass jcl, jlong ncPtr)
|
|
{
|
|
#if defined(OPENSSL_EXTRA) && !defined(IGNORE_NAME_CONSTRAINTS) && \
|
|
((LIBWOLFSSL_VERSION_HEX > 0x05008004) || \
|
|
defined(WOLFSSL_PR9705_PATCH_APPLIED))
|
|
WOLFSSL_NAME_CONSTRAINTS* nc =
|
|
(WOLFSSL_NAME_CONSTRAINTS*)(uintptr_t)ncPtr;
|
|
(void)jenv;
|
|
(void)jcl;
|
|
|
|
if (nc == NULL || nc->excludedSubtrees == NULL) {
|
|
return 0;
|
|
}
|
|
return (jint)wolfSSL_sk_GENERAL_SUBTREE_num(nc->excludedSubtrees);
|
|
#else
|
|
(void)jenv;
|
|
(void)jcl;
|
|
(void)ncPtr;
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLNameConstraints_wolfSSL_1GENERAL_1SUBTREE_1getBaseType
|
|
(JNIEnv* jenv, jclass jcl, jlong ncPtr, jboolean permitted, jint idx)
|
|
{
|
|
#if defined(OPENSSL_EXTRA) && !defined(IGNORE_NAME_CONSTRAINTS) && \
|
|
((LIBWOLFSSL_VERSION_HEX > 0x05008004) || \
|
|
defined(WOLFSSL_PR9705_PATCH_APPLIED))
|
|
WOLFSSL_NAME_CONSTRAINTS* nc =
|
|
(WOLFSSL_NAME_CONSTRAINTS*)(uintptr_t)ncPtr;
|
|
WOLFSSL_STACK* sk;
|
|
WOLFSSL_GENERAL_SUBTREE* subtree;
|
|
int skNum;
|
|
(void)jenv;
|
|
(void)jcl;
|
|
|
|
if (nc == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
sk = permitted ? nc->permittedSubtrees : nc->excludedSubtrees;
|
|
if (sk == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
/* Bounds check for idx to prevent out-of-bounds access */
|
|
skNum = wolfSSL_sk_GENERAL_SUBTREE_num(sk);
|
|
if (idx < 0 || idx >= skNum) {
|
|
return -1;
|
|
}
|
|
|
|
subtree = wolfSSL_sk_GENERAL_SUBTREE_value(sk, (int)idx);
|
|
if (subtree == NULL || subtree->base == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
return (jint)subtree->base->type;
|
|
#else
|
|
(void)jenv;
|
|
(void)jcl;
|
|
(void)ncPtr;
|
|
(void)permitted;
|
|
(void)idx;
|
|
return -1;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLNameConstraints_wolfSSL_1GENERAL_1SUBTREE_1getBaseValue
|
|
(JNIEnv* jenv, jclass jcl, jlong ncPtr, jboolean permitted, jint idx)
|
|
{
|
|
#if defined(OPENSSL_EXTRA) && !defined(IGNORE_NAME_CONSTRAINTS) && \
|
|
((LIBWOLFSSL_VERSION_HEX > 0x05008004) || \
|
|
defined(WOLFSSL_PR9705_PATCH_APPLIED))
|
|
WOLFSSL_NAME_CONSTRAINTS* nc =
|
|
(WOLFSSL_NAME_CONSTRAINTS*)(uintptr_t)ncPtr;
|
|
WOLFSSL_STACK* sk;
|
|
WOLFSSL_GENERAL_SUBTREE* subtree;
|
|
WOLFSSL_GENERAL_NAME* gn;
|
|
const unsigned char* str = NULL;
|
|
int strLen = 0;
|
|
int skNum;
|
|
char* buf = NULL;
|
|
jstring result = NULL;
|
|
(void)jcl;
|
|
|
|
if (nc == NULL || jenv == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
sk = permitted ? nc->permittedSubtrees : nc->excludedSubtrees;
|
|
if (sk == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
/* Bounds check for idx to prevent out-of-bounds access */
|
|
skNum = wolfSSL_sk_GENERAL_SUBTREE_num(sk);
|
|
if (idx < 0 || idx >= skNum) {
|
|
return NULL;
|
|
}
|
|
|
|
subtree = wolfSSL_sk_GENERAL_SUBTREE_value(sk, (int)idx);
|
|
if (subtree == NULL || subtree->base == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
gn = subtree->base;
|
|
|
|
switch (gn->type) {
|
|
case WOLFSSL_GEN_DNS:
|
|
case WOLFSSL_GEN_EMAIL:
|
|
case WOLFSSL_GEN_URI:
|
|
if (gn->d.ia5 != NULL) {
|
|
str = wolfSSL_ASN1_STRING_get0_data(gn->d.ia5);
|
|
strLen = wolfSSL_ASN1_STRING_length(gn->d.ia5);
|
|
}
|
|
break;
|
|
|
|
case WOLFSSL_GEN_DIRNAME:
|
|
if (gn->d.directoryName != NULL) {
|
|
/* Convert X509_NAME to one-line string */
|
|
buf = wolfSSL_X509_NAME_oneline(gn->d.directoryName, NULL, 0);
|
|
if (buf != NULL) {
|
|
result = (*jenv)->NewStringUTF(jenv, buf);
|
|
XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL);
|
|
return result;
|
|
}
|
|
}
|
|
return NULL;
|
|
|
|
case WOLFSSL_GEN_IPADD:
|
|
/* For IP addresses, return address/mask notation.
|
|
* IPv4 (8 bytes): "192.168.1.0/255.255.255.0"
|
|
* IPv6 (32 bytes): "fe80:0000:...:0001/ffff:ffff:...:0000" */
|
|
if (gn->d.ip != NULL) {
|
|
int i;
|
|
int ipLen = wolfSSL_ASN1_STRING_length(gn->d.ip);
|
|
const unsigned char* ipData =
|
|
wolfSSL_ASN1_STRING_get0_data(gn->d.ip);
|
|
|
|
if (ipData != NULL && ipLen > 0 && ipLen <= 32) {
|
|
if (ipLen == 8) {
|
|
/* IPv4: 4 bytes IP + 4 bytes mask */
|
|
/* Max: "255.255.255.255/255.255.255.255" = 31 chars */
|
|
buf = (char*)XMALLOC(40, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (buf != NULL) {
|
|
XSNPRINTF(buf, 40, "%d.%d.%d.%d/%d.%d.%d.%d",
|
|
ipData[0], ipData[1], ipData[2], ipData[3],
|
|
ipData[4], ipData[5], ipData[6], ipData[7]);
|
|
result = (*jenv)->NewStringUTF(jenv, buf);
|
|
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
return result;
|
|
}
|
|
}
|
|
else if (ipLen == 32) {
|
|
/* IPv6: 16 bytes IP + 16 bytes mask
|
|
* Format: "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/
|
|
* yyyy:yyyy:yyyy:yyyy:yyyy:yyyy:yyyy:yyyy"
|
|
* 8 groups * 4 chars + 7 colons = 39 chars per addr
|
|
* 39 + 1 (slash) + 39 = 79 chars + null = 80 */
|
|
buf = (char*)XMALLOC(80, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (buf != NULL) {
|
|
int pos = 0;
|
|
/* Format address (first 16 bytes) */
|
|
for (i = 0; i < 16; i += 2) {
|
|
if (i > 0) {
|
|
buf[pos++] = ':';
|
|
}
|
|
XSNPRINTF(buf + pos, 5, "%02x%02x",
|
|
ipData[i], ipData[i + 1]);
|
|
pos += 4;
|
|
}
|
|
buf[pos++] = '/';
|
|
/* Format mask (next 16 bytes) */
|
|
for (i = 16; i < 32; i += 2) {
|
|
if (i > 16) {
|
|
buf[pos++] = ':';
|
|
}
|
|
XSNPRINTF(buf + pos, 5, "%02x%02x",
|
|
ipData[i], ipData[i + 1]);
|
|
pos += 4;
|
|
}
|
|
buf[pos] = '\0';
|
|
result = (*jenv)->NewStringUTF(jenv, buf);
|
|
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
return result;
|
|
}
|
|
}
|
|
else {
|
|
/* Other lengths: return colon-separated hex bytes */
|
|
int bufLen = ipLen * 3;
|
|
buf = (char*)XMALLOC(bufLen, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (buf != NULL) {
|
|
int pos = 0;
|
|
for (i = 0; i < ipLen; i++) {
|
|
if (i > 0) {
|
|
buf[pos++] = ':';
|
|
}
|
|
XSNPRINTF(buf + pos, 3, "%02X", ipData[i]);
|
|
pos += 2;
|
|
}
|
|
buf[pos] = '\0';
|
|
result = (*jenv)->NewStringUTF(jenv, buf);
|
|
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
|
|
default:
|
|
return NULL;
|
|
}
|
|
|
|
/* Validate strLen to prevent excessive allocation */
|
|
if (str != NULL && strLen > 0 && strLen <= NC_MAX_STRING_LEN) {
|
|
/* Create null-terminated copy for JNI NewStringUTF */
|
|
buf = (char*)XMALLOC(strLen + 1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (buf != NULL) {
|
|
XMEMCPY(buf, str, strLen);
|
|
buf[strLen] = '\0';
|
|
result = (*jenv)->NewStringUTF(jenv, buf);
|
|
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
#else
|
|
(void)jenv;
|
|
(void)jcl;
|
|
(void)ncPtr;
|
|
(void)permitted;
|
|
(void)idx;
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLNameConstraints_wolfSSL_1NAME_1CONSTRAINTS_1check_1name
|
|
(JNIEnv* jenv, jclass jcl, jlong ncPtr, jint type, jstring name)
|
|
{
|
|
#if defined(OPENSSL_EXTRA) && !defined(IGNORE_NAME_CONSTRAINTS) && \
|
|
((LIBWOLFSSL_VERSION_HEX > 0x05008004) || \
|
|
defined(WOLFSSL_PR9705_PATCH_APPLIED))
|
|
WOLFSSL_NAME_CONSTRAINTS* nc =
|
|
(WOLFSSL_NAME_CONSTRAINTS*)(uintptr_t)ncPtr;
|
|
const char* nameStr = NULL;
|
|
int nameLen = 0;
|
|
int ret = 0;
|
|
(void)jcl;
|
|
|
|
if (nc == NULL || jenv == NULL || name == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
/* Get the name string from Java */
|
|
nameStr = (*jenv)->GetStringUTFChars(jenv, name, NULL);
|
|
if (nameStr == NULL) {
|
|
return 0;
|
|
}
|
|
nameLen = (int)(*jenv)->GetStringUTFLength(jenv, name);
|
|
|
|
/* Call native wolfSSL function */
|
|
ret = wolfSSL_NAME_CONSTRAINTS_check_name(nc, (int)type, nameStr, nameLen);
|
|
|
|
/* Release the string */
|
|
(*jenv)->ReleaseStringUTFChars(jenv, name, nameStr);
|
|
|
|
return (jint)ret;
|
|
#else
|
|
(void)jenv;
|
|
(void)jcl;
|
|
(void)ncPtr;
|
|
(void)type;
|
|
(void)name;
|
|
return 0;
|
|
#endif
|
|
}
|
|
|