diff --git a/bin/tlspr b/bin/tlspr new file mode 100644 index 0000000..8993cb0 Binary files /dev/null and b/bin/tlspr differ diff --git a/src/Makefile.inc b/src/Makefile.inc index 335a444..d7f4b1e 100644 --- a/src/Makefile.inc +++ b/src/Makefile.inc @@ -2,7 +2,7 @@ # 3 proxy common Makefile # -all: $(BUILDDIR)3proxy$(EXESUFFICS) $(BUILDDIR)mycrypt$(EXESUFFICS) $(BUILDDIR)pop3p$(EXESUFFICS) $(BUILDDIR)smtpp$(EXESUFFICS) $(BUILDDIR)ftppr$(EXESUFFICS) $(BUILDDIR)tcppm$(EXESUFFICS) $(BUILDDIR)udppm$(EXESUFFICS) $(BUILDDIR)socks$(EXESUFFICS) $(BUILDDIR)proxy$(EXESUFFICS) allplugins +all: $(BUILDDIR)3proxy$(EXESUFFICS) $(BUILDDIR)mycrypt$(EXESUFFICS) $(BUILDDIR)pop3p$(EXESUFFICS) $(BUILDDIR)smtpp$(EXESUFFICS) $(BUILDDIR)ftppr$(EXESUFFICS) $(BUILDDIR)tcppm$(EXESUFFICS) $(BUILDDIR)tlspr$(EXESUFFICS) $(BUILDDIR)udppm$(EXESUFFICS) $(BUILDDIR)socks$(EXESUFFICS) $(BUILDDIR)proxy$(EXESUFFICS) allplugins sockmap$(OBJSUFFICS): sockmap.c proxy.h structures.h @@ -41,6 +41,10 @@ ftppr$(OBJSUFFICS): ftppr.c proxy.h structures.h proxymain.c tcppm$(OBJSUFFICS): tcppm.c proxy.h structures.h proxymain.c $(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)PORTMAP tcppm.c +tlspr$(OBJSUFFICS): tlspr.c proxy.h structures.h proxymain.c + $(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)PORTMAP tlspr.c + + socks$(OBJSUFFICS): socks.c proxy.h structures.h proxymain.c $(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)NOPORTMAP socks.c @@ -68,6 +72,9 @@ $(BUILDDIR)socks$(EXESUFFICS): sockmap$(OBJSUFFICS) socks$(OBJSUFFICS) sockgetch $(BUILDDIR)tcppm$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tcppm$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) $(LN) $(LNOUT)$(BUILDDIR)tcppm$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tcppm$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(LIBS) +$(BUILDDIR)tlspr$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tlspr$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) + $(LN) $(LNOUT)$(BUILDDIR)tlspr$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tlspr$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(LIBS) + $(BUILDDIR)udppm$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) udppm$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) $(LN) $(LNOUT)$(BUILDDIR)udppm$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) udppm$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(LIBS) @@ -91,6 +98,9 @@ srvftppr$(OBJSUFFICS): ftppr.c proxy.h structures.h srvtcppm$(OBJSUFFICS): tcppm.c proxy.h structures.h $(CC) $(COUT)srvtcppm$(OBJSUFFICS) $(CFLAGS) tcppm.c +srvtlspr$(OBJSUFFICS): tlspr.c proxy.h structures.h + $(CC) $(COUT)srvtlspr$(OBJSUFFICS) $(CFLAGS) tlspr.c + srvauto$(OBJSUFFICS): auto.c proxy.h structures.h $(CC) $(COUT)srvauto$(OBJSUFFICS) $(CFLAGS) auto.c @@ -146,6 +156,6 @@ ntlm$(OBJSUFFICS): ntlm.c stringtable$(OBJSUFFICS): stringtable.c $(CC) $(COUT)stringtable$(OBJSUFFICS) $(CFLAGS) stringtable.c -$(BUILDDIR)3proxy$(EXESUFFICS): 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) auth$(OBJSUFFICS) authradius$(OBJSUFFICS) conf$(OBJSUFFICS) log$(OBJSUFFICS) datatypes$(OBJSUFFICS) md4$(OBJSUFFICS) md5$(OBJSUFFICS) mycrypt$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) smbdes$(OBJSUFFICS) ntlm$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) $(COMPATLIBS) $(VERSIONDEP) - $(LN) $(LNOUT)$(BUILDDIR)3proxy$(EXESUFFICS) $(LDFLAGS) $(VERFILE) 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) auth$(OBJSUFFICS) authradius$(OBJSUFFICS) conf$(OBJSUFFICS) datatypes$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) mycrypt$(OBJSUFFICS) md5$(OBJSUFFICS) md4$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) smbdes$(OBJSUFFICS) ntlm$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) $(COMPATLIBS) $(LIBS) +$(BUILDDIR)3proxy$(EXESUFFICS): 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) auth$(OBJSUFFICS) authradius$(OBJSUFFICS) conf$(OBJSUFFICS) log$(OBJSUFFICS) datatypes$(OBJSUFFICS) md4$(OBJSUFFICS) md5$(OBJSUFFICS) mycrypt$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) smbdes$(OBJSUFFICS) ntlm$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) $(COMPATLIBS) $(VERSIONDEP) + $(LN) $(LNOUT)$(BUILDDIR)3proxy$(EXESUFFICS) $(LDFLAGS) $(VERFILE) 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) auth$(OBJSUFFICS) authradius$(OBJSUFFICS) conf$(OBJSUFFICS) datatypes$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) mycrypt$(OBJSUFFICS) md5$(OBJSUFFICS) md4$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) smbdes$(OBJSUFFICS) ntlm$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) $(COMPATLIBS) $(LIBS) diff --git a/src/auth.c b/src/auth.c index 716870f..4e1e363 100644 --- a/src/auth.c +++ b/src/auth.c @@ -302,6 +302,9 @@ int handleredirect(struct clientparam * param, struct ace * acentry){ case R_SMTP: param->redirectfunc = smtppchild; break; + case R_TLS: + param->redirectfunc = tlsprchild; + break; default: param->redirectfunc = proxychild; } diff --git a/src/conf.c b/src/conf.c index 724d408..2f353b9 100644 --- a/src/conf.c +++ b/src/conf.c @@ -238,6 +238,13 @@ static int h_proxy(int argc, unsigned char ** argv){ childdef.service = S_TCPPM; childdef.helpmessage = ""; } + else if(!strcmp((char *)argv[0], "tlspr")) { + childdef.pf = tlsprchild; + childdef.port = 1443; + childdef.isudp = 0; + childdef.service = S_TLSPR; + childdef.helpmessage = ""; + } else if(!strcmp((char *)argv[0], "udppm")) { childdef.pf = udppmchild; childdef.port = 0; @@ -756,6 +763,7 @@ static int h_parent(int argc, unsigned char **argv){ else if(!strcmp((char *)argv[2], "socks4b"))chains->type = R_SOCKS4B; else if(!strcmp((char *)argv[2], "socks5b"))chains->type = R_SOCKS5B; else if(!strcmp((char *)argv[2], "pop3"))chains->type = R_POP3; + else if(!strcmp((char *)argv[2], "tls"))chains->type = R_TLS; else if(!strcmp((char *)argv[2], "ftp"))chains->type = R_FTP; else if(!strcmp((char *)argv[2], "admin"))chains->type = R_ADMIN; else if(!strcmp((char *)argv[2], "extip"))chains->type = R_EXTIP; @@ -1618,8 +1626,9 @@ struct commands commandhandlers[]={ {commandhandlers+63, "parentretries", h_parentretries, 2, 2}, {commandhandlers+64, "auto", h_proxy, 1, 0}, {commandhandlers+65, "backlog", h_backlog, 2, 2}, + {commandhandlers+66, "tlspr", h_proxy, 1, 0}, #ifndef NORADIUS - {commandhandlers+66, "radius", h_radius, 3, 0}, + {commandhandlers+67, "radius", h_radius, 3, 0}, #endif {specificcommands, "", h_noop, 1, 0} }; diff --git a/src/plugins.c b/src/plugins.c index 36b62a4..c1146a4 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -68,13 +68,15 @@ struct symbol symbols[] = { {symbols+41, "admin", (void *) adminchild}, {symbols+42, "ftppr", (void *) ftpprchild}, {symbols+43, "smtpp", (void *) smtppchild}, - {symbols+44, "authfuncs", (void *) &authfuncs}, - {symbols+45, "commandhandlers", (void *) &commandhandlers}, - {symbols+46, "decodeurl", (void *) decodeurl}, - {symbols+47, "parsestr", (void *) parsestr}, - {symbols+48, "make_ace", (void *) make_ace}, - {symbols+49, "freeacl", (void *) freeacl}, - {symbols+50, "handleredirect", (void *) handleredirect}, + {symbols+44, "auto", (void *) smtppchild}, + {symbols+45, "tlspr", (void *) smtppchild}, + {symbols+46, "authfuncs", (void *) &authfuncs}, + {symbols+47, "commandhandlers", (void *) &commandhandlers}, + {symbols+48, "decodeurl", (void *) decodeurl}, + {symbols+49, "parsestr", (void *) parsestr}, + {symbols+50, "make_ace", (void *) make_ace}, + {symbols+51, "freeacl", (void *) freeacl}, + {symbols+52, "handleredirect", (void *) handleredirect}, {NULL, "", NULL} }; diff --git a/src/proxy.h b/src/proxy.h index fdcfab9..983678d 100644 --- a/src/proxy.h +++ b/src/proxy.h @@ -297,6 +297,7 @@ void * autochild(struct clientparam * param); void * udppmchild(struct clientparam * param); void * adminchild(struct clientparam * param); void * ftpprchild(struct clientparam * param); +void * tlsprchild(struct clientparam * param); struct datatype; diff --git a/src/proxymain.c b/src/proxymain.c index 1d188af..e0612cd 100644 --- a/src/proxymain.c +++ b/src/proxymain.c @@ -383,6 +383,9 @@ int MODULEMAINFUNC (int argc, char** argv){ case 'p': *SAPORT(&srv.intsa) = htons(atoi(argv[i]+2)); break; + case 'P': + srv.targetport = ntohs(atoi(argv[i]+2)); + break; case '4': case '6': srv.family = atoi(argv[i]+1); @@ -414,6 +417,10 @@ int MODULEMAINFUNC (int argc, char** argv){ case 'h': hostname = argv[i] + 2; break; + case 'c': + srv.requirecert = 1; + if(isdigit(argv[i][2])) srv.requirecert = atoi(argv[i]+2); + break; case 'r': cbc_string = (unsigned char *)mystrdup(argv[i] + 2); iscbc = 1; diff --git a/src/socks.c b/src/socks.c index 4dbdbb7..6220dca 100644 --- a/src/socks.c +++ b/src/socks.c @@ -18,7 +18,7 @@ unsigned char * commands[] = {(unsigned char *)"UNKNOWN", (unsigned char *)"CONN static void printcommand(unsigned char * buf, int command, struct clientparam *param){ sprintf((char *)buf, "%s ", commands[command]); if(param->hostname){ - sprintf((char *)buf + strlen((char *)buf), "%.265s", param->hostname); + sprintf((char *)buf + strlen((char *)buf), "%.256s", param->hostname); } else myinet_ntop(*SAFAMILY(¶m->req), SAADDR(¶m->req), (char *)buf + strlen((char *)buf), 64); diff --git a/src/structures.h b/src/structures.h index 9705f1d..a2f5ba7 100644 --- a/src/structures.h +++ b/src/structures.h @@ -168,10 +168,10 @@ typedef enum { typedef enum { - S_NOSERVICE, + S_NOSERVICE = 0, S_PROXY, S_TCPPM, - S_POP3P, + S_POP3P = 3, S_SOCKS4 = 4, /* =4 */ S_SOCKS5 = 5, /* =5 */ S_UDPPM, @@ -184,7 +184,8 @@ typedef enum { S_REVLI, S_REVCO, S_ZOMBIE, - S_AUTO + S_AUTO, + S_TLSPR }PROXYSERVICE; struct clientparam; @@ -279,7 +280,8 @@ typedef enum { R_SOCKS4B, R_SOCKS5B, R_ADMIN, - R_EXTIP + R_EXTIP, + R_TLS } REDIRTYPE; struct chain { @@ -487,6 +489,7 @@ struct srvparam { int anonymous; int clisockopts, srvsockopts, lissockopts, cbcsockopts, cbssockopts; int gracetraf, gracenum, gracedelay; + int requirecert; #ifdef WITHSPLICE int usesplice; #endif diff --git a/src/tlspr.c b/src/tlspr.c new file mode 100644 index 0000000..b337ecf --- /dev/null +++ b/src/tlspr.c @@ -0,0 +1,292 @@ +/* + 3APA3A simpliest proxy server + (c) 2002-2021 by Vladimir Dubrovin <3proxy@3proxy.org> + + please read License Agreement + +*/ + +#include "proxy.h" + +#ifndef PORTMAP +#define PORTMAP +#endif +#define RETURN(xxx) { param->res = xxx; goto CLEANRET; } + +unsigned size16(unsigned char *buf){ + unsigned res; + res = (((unsigned)buf[0]) << 8) + +buf[1]; + return res; +} + +int readtls(struct clientparam *param, int direction, unsigned char *buf, int bufsize){ + int res = 0; + int len; + + if(bufsize < 3) return -1; + res = sockgetlinebuf(param, direction, buf, 3, EOF, conf.timeouts[STRING_S]); + if(res !=3 || buf[0] != 22 || buf[1] != 3) return -2; + len = size16(buf+3); + if((len+3) > bufsize) return -3; + res = sockgetlinebuf(param, direction, buf+3, len, EOF, conf.timeouts[STRING_S]); + if(res != len) return -4; + return len+3; +} + +#define BSIZE (4096) +#define SNILEN (256) +#define PROTOLEN (32) + + +int parsehello(int type, unsigned char *hello, int len, unsigned char *sni, int *lv, unsigned char * proto){ + int hlen; + unsigned offset; + int slen; + int cslen; + int elen; + int snllen, snlen, alpnlen; + int snifound=0; + + if(len < 64) return -1; + if(hello[5] != type) return -2; + if(hello[6] != 0) return -3; + hlen = size16(hello+7); + if((hlen+9) != len) return -4; + offset = 9; + if(hello[offset] != 3) return -5; + *lv = hello[offset+1]; + offset += 34; + slen = hello[offset]; + if((offset + slen + 3) > len) return -6; + offset += (slen+1); + if(type == 1){ + cslen = size16(hello+offset); + if((offset + cslen + 3) > len) return -7; + offset += (cslen+2); + cslen = hello[offset]; + if((offset + cslen + 3) > len) return -8; + offset += (cslen+1); + } + else if(type == 2){ + offset += 3; + } + elen = size16(hello+offset); + offset += 2; + if(elen+offset != len) return -9; + while(elen > 1){ + int xlen; + xlen = size16(hello+offset+2); + if(xlen+4 > elen) return -10; + if(type == 1 && hello[offset] == 0 && hello[offset+1] == 0){ + snllen=size16(hello+offset+4); + if(snllen>3){ + if(snllen+2 != xlen) return -12; + if(hello[offset+6] != 0) return -13; + snlen=size16(hello+offset+7); + if(snlen + 3 > snllen) return -14; + if(snlen+1 > SNILEN) return -15; + memcpy(sni, hello + offset + 9, snlen); + sni[snlen] = 0; + snifound = snlen; + } + } + else if(hello[offset] == 0 && hello[offset+1] == 43){ + if(xlen>2){ + *lv = hello[offset+6]; + } + else if(xlen==2){ + *lv = hello[offset+5]; + } + } + else if(hello[offset] == 0 && hello[offset+1] == 16){ + alpnlen=hello[offset+6]; + if(alpnlen+7>elen) return -16; + if(alpnlen+1>PROTOLEN) return -17; + memcpy(proto, hello+offset+7, alpnlen); + proto[alpnlen] = 0; + } + offset += (xlen+4); + elen -= (xlen+4); + } + return snifound; +} + +int tlstobufcli(struct clientparam *param, int offset){ + int len, newlen; + if(!param->clibuf){ + if(!(param->clibuf = myalloc(SRVBUFSIZE))) return -1; + param->clibufsize = SRVBUFSIZE; + param->clioffset = param->cliinbuf = 0; + } + if(param->srvinbuf != param->srvoffset){ + len = socksend(param, param->clisock, param->srvbuf+param->srvoffset,param->srvinbuf-param->srvoffset, conf.timeouts[STRING_S]); + if(len != param->srvinbuf-param->srvoffset){ + return -2; + } + param->srvinbuf = param->srvoffset = 0; + } + len = sockfillbuffcli(param, 5, conf.timeouts[STRING_S]); + if(len < 5) return -2; + if(param->clibuf[1] != 3) { + return -3; + } + else { + len = 5 + size16(param->clibuf+3); + if(len > param->clibufsize) return -4; + for(newlen=param->cliinbuf; newlen < len; newlen=param->cliinbuf){ + sockfillbuffcli(param, len, conf.timeouts[STRING_S]); + if(param->cliinbuf <= newlen) return -5; + } + } + return len; +} + +int tlstobufsrv(struct clientparam *param, int offset){ + int len, newlen; + + if(param->cliinbuf != param->clioffset){ + len = socksend(param, param->remsock, param->clibuf+param->clioffset,param->cliinbuf-param->clioffset, conf.timeouts[STRING_S]); + if(len != param->cliinbuf-param->clioffset){ + return -1; + } + param->cliinbuf = param->clioffset = 0; + } + if(!param->srvbuf){ + if(!(param->srvbuf = myalloc(SRVBUFSIZE))) return -1; + param->srvbufsize = SRVBUFSIZE; + param->srvoffset = param->srvinbuf = 0; + } + len = sockfillbuffsrv(param, offset+5, conf.timeouts[STRING_S]); + if(len < offset+5) return -3; + if(param->srvbuf[offset+1] != 3) { + return -4; + } + else { + len = offset + 5 + size16(param->srvbuf+offset+3); + if(len > param->srvbufsize) return -5; + for(newlen=param->srvinbuf; newlen < len; newlen=param->srvinbuf){ + sockfillbuffsrv(param, len, conf.timeouts[STRING_S]); + if(param->srvinbuf <= newlen) return -6; + } + } + return len-offset; +} + +void * tlsprchild(struct clientparam* param) { + int res; + unsigned char sni[SNILEN]; + char req[SNILEN+PROTOLEN+16]; + int lv=-1; + unsigned char proto[PROTOLEN]="-"; + + res = tlstobufcli(param, 0); + if(res <= 0 || param->clibuf[0] != 22){ + if(param->srv->requirecert)RETURN(300-res); + } + else { + lv = param->clibuf[2]; + res = parsehello(1, param->clibuf, res, sni, &lv, proto); + if(res > 0){ + if(param->hostname){ + myfree(param->hostname); + param->hostname = NULL; + } + else if (parsehostname(sni, param, param->srv->targetport? param->srv->targetport:443)) RETURN (100); + if (!param->hostname)param->hostname = mystrdup((char *)sni); + } + else if (res < 0 && param->srv->requirecert) RETURN(310-res); + } + param->operation = CONNECT; + param->redirectfunc = NULL; + res = (*param->srv->authfunc)(param); + if(res) {RETURN(res);} + if (param->npredatfilters){ + int action; + action = handlepredatflt(param); + if(action == HANDLED){ + RETURN(0); + } + if(action != PASS) RETURN(19); + } + if(param->redirectfunc && param->redirectfunc != tlsprchild){ + return (*param->redirectfunc)(param); + } + + if(param->srv->requirecert > 1){ + res = tlstobufsrv(param, 0); + if(res <= 0 || param->srvbuf[0] != 22) RETURN(340-res); + lv = param->srvbuf[2]; + res = parsehello(2, param->srvbuf, res, sni, &lv, proto); + if (res < 0) RETURN(350-res); + } + if(param->srv->requirecert > 2){ + if(lv > 3) RETURN(370); + int srvcert=0, clicert=0, reqcert=0, len, rlen, done; + for(done=0;!done;) { + len = param->srvinbuf; + if(socksend(param, param->clisock, param->srvbuf,len, conf.timeouts[STRING_S]) != len) RETURN(371); + param->srvinbuf = 0; + res = tlstobufsrv(param, 0); + if(res <= 0) RETURN(380-res); + if(param->srvbuf[0]!= 22) break; + switch(param->srvbuf[5]){ + case 11: + /* process server certificates here */ + if(param->srvbuf[6]||param->srvbuf[7]||param->srvbuf[8]>64) srvcert = 1; + break; + case 13: + reqcert = 1; + break; + case 14: + done = 1; + break; + default: + break; + } + } + if(!srvcert) RETURN(373); + if(param->srv->requirecert > 3){ + if(!reqcert) RETURN(374); + for(done=0;!done;) { + res = tlstobufcli(param, 0); + if(res <= 0) RETURN(390-res); + len = res; + if(param->clibuf[0]!= 22) break; + switch(param->clibuf[5]){ + case 11: + /* process client certificates here */ + if(param->clibuf[6]||param->clibuf[7]||param->clibuf[8]>64)clicert = 1; + break; + case 14: + done = 1; + break; + default: + break; + } + if(done) break; + if(socksend(param, param->remsock, param->clibuf,len, conf.timeouts[STRING_S]) != len) RETURN(375); + param->cliinbuf = 0; + } + if(!clicert) RETURN(375); + } + } + + RETURN (mapsocket(param, conf.timeouts[CONNECTION_L])); +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?param->hostname:"-", proto); + dolog(param, req); + freeparam(param); + return (NULL); +} + +#ifdef WITHMAIN +struct proxydef childdef = { + tlsprchild, + 1443, + 0, + S_TLSPR, + "" +}; +#include "proxymain.c" +#endif