@@ -543,6 +543,76 @@ static int wolfCLU_setAltNames(WOLFSSL_X509* x509, WOLFSSL_CONF* conf,
543543}
544544
545545
546+ #ifdef WOLFSSL_ALT_NAMES
547+ /* Apply an inline subjectAltName list to x509, e.g.
548+ * "DNS:example.com,IP:10.0.0.1". Leading whitespace per entry is skipped.
549+ * Buffer is tokenized in place, so callers pass a writable string. Returns
550+ * WOLFCLU_SUCCESS, or WOLFCLU_FATAL_ERROR on a malformed entry so a bad SAN is
551+ * never silently ignored. */
552+ static int wolfCLU_setInlineAltNames (WOLFSSL_X509 * x509 , char * val )
553+ {
554+ int ret = WOLFCLU_SUCCESS ;
555+ char * token ;
556+ char * ptr = NULL ;
557+
558+ if (x509 == NULL || val == NULL ) {
559+ return WOLFCLU_FATAL_ERROR ;
560+ }
561+
562+ token = XSTRTOK (val , "," , & ptr );
563+ while (token != NULL ) {
564+ char * colon ;
565+ char * value ;
566+ size_t len ;
567+
568+ /* trim whitespace around entries and trailing whitespace */
569+ while (* token == ' ' || * token == '\t' || * token == '\r' || * token == '\n' ) {
570+ token ++ ;
571+ }
572+ len = XSTRLEN (token );
573+ while (len > 0 && (token [len - 1 ] == ' ' || token [len - 1 ] == '\t' ||
574+ token [len - 1 ] == '\r' || token [len - 1 ] == '\n' )) {
575+ token [-- len ] = '\0' ;
576+ }
577+ colon = XSTRSTR (token , ":" );
578+ if (colon == NULL ) {
579+ wolfCLU_LogError ("bad subjectAltName entry \"%s\", expected "
580+ "TYPE:value" , token );
581+ ret = WOLFCLU_FATAL_ERROR ;
582+ break ;
583+ }
584+ * colon = '\0' ;
585+ /* The trailing-whitespace trim above already NUL-terminated the token
586+ * at the correct boundary, so value needs no second trailing trim. */
587+ /* drop whitespace between the colon and the value */
588+ value = colon + 1 ;
589+ while (* value == ' ' || * value == '\t' || * value == '\r' || * value == '\n' ) {
590+ value ++ ;
591+ }
592+
593+ /* Check for empty type or value after trimming */
594+ if (XSTRLEN (token ) == 0 ) {
595+ wolfCLU_LogError ("bad subjectAltName entry: empty type prefix" );
596+ ret = WOLFCLU_FATAL_ERROR ;
597+ break ;
598+ }
599+ if (XSTRLEN (value ) == 0 ) {
600+ wolfCLU_LogError ("bad subjectAltName entry: empty value for type \"%s\"" , token );
601+ ret = WOLFCLU_FATAL_ERROR ;
602+ break ;
603+ }
604+
605+ ret = wolfCLU_addAltName (x509 , token , value );
606+ if (ret != WOLFCLU_SUCCESS ) {
607+ break ;
608+ }
609+ token = XSTRTOK (NULL , "," , & ptr );
610+ }
611+ return ret ;
612+ }
613+ #endif /* WOLFSSL_ALT_NAMES */
614+
615+
546616/* return WOLFCLU_SUCCESS on success */
547617int wolfCLU_setExtensions (WOLFSSL_X509 * x509 , WOLFSSL_CONF * conf , char * sect )
548618{
@@ -576,9 +646,40 @@ int wolfCLU_setExtensions(WOLFSSL_X509* x509, WOLFSSL_CONF* conf, char* sect)
576646 }
577647
578648 current = wolfSSL_NCONF_get_string (conf , sect , "subjectAltName" );
579- if (current != NULL && current [0 ] == '@' ) {
580- current = current + 1 ;
581- ret = wolfCLU_setAltNames (x509 , conf , current );
649+ if (current != NULL ) {
650+ if (current [0 ] == '@' ) {
651+ ret = wolfCLU_setAltNames (x509 , conf , current + 1 );
652+ }
653+ else {
654+ /* Accept inline form for config compatibility. */
655+ #ifndef WOLFSSL_ALT_NAMES
656+ /* Intentional: mirror the pre-existing silent-skip behaviour of
657+ * the @section form (wolfCLU_setAltNames is also a no-op when
658+ * WOLFSSL_ALT_NAMES is not defined). We log the skip but do NOT
659+ * promote ret to WOLFCLU_FATAL_ERROR so that a config containing
660+ * a subjectAltName line is still usable in builds where alt-name
661+ * support was compiled out. */
662+ WOLFCLU_LOG (WOLFCLU_L0 , "Skipping alt names, recompile wolfSSL "
663+ "with WOLFSSL_ALT_NAMES..." );
664+ #else
665+ {
666+ int len = (int )XSTRLEN (current );
667+ char * dup = (char * )XMALLOC (len + 1 , NULL ,
668+ DYNAMIC_TYPE_TMP_BUFFER );
669+
670+ if (dup == NULL ) {
671+ wolfCLU_LogError ("out of memory duplicating "
672+ "subjectAltName value" );
673+ ret = WOLFCLU_FATAL_ERROR ;
674+ }
675+ else {
676+ XMEMCPY (dup , current , len + 1 );
677+ ret = wolfCLU_setInlineAltNames (x509 , dup );
678+ XFREE (dup , NULL , DYNAMIC_TYPE_TMP_BUFFER );
679+ }
680+ }
681+ #endif
682+ }
582683 }
583684 return ret ;
584685}
@@ -621,26 +722,8 @@ int wolfCLU_parseAddExt(WOLFSSL_X509* x509, char* addExt)
621722 (void )val ;
622723 WOLFCLU_LOG (WOLFCLU_L0 , "Skipping alt names, recompile wolfSSL with WOLFSSL_ALT_NAMES..." );
623724#else
624- char * token ;
625- char * ptr = NULL ;
626-
627725 /* value is a comma separated list of TYPE:value pairs */
628- token = XSTRTOK (val , "," , & ptr );
629- while (token != NULL ) {
630- char * colon = XSTRSTR (token , ":" );
631- if (colon == NULL ) {
632- wolfCLU_LogError ("bad subjectAltName entry \"%s\", expected "
633- "TYPE:value" , token );
634- ret = WOLFCLU_FATAL_ERROR ;
635- break ;
636- }
637- * colon = '\0' ;
638- ret = wolfCLU_addAltName (x509 , token , colon + 1 );
639- if (ret != WOLFCLU_SUCCESS ) {
640- break ;
641- }
642- token = XSTRTOK (NULL , "," , & ptr );
643- }
726+ ret = wolfCLU_setInlineAltNames (x509 , val );
644727#endif
645728 }
646729 else {
@@ -656,9 +739,18 @@ int wolfCLU_setExtensions(WOLFSSL_X509* x509, WOLFSSL_CONF* conf, char* sect)
656739{
657740 (void )x509 ;
658741 (void )conf ;
659- (void )sect ;
660742
661- wolfCLU_LogError ("wolfSSL not compiled with cert extensions" );
743+ /* No extension section requested, so not having WOLFSSL_CERT_EXT
744+ * can be ignored. (Coupled with `ret = ` in wolfCLU_readConfig) */
745+ if (sect == NULL ) {
746+ return WOLFCLU_SUCCESS ;
747+ }
748+
749+ /* If not compiled with WOLFSSL_CERT_EXT, fail so certs can be built as
750+ * intended by user. */
751+ wolfCLU_LogError ("wolfSSL not compiled with cert extensions "
752+ "(WOLFSSL_CERT_EXT); cannot apply requested x509_extensions "
753+ "section \"%s\"" , sect );
662754 return NOT_COMPILED_IN ;
663755}
664756
@@ -918,7 +1010,11 @@ int wolfCLU_readConfig(WOLFSSL_X509* x509, char* config, char* sect, char* ext)
9181010 wolfCLU_setAttributes (x509 , conf ,
9191011 wolfSSL_NCONF_get_string (conf , sect , "attributes" ));
9201012 if (ext == NULL ) {
921- (void )wolfCLU_setExtensions (x509 , conf ,
1013+ /* Note: we capture this return code because the !WOLFSSL_CERT_EXT stub
1014+ * of wolfCLU_setExtensions gracefully returns SUCCESS when the string
1015+ * is NULL, but fails loudly if an extension section IS requested and
1016+ * WOLFSSL_CERT_EXT is disabled. These two behaviors are coupled. */
1017+ ret = wolfCLU_setExtensions (x509 , conf ,
9221018 wolfSSL_NCONF_get_string (conf , sect , "x509_extensions" ));
9231019 }
9241020 else {
0 commit comments