mirror of
https://github.com/3proxy/3proxy.git
synced 2026-08-05 17:20:11 +08:00
replace recursion with loop for local redirects, fix wolfSSL build
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ubuntu-latest (wolfSSL) (push) Waiting to run
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ubuntu-latest (wolfSSL) (push) Waiting to run
This commit is contained in:
parent
5f1ed7363b
commit
44c47ee7d9
@ -24,13 +24,13 @@ void * autochild(struct clientparam* param) {
|
||||
}
|
||||
if(*param->clibuf == 4 || *param->clibuf == 5) {
|
||||
param->service = S_SOCKS;
|
||||
return sockschild(param);
|
||||
return (void *)sockschild;
|
||||
}
|
||||
if(*param->clibuf == 22) {
|
||||
param->service = S_TLSPR;
|
||||
return tlsprchild(param);
|
||||
return (void *)tlsprchild;
|
||||
}
|
||||
param->service = S_PROXY;
|
||||
return proxychild(param);
|
||||
return (void *)proxychild;
|
||||
}
|
||||
|
||||
|
||||
@ -222,7 +222,6 @@ CLEANRET:
|
||||
#ifndef _WIN32
|
||||
param->clisock = INVALID_SOCKET;
|
||||
#endif
|
||||
freeparam(param);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -325,7 +325,6 @@ CLEANRET:
|
||||
}
|
||||
if(req) free(req);
|
||||
if(buf) free(buf);
|
||||
freeparam(param);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -64,7 +64,7 @@ void * imappchild(struct clientparam* param) {
|
||||
if(socksend(param, param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]) <= 0) {RETURN(698);}
|
||||
param->clientstarttls = S_IMAPP;
|
||||
if(!param->srv->targetport) param->srv->targetport = htons(143);
|
||||
return tlsprchild(param);
|
||||
return (void *)tlsprchild;
|
||||
}
|
||||
#endif
|
||||
if(!strncasecmp((char *)cmd, "LOGIN ", 6)){
|
||||
@ -238,7 +238,6 @@ CLEANRET:
|
||||
socksend(param, param->clisock, buf, (int)strlen((char *)buf),conf.timeouts[STRING_S]);
|
||||
}
|
||||
}
|
||||
freeparam(param);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -338,7 +338,7 @@ void lognone(struct clientparam * param, const unsigned char *s) {
|
||||
clearstat(param);
|
||||
}
|
||||
|
||||
void logstdout(struct clientparam * param, const unsigned char *s) {
|
||||
NOINLINE void logstdout(struct clientparam * param, const unsigned char *s) {
|
||||
FILE *log;
|
||||
unsigned char tmpbuf[8192];
|
||||
|
||||
|
||||
@ -38,7 +38,7 @@ void * pop3pchild(struct clientparam* param) {
|
||||
if(socksend(param, param->clisock, (unsigned char *)"+OK Begin TLS negotiation\r\n", 27, conf.timeouts[STRING_S])!=27) {RETURN(623);}
|
||||
param->clientstarttls = S_POP3P;
|
||||
if(!param->srv->targetport) param->srv->targetport = htons(110);
|
||||
return tlsprchild(param);
|
||||
return (void *)tlsprchild;
|
||||
}
|
||||
#endif
|
||||
socksend(param, param->clisock, (unsigned char *)"-ERR need USER first\r\n", 22, conf.timeouts[STRING_S]);
|
||||
@ -74,7 +74,6 @@ CLEANRET:
|
||||
if(param->clisock != INVALID_SOCKET) {
|
||||
if ((param->res > 0 && param->res < 100) || (param->res > 611 && param->res <700)) socksend(param, param->clisock, (unsigned char *)"-ERR\r\n", 6,conf.timeouts[STRING_S]);
|
||||
}
|
||||
freeparam(param);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -864,7 +864,7 @@ for(;;){
|
||||
if(isconnect && param->redirtype != R_HTTP) {
|
||||
if(param->redirectfunc) {
|
||||
freeptr(&req); freeptr(&buf); freeptr(&ftpbase);
|
||||
return (*param->redirectfunc)(param);
|
||||
return (void *)param->redirectfunc;
|
||||
}
|
||||
param->res = mapsocket(param, conf.timeouts[CONNECTION_L]);
|
||||
RETURN(param->res);
|
||||
@ -1226,7 +1226,6 @@ CLEANRET:
|
||||
}
|
||||
logurl(param, (char *)buf, (char *)req, ftp);
|
||||
freeptr(&req); freeptr(&buf); freeptr(&ftpbase);
|
||||
freeparam(param);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
21
src/proxy.h
21
src/proxy.h
@ -112,6 +112,18 @@ void daemonize(void);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Keeps a callee with a large frame out of the caller's frame, e.g. the
|
||||
8K log buffer of logstdout() out of dolog(), which calls it in a branch
|
||||
taken only when there is no service.
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
#define NOINLINE __attribute__((noinline))
|
||||
#elif defined(_MSC_VER)
|
||||
#define NOINLINE __declspec(noinline)
|
||||
#else
|
||||
#define NOINLINE
|
||||
#endif
|
||||
|
||||
/* Thread stack size, stacksize command value is added to it. BSD libc uses
|
||||
significantly more stack, e.g. in vfprintf() called by syslog().
|
||||
*/
|
||||
@ -213,7 +225,7 @@ void dolog(struct clientparam * param, const unsigned char *s);
|
||||
int dobuf(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec);
|
||||
int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec, struct tm* tm, char * format);
|
||||
extern FILE * stdlog;
|
||||
void logstdout(struct clientparam * param, const unsigned char *s);
|
||||
NOINLINE void logstdout(struct clientparam * param, const unsigned char *s);
|
||||
void logsyslog(struct clientparam * param, const unsigned char *s);
|
||||
void lognone(struct clientparam * param, const unsigned char *s);
|
||||
void logradius(struct clientparam * param, const unsigned char *s);
|
||||
@ -357,6 +369,13 @@ void * udppmchild(struct clientparam * param);
|
||||
void * adminchild(struct clientparam * param);
|
||||
void * ftpprchild(struct clientparam * param);
|
||||
void * tlsprchild(struct clientparam * param);
|
||||
/* Child functions return the child to redirect the request to, or NULL if
|
||||
the request is complete. childfunc() calls them and releases param.
|
||||
Recursive redirection, e.g. a socks service redirected to socks5, used to
|
||||
be limited by the stack size only, MAXCHILDREDIRECTS limits it now.
|
||||
*/
|
||||
#define MAXCHILDREDIRECTS 16
|
||||
void * childfunc(struct clientparam * param);
|
||||
|
||||
|
||||
struct datatype;
|
||||
|
||||
@ -13,13 +13,19 @@
|
||||
|
||||
/* Child functions do not call each other, a child requesting redirection to
|
||||
another child returns it instead of calling it, to keep the stack flat.
|
||||
NULL is returned by the child which completed the request, it has already
|
||||
released param and it must not be accessed after the call.
|
||||
The child which completed the request returns NULL. param is logged by
|
||||
the child and released here.
|
||||
*/
|
||||
void * childfunc(struct clientparam * param){
|
||||
PROXYFUNC pf = param->srv->pf;
|
||||
int i;
|
||||
|
||||
while(pf) pf = (PROXYFUNC)(*pf)(param);
|
||||
for(i = 0; pf && i < MAXCHILDREDIRECTS; i++) pf = (PROXYFUNC)(*pf)(param);
|
||||
if(pf){
|
||||
param->res = 101;
|
||||
dolog(param, (unsigned char *)"Redirection loop");
|
||||
}
|
||||
freeparam(param);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -133,7 +139,7 @@ void * threadfunc (void *p) {
|
||||
}
|
||||
}
|
||||
}
|
||||
((struct clientparam *) p)->srv->pf((struct clientparam *)p);
|
||||
childfunc((struct clientparam *)p);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
return 0;
|
||||
@ -701,7 +707,7 @@ int MODULEMAINFUNC (int argc, char** argv){
|
||||
return 2;
|
||||
};
|
||||
*newparam = defparam;
|
||||
return((*srv.pf)((void *)newparam)? 1:0);
|
||||
return(childfunc(newparam)? 1:0);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -132,7 +132,7 @@ void * smtppchild(struct clientparam* param) {
|
||||
if(socksend(param, param->clisock, (unsigned char *)"220 2.0.0 Ready to start TLS\r\n", 30, conf.timeouts[STRING_S])!=30) {RETURN(673);}
|
||||
param->clientstarttls = S_SMTPP;
|
||||
if(!param->srv->targetport) param->srv->targetport = htons(587);
|
||||
return tlsprchild(param);
|
||||
return (void *)tlsprchild;
|
||||
}
|
||||
#endif
|
||||
else if(!param->hostname) socksend(param, param->clisock, (unsigned char *)"571 need AUTH first\r\n", 22, conf.timeouts[STRING_S]);
|
||||
@ -319,7 +319,6 @@ CLEANRET:
|
||||
if ((param->res > 0 && param->res < 100) || (param->res > 661 && param->res <700)) socksend(param, param->clisock, (unsigned char *)"571 \r\n", 6,conf.timeouts[STRING_S]);
|
||||
}
|
||||
if(command) free(command);
|
||||
freeparam(param);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -385,9 +385,8 @@ fflush(stderr);
|
||||
switch(command) {
|
||||
case 1:
|
||||
if(param->redirectfunc){
|
||||
void *ret = (*param->redirectfunc)(param);
|
||||
if(buf)free(buf);
|
||||
return ret;
|
||||
return (void *)param->redirectfunc;
|
||||
}
|
||||
param->res = mapsocket(param, conf.timeouts[CONNECTION_L]);
|
||||
break;
|
||||
@ -467,7 +466,6 @@ fflush(stderr);
|
||||
dolog(param, buf);
|
||||
free(buf);
|
||||
}
|
||||
freeparam(param);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
65
src/ssllib.c
65
src/ssllib.c
@ -72,6 +72,18 @@ static size_t bin2hex (const unsigned char* bin, size_t bin_length, char* str, s
|
||||
return p - str;
|
||||
}
|
||||
|
||||
static int copy_ext(X509 *dst_cert, X509 *src_cert, int nid)
|
||||
{
|
||||
X509_EXTENSION *ext;
|
||||
int idx;
|
||||
|
||||
idx = X509_get_ext_by_NID(src_cert, nid, -1);
|
||||
if(idx < 0) return 0;
|
||||
if(!(ext = X509_get_ext(src_cert, idx))) return 0;
|
||||
return X509_add_ext(dst_cert, ext, -1) > 0;
|
||||
}
|
||||
|
||||
#ifndef WITH_WOLFSSL
|
||||
static int add_ext(X509 *cert, int nid, const char *value)
|
||||
{
|
||||
X509_EXTENSION *ex;
|
||||
@ -93,11 +105,11 @@ static int add_ext(X509 *cert, int nid, const char *value)
|
||||
X509_EXTENSION_free(ex);
|
||||
return err > 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
SSL_CERT ssl_copy_cert(SSL_CERT cert, SSL_CONFIG *config)
|
||||
{
|
||||
int err = -1;
|
||||
int san_idx;
|
||||
BIO *fcache;
|
||||
X509 *src_cert = (X509 *) cert;
|
||||
X509 *dst_cert = NULL;
|
||||
@ -153,7 +165,11 @@ SSL_CERT ssl_copy_cert(SSL_CERT cert, SSL_CONFIG *config)
|
||||
X509_free(dst_cert);
|
||||
return NULL;
|
||||
}
|
||||
#if !defined(WITH_WOLFSSL) && OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
/* wolfSSL has no X509_set1_notBefore/X509_set1_notAfter before 5.7.2,
|
||||
X509_set_notBefore/X509_set_notAfter are available in every version and
|
||||
copy the time the same way.
|
||||
*/
|
||||
#if defined(WITH_WOLFSSL) || OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
if(!X509_set_notBefore(dst_cert, X509_get_notBefore(src_cert))
|
||||
|| !X509_set_notAfter(dst_cert, X509_get_notAfter(src_cert))){
|
||||
#else
|
||||
@ -163,26 +179,30 @@ SSL_CERT ssl_copy_cert(SSL_CERT cert, SSL_CONFIG *config)
|
||||
X509_free(dst_cert);
|
||||
return NULL;
|
||||
}
|
||||
san_idx = X509_get_ext_by_NID(src_cert, NID_subject_alt_name, -1);
|
||||
if(san_idx >= 0){
|
||||
X509_EXTENSION *san;
|
||||
san = X509_get_ext(src_cert, san_idx);
|
||||
if(san && !X509_add_ext(dst_cert, san, -1)){
|
||||
X509_free(dst_cert);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* Extensions required from an end entity certificate. Without EKU
|
||||
* serverAuth Apple's TLS stack (and Chrome on macOS/iOS, which uses it)
|
||||
* rejects the certificate. keyUsage is intentionally not set: it depends
|
||||
* on the type of the key being reused for every generated certificate,
|
||||
* and an absent keyUsage places no restriction.
|
||||
/* Copy the extensions an end entity certificate is expected to have.
|
||||
* The extensions which break chain validation (AKI, CRL distribution
|
||||
* points, certificate policies, ...) are intentionally not copied.
|
||||
* A copy may fail: wolfSSL keeps extKeyUsage in its own form and can
|
||||
* not add back the one it returns, it is not fatal.
|
||||
*/
|
||||
if(!add_ext(dst_cert, NID_basic_constraints, "critical,CA:FALSE")
|
||||
|| !add_ext(dst_cert, NID_ext_key_usage, "serverAuth")){
|
||||
X509_free(dst_cert);
|
||||
return NULL;
|
||||
}
|
||||
copy_ext(dst_cert, src_cert, NID_subject_alt_name);
|
||||
#ifndef WITH_WOLFSSL
|
||||
/* Without EKU serverAuth Apple's TLS stack (and Chrome on macOS/iOS,
|
||||
* which uses it) rejects the certificate, generate the extensions the
|
||||
* server certificate has no usable ones to copy. keyUsage is not set:
|
||||
* it depends on the type of the key reused for every generated
|
||||
* certificate, and an absent keyUsage places no restriction.
|
||||
* wolfSSL_X509V3_EXT_conf_nid() is a stub returning NULL in every
|
||||
* wolfSSL version, the extensions can not be generated there.
|
||||
*/
|
||||
if(!copy_ext(dst_cert, src_cert, NID_basic_constraints))
|
||||
add_ext(dst_cert, NID_basic_constraints, "critical,CA:FALSE");
|
||||
if(!copy_ext(dst_cert, src_cert, NID_ext_key_usage))
|
||||
add_ext(dst_cert, NID_ext_key_usage, "serverAuth");
|
||||
#else
|
||||
copy_ext(dst_cert, src_cert, NID_basic_constraints);
|
||||
copy_ext(dst_cert, src_cert, NID_ext_key_usage);
|
||||
#endif
|
||||
err = X509_sign(dst_cert, config->CA_key, EVP_sha256());
|
||||
if(!err){
|
||||
X509_free(dst_cert);
|
||||
@ -256,10 +276,10 @@ void _ssl_cert_free(SSL_CERT cert)
|
||||
#define LEGACY_SSL_THREADING 0
|
||||
#endif
|
||||
|
||||
#if LEGACY_SSL_THREADING
|
||||
/* This array will store all of the mutexes available to OpenSSL. */
|
||||
static _3proxy_mutex_t *mutex_buf= NULL;
|
||||
|
||||
|
||||
static void locking_function(int mode, int n, const char * file, int line)
|
||||
{
|
||||
if (mode & CRYPTO_LOCK)
|
||||
@ -276,6 +296,7 @@ static unsigned long id_function(void)
|
||||
return ((unsigned long)pthread_self());
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
int thread_setup(void)
|
||||
{
|
||||
|
||||
@ -40,14 +40,13 @@ void * tcppmchild(struct clientparam* param) {
|
||||
if(action != PASS) RETURN(19);
|
||||
}
|
||||
if(param->redirectfunc){
|
||||
return (*param->redirectfunc)(param);
|
||||
return (void *)param->redirectfunc;
|
||||
}
|
||||
|
||||
RETURN (mapsocket(param, conf.timeouts[CONNECTION_L]));
|
||||
CLEANRET:
|
||||
|
||||
dolog(param, param->hostname);
|
||||
freeparam(param);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -396,7 +396,7 @@ void * tlsprchild(struct clientparam* param) {
|
||||
if(action != PASS) RETURN(19);
|
||||
}
|
||||
if(param->redirectfunc && param->redirectfunc != tlsprchild){
|
||||
return (*param->redirectfunc)(param);
|
||||
return (void *)param->redirectfunc;
|
||||
}
|
||||
|
||||
if(stlsproto){
|
||||
@ -471,7 +471,6 @@ CLEANRET:
|
||||
|
||||
sprintf(req, "%sv%d.%d %s %s", lv<0?"NONE":lv?"TLS":"SSL", lv<0?0:lv?1:3, lv<0?0:lv?lv-1:0, param->hostname?(char *)param->hostname:"-", proto);
|
||||
dolog(param, (unsigned char *)req);
|
||||
freeparam(param);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -87,7 +87,6 @@ CLEANRET:
|
||||
_3proxy_sem_unlock(udpinit);
|
||||
dolog(param, NULL);
|
||||
param->clisock = INVALID_SOCKET;
|
||||
freeparam(param);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -615,6 +615,5 @@ CLEANRET:
|
||||
if(buf) free(buf);
|
||||
dolog(param, (unsigned char *)req);
|
||||
if(req)free(req);
|
||||
freeparam(param);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user