Exemple #1
0
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);
}
Exemple #2
0
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;
}
Exemple #3
0
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;
}
Exemple #4
0
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;
}
Exemple #5
0
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;
}
Exemple #6
0
/* 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;
}
Exemple #7
0
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;
}
Exemple #8
0
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;
}
Exemple #9
0
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;
}
Exemple #10
0
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;
}
Exemple #11
0
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;
}
Exemple #12
0
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;
}
Exemple #13
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;
}
Exemple #14
0
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;
}
Exemple #15
0
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);
}
Exemple #16
0
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;
}
Exemple #17
0
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;
}
Exemple #18
0
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;
}