@@ -1680,7 +1680,7 @@ int wolfIO_TcpAccept(SOCKET_T sockfd, SOCKADDR* peer_addr, XSOCKLENT* peer_len)
16801680int wolfIO_DecodeUrl (const char * url , int urlSz , char * outName , char * outPath ,
16811681 word16 * outPort )
16821682{
1683- int result = -1 ;
1683+ int result = WC_NO_ERR_TRACE ( WOLFSSL_FATAL_ERROR ) ;
16841684
16851685 if (url == NULL || urlSz == 0 ) {
16861686 if (outName )
@@ -1706,6 +1706,8 @@ int wolfIO_DecodeUrl(const char* url, int urlSz, char* outName, char* outPath,
17061706 /* copy until ']' */
17071707 while (i < MAX_URL_ITEM_SIZE - 1 && cur < urlSz && url [cur ] != 0 &&
17081708 url [cur ] != ']' ) {
1709+ if (url [cur ] == '\r' || url [cur ] == '\n' )
1710+ return WOLFSSL_FATAL_ERROR ;
17091711 if (outName )
17101712 outName [i ] = url [cur ];
17111713 i ++ ; cur ++ ;
@@ -1715,6 +1717,8 @@ int wolfIO_DecodeUrl(const char* url, int urlSz, char* outName, char* outPath,
17151717 else {
17161718 while (i < MAX_URL_ITEM_SIZE - 1 && cur < urlSz && url [cur ] != 0 &&
17171719 url [cur ] != ':' && url [cur ] != '/' ) {
1720+ if (url [cur ] == '\r' || url [cur ] == '\n' )
1721+ return WOLFSSL_FATAL_ERROR ;
17181722 if (outName )
17191723 outName [i ] = url [cur ];
17201724 i ++ ; cur ++ ;
@@ -1752,6 +1756,8 @@ int wolfIO_DecodeUrl(const char* url, int urlSz, char* outName, char* outPath,
17521756 if (cur < urlSz && url [cur ] == '/' ) {
17531757 i = 0 ;
17541758 while (i < MAX_URL_ITEM_SIZE - 1 && cur < urlSz && url [cur ] != 0 ) {
1759+ if (url [cur ] == '\r' || url [cur ] == '\n' )
1760+ return WOLFSSL_FATAL_ERROR ;
17551761 if (outPath )
17561762 outPath [i ] = url [cur ];
17571763 i ++ ; cur ++ ;
@@ -2065,6 +2071,21 @@ int wolfIO_HttpBuildRequest(const char *reqType, const char *domainName,
20652071 return wolfIO_HttpBuildRequest_ex (reqType , domainName , path , pathLen , reqSz , contentType , "" , buf , bufSize );
20662072}
20672073
2074+ /* Returns 1 if the buffer contains a CR or LF byte, 0 otherwise. Used to
2075+ * reject attacker-controlled URL components that would allow HTTP header
2076+ * injection or request splitting. */
2077+ static int wolfIO_UrlHasCrlf (const char * in , int inSz )
2078+ {
2079+ int i = 0 ;
2080+ if (in == NULL )
2081+ return 0 ;
2082+ for (i = 0 ; i < inSz ; i ++ ) {
2083+ if (in [i ] == '\r' || in [i ] == '\n' )
2084+ return 1 ;
2085+ }
2086+ return 0 ;
2087+ }
2088+
20682089int wolfIO_HttpBuildRequest_ex (const char * reqType , const char * domainName ,
20692090 const char * path , int pathLen , int reqSz , const char * contentType ,
20702091 const char * exHdrs , byte * buf , int bufSize )
@@ -2087,6 +2108,13 @@ int wolfIO_HttpBuildRequest_ex(const char *reqType, const char *domainName,
20872108 reqSzStrLen = wolfIO_Word16ToString (reqSzStr , (word16 )reqSz );
20882109 contentTypeLen = (word32 )XSTRLEN (contentType );
20892110
2111+ /* reject CR/LF in the path or host to prevent HTTP header injection or
2112+ * request splitting from attacker-controlled URL components */
2113+ if (wolfIO_UrlHasCrlf (path , pathLen ) ||
2114+ wolfIO_UrlHasCrlf (domainName , (int )domainNameLen )) {
2115+ return 0 ;
2116+ }
2117+
20902118 blankStrLen = (word32 )XSTRLEN (blankStr );
20912119 http11StrLen = (word32 )XSTRLEN (http11Str );
20922120 hostStrLen = (word32 )XSTRLEN (hostStr );
@@ -2126,7 +2154,10 @@ int wolfIO_HttpBuildRequest_ex(const char *reqType, const char *domainName,
21262154 buf += reqTypeLen ; bufSize -= (int )reqTypeLen ;
21272155 XSTRNCPY ((char * )buf , blankStr , (size_t )bufSize );
21282156 buf += blankStrLen ; bufSize -= (int )blankStrLen ;
2129- XSTRNCPY ((char * )buf , path , (size_t )bufSize );
2157+ /* path may not be NUL terminated (CRL raw-URL case passes a pointer into
2158+ * the certificate with only pathLen valid bytes), so bound the copy to
2159+ * pathLen rather than scanning for a NUL */
2160+ XMEMCPY ((char * )buf , path , (size_t )pathLen );
21302161 buf += pathLen ; bufSize -= (int )pathLen ;
21312162 XSTRNCPY ((char * )buf , http11Str , (size_t )bufSize );
21322163 buf += http11StrLen ; bufSize -= (int )http11StrLen ;
@@ -2251,8 +2282,11 @@ int EmbedOcspLookup(void* ctx, const char* url, int urlSz,
22512282 httpBufSz = wolfIO_HttpBuildRequestOcsp (domainName , path , ocspReqSz ,
22522283 httpBuf , httpBufSz );
22532284
2254- ret = wolfIO_TcpConnect (& sfd , domainName , port , io_timeout_sec );
2255- if (ret != 0 ) {
2285+ if (httpBufSz <= 0 ) {
2286+ WOLFSSL_MSG ("Unable to build OCSP request" );
2287+ }
2288+ else if ((ret = wolfIO_TcpConnect (& sfd , domainName , port ,
2289+ io_timeout_sec )) != 0 ) {
22562290 WOLFSSL_MSG ("OCSP Responder connection failed" );
22572291 }
22582292 else if (wolfIO_Send (sfd , (char * )httpBuf , httpBufSz , 0 ) !=
@@ -2351,8 +2385,11 @@ int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, int urlSz)
23512385 httpBufSz = wolfIO_HttpBuildRequestCrl (url , urlSz , domainName ,
23522386 httpBuf , httpBufSz );
23532387
2354- ret = wolfIO_TcpConnect (& sfd , domainName , port , io_timeout_sec );
2355- if (ret != 0 ) {
2388+ if (httpBufSz <= 0 ) {
2389+ WOLFSSL_MSG ("Unable to build CRL request" );
2390+ }
2391+ else if ((ret = wolfIO_TcpConnect (& sfd , domainName , port ,
2392+ io_timeout_sec )) != 0 ) {
23562393 WOLFSSL_MSG ("CRL connection failed" );
23572394 }
23582395 else if (wolfIO_Send (sfd , (char * )httpBuf , httpBufSz , 0 )
0 commit comments