static void do_forward(Connection *Conn,PCStr(lport),PCStr(peername),int shared,int svsock,int priority,int fromC,int toC) { int cls,svs; CStr(host,MaxHostNameLen); int port; CStr(opt,256); CStr(clntname,1024); CStr(servname,1024); CStr(sockname,1024); if( svsock < 0 ){ SockPrintf(toC,"%s %d no socket to accept\r\n",VER,NO_ACCEPT); return; } SockPrintf(toC,"%s %d forwarding start.\r\n",VER,OK_FORWARD1); opt[0] = 0; Xsscanf(peername,"%[^:]:%d %s",AVStr(host),&port,AVStr(opt)); for(;;){ cls = do_accept(lport,"",shared,priority,fromC,toC); if( cls < 0 ){ if( 0 < PollIn(fromC,1) ){ if( intcom("",fromC,toC,NULL,NULL) == 0 ) continue; else break; } SockPrintf(toC,"%s %d could not accept at %s\r\n", VER,NO_ACCEPT,lport); break; } getpairName(cls,AVStr(sockname),AVStr(clntname)); SockPrintf(toC,"%s %d accepted %s %s\r\n",VER,OK_ACCEPT, sockname,clntname); svs = Socket1("VSAPdata",NEWSOCK,VStrANYPORT,host,port, 0,NULL,0); if( svs < 0 ){ SockPrintf(toC,"%s %d could not connect to %s\r\n", VER,NO_CONNECT,peername); break; }else{ if( strstr(opt,"TRACE") ){ getpairName(svs,AVStr(sockname),AVStr(servname)); SockPrintf(cls,"%s %d %s %s connected.\r\n", VER,OK_CONNECT,sockname,servname); SockPrintf(svs,"%s %d %s %s accepted.\r\n", VER,OK_ACCEPT,sockname,clntname); } relay2_cntl(60*1000,cls,svs,svs,cls,fromC,toC,(IFUNCP)intcom,0); close(svs); SockPrintf(toC,"%s %d relay done.\r\n",VER,OK_RELAYED); } close(cls); } SockPrintf(toC,"%s %d forwarding done.\r\n",VER,OK_FORWARD2); }
int CTX_VSAPconnect(Connection *Conn,PVStr(sockname),PVStr(peername)) { CStr(resp,1024); int rsock; int cid; int acode; rsock = open_vsap(Conn,FOR_HTCONNECT); if( 0 <= rsock ){ rsock = ConnectViaHTTP(Conn,rsock,0, BVStr(sockname),BVStr(peername)); if( 0 <= rsock ){ goto EXIT; } return -1; } rsock = open_vsap(Conn,FOR_CONNECT); if( rsock < 0 ) return -1; if( elnumof(Socknames) <= rsock ){ close(rsock); return -1; } if( sockname[0] != 0 ){ SockPrintf(rsock,"%s BIND %s\r\n",VER,sockname); RecvLine(rsock,resp,sizeof(resp)); } SockPrintf(rsock,"%s CONNECT %s\r\n",VER,peername); if( RecvLine(rsock,resp,sizeof(resp)) <= 0 ){ close(rsock); return -1; } daemonlog("D","VSAPd says: %s",resp); if( !resp_OK(resp) ){ close(rsock); return -1; } SockPrintf(rsock,"RELAY\r\n"); Xsscanf(resp,"%*s %*d %d %s %s connected.",&cid,AVStr(sockname),AVStr(peername)); EXIT: sv1log("-- VSAPconnect[%d][%s][%s]\n",rsock,sockname,peername); Socknames[rsock] = stralloc(sockname); Peernames[rsock] = stralloc(peername); return rsock; }
static int do_connect(int lsock,PCStr(rport),int toC) { CStr(host,MaxHostNameLen); int port; int clsock; CStr(sockname,MaxHostNameLen); CStr(peername,MaxHostNameLen); int wcc; int sockid; if( rport[0] == '/' ){ clsock = client_open_un("vsap",rport,60); daemonlog("E","## CLPORT %s [%d]\n",rport,clsock); if( clsock < 0 ){ wcc = SockPrintf(toC,"%s %d not connected\r\n",VER,NO_BIND); return -1; } strcpy(sockname,rport); strcpy(peername,rport); goto CONNECTED; } strcpy(host,"127.0.0.1"); port = 0; if( strchr(rport,':') ) Xsscanf(rport,"%[^:]:%d",AVStr(host),&port); else sscanf(rport,"%d",&port); clsock = Socket1("VSAP",lsock,NULL,NULL,NULL,VStrANYPORT,host,port,0,NULL,0); if( clsock < 0 ){ wcc = SockPrintf(toC,"%s %d cannot connect %s\r\n", VER,NO_CONNECT,rport); return -1; } getpairName(clsock,AVStr(sockname),AVStr(peername)); CONNECTED: sockid = add_clsock(clsock); wcc = SockPrintf(toC,"%s %d %d %s %s connected.\r\n", VER,OK_CONNECT,sockid,sockname,rport); return clsock; }
int SMTP_data(int sock, char smtp_mode) /* send a "DATA" message to the SMTP listener */ { int ok; SockPrintf(sock,"DATA\r\n"); if (outlevel >= O_MONITOR) report(stdout, "%cMTP> DATA\n", smtp_mode); ok = SMTP_ok(sock, smtp_mode, TIMEOUT_DATA); return ok; }
int SMTP_quit(int sock, char smtp_mode) /* send a "QUIT" message to the SMTP listener */ { int ok; SockPrintf(sock,"QUIT\r\n"); if (outlevel >= O_MONITOR) report(stdout, "%cMTP> QUIT\n", smtp_mode); ok = SMTP_ok(sock, smtp_mode, TIMEOUT_DEFAULT); return ok; }
/* XXX: this must not be used for LMTP! */ int SMTP_helo(int sock, char smtp_mode, const char *host) /* send a "HELO" message to the SMTP listener */ { int ok; SockPrintf(sock,"HELO %s\r\n", host); if (outlevel >= O_MONITOR) report(stdout, "%cMTP> HELO %s\n", smtp_mode, host); ok = SMTP_ok(sock, smtp_mode, TIMEOUT_HELO); return ok; }
int SMTP_rcpt(int sock, char smtp_mode, const char *to) /* send a "RCPT TO:" message to the SMTP listener */ { int ok; SockPrintf(sock,"RCPT TO:<%s>\r\n", to); if (outlevel >= O_MONITOR) report(stdout, "%cMTP> RCPT TO:<%s>\n", smtp_mode, to); ok = SMTP_ok(sock, smtp_mode, TIMEOUT_RCPT); return ok; }
int SMTP_ehlo(int sock, char smtp_mode, const char *host, char *name, char *password, int *opt) /* send a "EHLO" message to the SMTP listener, return extension status bits */ { struct opt *hp; char auth_response[511]; SIGHANDLERTYPE alrmsave; const int tmout = (mytimeout >= TIMEOUT_HELO ? mytimeout : TIMEOUT_HELO); SockPrintf(sock,"%cHLO %s\r\n", (smtp_mode == 'S') ? 'E' : smtp_mode, host); if (outlevel >= O_MONITOR) report(stdout, "%cMTP> %cHLO %s\n", smtp_mode, (smtp_mode == 'S') ? 'E' : smtp_mode, host); alrmsave = set_signal_handler(SIGALRM, null_signal_handler); set_timeout(tmout); *opt = 0; while ((SockRead(sock, smtp_response, sizeof(smtp_response)-1)) != -1) { size_t n; set_timeout(0); (void)set_signal_handler(SIGALRM, alrmsave); n = strlen(smtp_response); if (n > 0 && smtp_response[n-1] == '\n') smtp_response[--n] = '\0'; if (n > 0 && smtp_response[n-1] == '\r') smtp_response[--n] = '\0'; if (n < 4) return SM_ERROR; smtp_response[n] = '\0'; if (outlevel >= O_MONITOR) report(stdout, "%cMTP< %s\n", smtp_mode, smtp_response); for (hp = extensions; hp->name; hp++) if (!strncasecmp(hp->name, smtp_response+4, strlen(hp->name))) { *opt |= hp->value; if (strncmp(hp->name, "AUTH ", 5) == 0) strncpy(auth_response, smtp_response, sizeof(auth_response)); auth_response[sizeof(auth_response)-1] = '\0'; } if ((smtp_response[0] == '1' || smtp_response[0] == '2' || smtp_response[0] == '3') && smtp_response[3] == ' ') { if (*opt & ESMTP_AUTH) SMTP_auth(sock, smtp_mode, name, password, auth_response); return SM_OK; } else if (smtp_response[3] != '-') return SM_ERROR; alrmsave = set_signal_handler(SIGALRM, null_signal_handler); set_timeout(tmout); } return SM_UNRECOVERABLE; }
static int intcom(PCStr(arg),int src,int dst,int *rccp,int *wccp) { int rcc,wcc,rcode; CStr(req,1024); daemonlog("E","## intcom: %d->d\n",src,dst); rcc = RecvLine(src,req,sizeof(req)); if( rcc <= 0 ) return -1; if( rccp ) *rccp = rcc; rcode = 0; wcc = SockPrintf(dst,"%s %d interrupted by \"%s\"",VER,OK_ACCEPT,req); if( strncasecmp(req,"BREAK",5) == 0 ) rcode = -1; return rcode; }
int SMTP_eom(int sock, char smtp_mode) /* send a message data terminator to the SMTP listener */ { SockPrintf(sock,".\r\n"); if (outlevel >= O_MONITOR) report(stdout, "%cMTP>. (EOM)\n", smtp_mode); /* * When doing LMTP, must process many of these at the outer level. */ if (smtp_mode == 'S') return SMTP_ok(sock, smtp_mode, TIMEOUT_EOM); else return SM_OK; }
int open_vsap(Connection *Conn,int method) { int rsock; int ri; const char *host; int port; if( serverX == 0 ) return -1; rsock = -1; for( ri = 0; ri < serverX; ri++ ){ if( acceptedViaVSAP == 0 ) if( (serverV[ri].r_methods & method) == 0 ) continue; if( method == FOR_HTACCEPT ) if( serverV[ri].r_methods & FOR_HTACCEPT ){ return 1; } host = serverV[ri].r_host; port = serverV[ri].r_port; rsock = -1; if( method & (FOR_HTBIND|FOR_HTCONNECT) ){ rsock = connectViaUpper(Conn,"VSAP","http",host,port); } if( rsock < 0 ) rsock = Socket1("VSAP",NEWSOCK,VStrANYPORT,host,port,0,NULL,0); if( 0 <= rsock ) break; } if( method & (FOR_HTCONNECT|FOR_HTBIND|FOR_HTACCEPT) ){ return rsock; } if( 0 <= rsock ){ const char *auth; CStr(authb,256); if( get_MYAUTH(Conn,AVStr(authb),"vsap",host,port) ) auth = authb; else auth = getenv("VSAP_AUTH"); if( auth ){ CStr(resp,256); SockPrintf(rsock,"%s AUTH %s\r\n",VER,auth); RecvLine(rsock,resp,sizeof(resp)); daemonlog((char*)(resp_OK(resp)?"D":"E"),"## AUTH: %s",resp); } } return rsock; }
static int vsap_permit(Connection *Conn,PCStr(portname)) { CStr(host,512); int port; host[0] = 0; port = 0; if( strchr(portname,':') ) Xsscanf(portname,"%[^:]:%d",AVStr(host),&port); else{ sscanf(portname,"%d",&port); } set_realserver(Conn,"vsap",host,port); if( service_permitted(Conn,"vsap") ) return 1; SockPrintf(ToC,"%s %d forbidden.\r\n",VER,NO_PERMISSION); return 0; }
int SMTP_from(int sock, char smtp_mode, const char *from, const char *opts) /* send a "MAIL FROM:" message to the SMTP listener */ { int ok; char buf[MSGBUFSIZE]; if (from[0]=='<') snprintf(buf, sizeof(buf), "MAIL FROM:%s", from); else snprintf(buf, sizeof(buf), "MAIL FROM:<%s>", from); if (opts) snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%s", opts); SockPrintf(sock,"%s\r\n", buf); if (outlevel >= O_MONITOR) report(stdout, "%cMTP> %s\n", smtp_mode, buf); ok = SMTP_ok(sock, smtp_mode, TIMEOUT_MAIL); return ok; }
static void SMTP_auth(int sock, char smtp_mode, char *username, char *password, char *buf) /* ESMTP Authentication support for fetchmail by Wojciech Polak */ { int c; char *p = 0; char b64buf[512]; char tmp[512]; if (!username || !password) return; memset(b64buf, 0, sizeof(b64buf)); memset(tmp, 0, sizeof(tmp)); if (strstr(buf, "CRAM-MD5")) { unsigned char digest[16]; memset(digest, 0, sizeof(digest)); if (outlevel >= O_MONITOR) report(stdout, GT_("ESMTP CRAM-MD5 Authentication...\n")); SockPrintf(sock, "AUTH CRAM-MD5\r\n"); SockRead(sock, smtp_response, sizeof(smtp_response) - 1); strlcpy(tmp, smtp_response, sizeof(tmp)); if (strncmp(tmp, "334", 3)) { /* Server rejects AUTH */ SMTP_auth_error(sock, GT_("Server rejected the AUTH command.\n")); return; } p = strchr(tmp, ' '); p++; /* (hmh) from64tobits will not NULL-terminate strings! */ if (from64tobits(b64buf, p, sizeof(b64buf) - 1) <= 0) { SMTP_auth_error(sock, GT_("Bad base64 reply from server.\n")); return; } if (outlevel >= O_DEBUG) report(stdout, GT_("Challenge decoded: %s\n"), b64buf); hmac_md5((unsigned char *)password, strlen(password), (unsigned char *)b64buf, strlen(b64buf), digest, sizeof(digest)); snprintf(tmp, sizeof(tmp), "%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", username, digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7], digest[8], digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15]); to64frombits(b64buf, tmp, strlen(tmp)); SockPrintf(sock, "%s\r\n", b64buf); SMTP_ok(sock, smtp_mode, TIMEOUT_DEFAULT); } else if (strstr(buf, "PLAIN")) { int len; if (outlevel >= O_MONITOR) report(stdout, GT_("ESMTP PLAIN Authentication...\n")); snprintf(tmp, sizeof(tmp), "^%s^%s", username, password); len = strlen(tmp); for (c = len - 1; c >= 0; c--) { if (tmp[c] == '^') tmp[c] = '\0'; } to64frombits(b64buf, tmp, len); SockPrintf(sock, "AUTH PLAIN %s\r\n", b64buf); SMTP_ok(sock, smtp_mode, TIMEOUT_DEFAULT); } else if (strstr(buf, "LOGIN")) { if (outlevel >= O_MONITOR) report(stdout, GT_("ESMTP LOGIN Authentication...\n")); SockPrintf(sock, "AUTH LOGIN\r\n"); SockRead(sock, smtp_response, sizeof(smtp_response) - 1); strlcpy(tmp, smtp_response, sizeof(tmp)); if (strncmp(tmp, "334", 3)) { /* Server rejects AUTH */ SMTP_auth_error(sock, GT_("Server rejected the AUTH command.\n")); return; } p = strchr(tmp, ' '); p++; if (from64tobits(b64buf, p, sizeof(b64buf) - 1) <= 0) { SMTP_auth_error(sock, GT_("Bad base64 reply from server.\n")); return; } to64frombits(b64buf, username, strlen(username)); SockPrintf(sock, "%s\r\n", b64buf); SockRead(sock, smtp_response, sizeof(smtp_response) - 1); strlcpy(tmp, smtp_response, sizeof(tmp)); p = strchr(tmp, ' '); if (!p) { SMTP_auth_error(sock, GT_("Bad base64 reply from server.\n")); return; } p++; memset(b64buf, 0, sizeof(b64buf)); if (from64tobits(b64buf, p, sizeof(b64buf) - 1) <= 0) { SMTP_auth_error(sock, GT_("Bad base64 reply from server.\n")); return; } to64frombits(b64buf, password, strlen(password)); SockPrintf(sock, "%s\r\n", b64buf); SMTP_ok(sock, smtp_mode, TIMEOUT_DEFAULT); } return; }
static void SMTP_auth_error(int sock, const char *msg) { SockPrintf(sock, "*\r\n"); SockRead(sock, smtp_response, sizeof(smtp_response) - 1); if (outlevel >= O_MONITOR) report(stdout, "%s", msg); }
static int do_bind(int sock,PVStr(lport),PCStr(opts),int *sharedp,PVStr(sockname),int toC) { int svsock; CStr(host,MaxHostNameLen); CStr(ports,256); int port; int nlisten; int wcc; int sockid; *sharedp = 0; host[0] = 0; ports[0] = 0; port = 0; nlisten = 0; if( lport[0] == '/' ){ svsock = server_open_un("vsap",AVStr(lport),1); daemonlog("E","## SVPORT %s [%d]\n",lport,svsock); if( svsock < 0 ){ wcc = SockPrintf(toC,"%s %d not bound-1\r\n",VER,NO_BIND); return -1; } strcpy(sockname,lport); *sharedp = 1; goto BOUND; } if( strchr(lport,':') ) Xsscanf(lport,"%[^:]:%s",AVStr(host),AVStr(ports)); else Xsscanf(lport,"%s",AVStr(ports)); port = atoi(ports); if( strncmp(opts,"-l=",3) == 0 ) nlisten = atoi(opts+3); daemonlog("D","bind: %s:%d nlisten=%d\n",host,port,nlisten); if( 0 <= (svsock = ServSockOf(host,port)) ){ daemonlog("D","## SVPORT %d\n",svsock); *sharedp = 1; }else if( 0 <= (svsock = ReservedPortSock(host,port)) ){ daemonlog("D","## RESV_PORT %d\n",svsock); *sharedp = 1; }else if( lSINGLEP() && 0 <= (svsock = findopen_port("VSAP",AVStr(host),port,nlisten)) ){ daemonlog("D","## SHARED_PORT %d\n",svsock); *sharedp = 1; }else if( 0 <= (svsock = NewPort(lport,AVStr(host),port,toC,nlisten)) ){ daemonlog("D","## NEW_PORT %d\n",svsock); *sharedp = 0; }else{ wcc = SockPrintf(toC,"%s %d not bound-2 %s\r\n",VER,NO_BIND, lport); return -1; } gethostName(svsock,AVStr(sockname),"%A:%P"); BOUND: sockid = add_svsock(svsock); wcc = SockPrintf(toC,"%s %d %d %s bound.\r\n",VER,OK_BIND, sockid,sockname); return svsock; }
static int do_accept(PCStr(lport),PCStr(opts),int shared,int priobase,int fromC,int toC) { int shlock,exlock; CStr(shlockpath,1024); CStr(exlockpath,1024); CStr(host,1024); int port; const char *op; CStr(opt1,128); int rcode; int clsock; int wcc; CStr(sockname,MaxHostNameLen); CStr(peername,MaxHostNameLen); int fi,fdv[32],rfv[32],nready; int svsock; int priority,timeout; int start; clsock = -1; if( SvSockN < 1 ){ SockPrintf(toC,"%s %d no socket to accept\r\n",VER,NO_ACCEPT); return -1; } /* repeat until accept succeed and authorization OK, * while the client's connection is alive ... */ shlock = -1; host[0] = 0; port = 0; if( strchr(host,':') ) Xsscanf(lport,"%[^:]:%d",AVStr(host),&port); else sscanf(lport,"%d",&port); priority = 0; timeout = 0; for( op = wordScan(opts,opt1); *opt1; op = wordScan(op,opt1) ){ if( strncmp(opt1,"-p=",3) == 0 ){ priority = atoi(opt1+3); }else if( strncmp(opt1,"-t=",3) == 0 ){ timeout = atoi(opt1+3); }else break; } if( priobase == 0 ) priority = 0; daemonlog("D","accept: priority=%d timeout=%d\n",priority,timeout); if( shared ){ const char *ltype; int rem; start = time(0L); shlock = PortLocks(lport,2,AVStr(shlockpath)); rcode = -1; for(;;){ if( priority ){ rcode = lock_exclusiveTO(shlock,1000,NULL); ltype = "exclusive"; }else{ rcode = lock_sharedTO(shlock,1000,NULL); ltype = "shared"; } if( !IsAlive(toC) ){ daemonlog("E","## disconnected during LOCKing\n"); goto EXIT; } if( rcode == 0 ) break; if( timeout <= time(0L) - start ) break; } rem = timeout - (time(0L) - start); if( rcode != 0 && rem <= 0 ){ daemonlog("E","## accept: timedout during %s LOCKing (%d)\n", ltype,timeout); goto EXIT; } daemonlog("D","## accept: %s LOCKed (%d)\n",ltype,timeout-rem); } daemonlog("D","## START accept at %d (%d ports)\n",port,SvSockN); for(;;){ RETRY: fdv[0] = fromC; for( fi = 1; fi <= SvSockN; fi++ ){ fdv[fi] = SvSocks[fi].a_sock; if( !shared && 0 < bind_nlisten ) Listen(fdv[fi],bind_nlisten); } nready = PollIns(timeout*1000,1+SvSockN,fdv,rfv); if( nready <= 0 ) break; if( rfv[0] != 0 && !IsAlive(fromC) ) { daemonlog("E","## disconnected during POLLing\n"); break; } svsock = -1; for( fi = 1; fi <= SvSockN; fi++ ){ if( rfv[fi] < 0 ) goto EXIT; if( 0 < rfv[fi] ){ svsock = fdv[fi]; break; } } if( svsock < 0 ) break; /* not lport but the real port-number of svsock ? */ exlock = PortLocks(lport,3,AVStr(exlockpath)); start = time(0L); rcode = -1; for(;;){ rcode = lock_exclusiveTO(exlock,1000,NULL); if( !IsAlive(toC) ){ daemonlog("E","## disconnected during ACCEPT LOCKing\n"); rcode = -1; break; } if( rcode == 0 ) break; if( timeout <= time(0L) - start ){ daemonlog("E","## timedout during ACCEPT LOCKing\n"); lock_unlock(exlock); goto RETRY; } } if( rcode == 0 ){ if( PollIn(svsock,1) <= 0 ){ daemonlog("E","## be snatched during ACCEPT LOCKing\n"); lock_unlock(exlock); goto RETRY; }else{ clsock = ACCEPT(svsock,1,-1,timeout); } } if( !shared ) closeSvSocks(); if( 0 <= exlock ) lock_unlock(exlock); if( 0 <= shlock ){ lock_unlock(shlock); shlock = -1; } break; } EXIT: if( !shared ) closeSvSocks(); if( 0 <= bind_exlock ){ lock_unlock(bind_exlock); bind_exlock = -1; } if( clsock < 0 ) daemonlog("D","## FAILED accept at %d\n",port); if( 0 <= shlock ) lock_unlock(shlock); return clsock; }
int service_vsap(Connection *Conn) { CStr(request,1024); CStr(reqver,128); const char *req; int svsock,shared,clsock,rcode; CStr(myport,256); CStr(sockname,MaxHostNameLen); CStr(peername,MaxHostNameLen); int wcc,rcc; CStr(com,1024); CStr(arg,1024); const char *argp; CStr(opt,32); const char *op; int timeout; int AuthOk; FILE *authout; minit_vsapsv(); if( ToS <= 0 || FromS <= 0 ){ /* If the DST_HOST is not local connect to the master and simple_relay... */ } if( !isMYSELF(DFLT_HOST) ){ daemonlog("E","VSAP relaying to %s:%d\n",DFLT_HOST,DFLT_PORT); if( ToS < 0 ) connect_to_serv(Conn,FromC,ToC,0); relay_svcl(Conn,FromC,ToC,FromS,ToS); close(ToS); return 0; } /* timeout = 300; */ timeout = IO_TIMEOUT; shared = 0; myport[0] = 0; SvSockN = 0; ClSockN = 0; clsock = -1; svsock = -1; reqver[0] = 0; authout = TMPFILE("VSAP-AUTH"); if( doAUTH(Conn,NULL,authout,"vsap","-",0,CVStr("user-xxxx:pass-xxxx"),CVStr("host-xxxx"),NULL,NULL) == EOF ){ AuthOk = 0; }else AuthOk = -1; if( ImMaster ){ sprintf(myport,"%s:%d",DST_HOST,DST_PORT); }else for(;;){ if( DDI_fgetsFromCbuf(Conn,AVStr(request),sizeof(request),NULL) == 0 ) { int closed = 0; for(;;){ if( PollIn(FromC,1*1000) != 0 ) break; closed |= checkCloseOnTimeout(1); if( 0 <= clsock && !IsAlive(clsock) ){ daemonlog("E","## disconnected by peer\n"); SockPrintf(ToC,"%s %d %s.\r\n",VER,NO_GENERIC_BYE,"disconnected by peer"); close(clsock);del_clsock(clsock); goto EXIT; } } if( (rcc = RecvLine(FromC,request,sizeof(request))) <= 0 ) break; } daemonlog("D","CLIENT-SAYS: %s",request); daemonlog("E","CLIENT-SAYS: %s",request); req = request; if( strncmp(req,"VSAP/",5) == 0 ) req = wordScan(req,reqver); argp = wordScan(req,com); arg[0] = 0; lineScan(argp,arg); if( strcasecmp(com,"AUTH") == 0 ){ CStr(ahost,MaxHostNameLen); ahost[0] = 0; if( doAUTH(Conn,NULL,authout,"vsap","-",0,AVStr(arg),AVStr(ahost),NULL,NULL) == EOF ){ }else{ AuthOk = 1; SockPrintf(ToC,"%s %d OK\r\n",VER,OK_GENERIC); continue; } } if( AuthOk == 0 ){ SockPrintf(ToC,"%s %d forbidden\r\n",VER,NO_PERMISSION); sv1log("WITH AUTHORIZER, but NO AUTH from client\n"); break; } if( strcasecmp(com,"ECHO") == 0 ){ CStr(stime,64); StrftimeLocal(AVStr(stime),sizeof(stime),TIMEFORM_HTTPD,time(0),0); SockPrintf(ToC,"%s %d [%s] %s\r\n",VER,OK_GENERIC, stime,arg); }else if( strcasecmp(com,"CONNECT") == 0 ){ strcpy(myport,arg); if( !vsap_permit(Conn,myport) ) break; clsock = do_connect(svsock,myport,ToC); if( clsock < 0 ) break; }else if( strcasecmp(com,"BIND") == 0 ){ CStr(opts,1024); opts[0] = 0; Xsscanf(arg,"%s %[^\r\n]",AVStr(myport),AVStr(opts)); if( !vsap_permit(Conn,myport) ) break; svsock = do_bind(-1,AVStr(myport),opts,&shared,AVStr(sockname),ToC); if( svsock < 0 ) break; }else if( strcasecmp(com,"LISTEN") == 0 ){ int nlisten = atoi(arg); Socket1("VSAP",svsock,NULL,NULL,NULL,VStrANYPORT,ANYPORT,nlisten,NULL,0); SockPrintf(ToC,"%s %d listen ok.\r\n",VER,OK_LISTEN); }else if( strcasecmp(com,"ACCEPT") == 0 ){ int priority; if( Conn->cl_count <= 1 ) priority = 0; else priority = 1; clsock = do_accept(myport,arg,shared,priority,FromC,ToC); if( !shared ) svsock = -1; if( clsock < 0 ){ wcc = SockPrintf(ToC,"%s %d accept fail\r\n", VER,NO_ACCEPT); break; } add_clsock(clsock); if( myport[0] == '/' ){ strcpy(sockname,myport); strcpy(peername,myport); }else getpairName(clsock,AVStr(sockname),AVStr(peername)); wcc = SockPrintf(ToC,"%s %d %d %s %s accepted.\r\n", VER,OK_ACCEPT,ClSockN,sockname,peername); }else if( strcasecmp(com,"QUIT") == 0 ){ SockPrintf(ToC,"%s %d bye.\r\n",VER,OK_BYE); break; }else if( strcasecmp(com,"FORWARD") == 0 ){ do_forward(Conn,myport,arg,shared,svsock,0,FromC,ToC); }else if( strcasecmp(com,"RELAY") == 0 ){ /* -t timeout */ for( op = arg; *op == '-'; ){ if( strneq(op,"-t=",3) ){ int to; op = numscanX(op+3,AVStr(opt),sizeof(opt)); to = atoi(opt); if( to < timeout ) timeout = to; }else{ break; } } tcp_relay2(timeout*1000,FromC,clsock,clsock,ToC); /* set_linger(clsock,10); */ set_linger(clsock,LIN_TIMEOUT); close(clsock);del_clsock(clsock); break; }else if( strcasecmp(com,"PROXY") == 0 ){ ToS = FromS = ToC; ToC = FromC = clsock; daemonlog("E","##### VSAP switch protocol to '%s'\n",arg); if( strcmp(arg,"http")==0 ) service_http(Conn); else if( strcmp(arg,"ftp")==0 ) service_ftp(Conn); set_linger(clsock,10); close(clsock);del_clsock(clsock); break; }else { /* wcc = write(clsock,req,rcc); tcp_relay2(timeout*1000,FromC,clsock,clsock,ToC); */ SockPrintf(ToC,"%s %d %s",VER,NO_GENERIC,request); } } EXIT: fclose(authout); return 0; }