Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package hylafax+ for openSUSE:Factory checked in at 2022-12-27 11:55:04
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/hylafax+ (Old)
and /work/SRC/openSUSE:Factory/.hylafax+.new.1563 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "hylafax+"
Tue Dec 27 11:55:04 2022 rev:43 rq:1045467 version:7.0.6
Changes:
--------
--- /work/SRC/openSUSE:Factory/hylafax+/hylafax+.changes 2022-06-08 14:24:48.932494525 +0200
+++ /work/SRC/openSUSE:Factory/.hylafax+.new.1563/hylafax+.changes 2022-12-27 11:55:15.227378608 +0100
@@ -1,0 +2,15 @@
+Mon Dec 26 15:10:02 UTC 2022 - Axel Braun
+
+- version 7.0.6
+ * add support for libtiff v4.4 (10 Jun 2022)
+ * libtiff44.diff removed
+ * cope with SSL Fax senders who skip Phase C (5 May 2022)
+ * add ability to trace SSL Fax data reception (3 May 2022)
+ * handle timeout OK response to +FRH=3 and +FRM=n (25 Apr 2022)
+ * don't leave the modem waiting for a response when in SSL Fax (25 Apr 2022)
+ * improve recovery from unexpected SSL Fax terminations during ECM (15, 18, 26 Apr 2022)
+ * try to cope with false "no dialtone" results (4, 8 Apr 2022)
+ * add initial support for SSL Fax Proxy servers (4, 23 Feb; 4, 19 Apr; 10, 24 Jun 2022)
+ * buildrequirement for libssl added (Thanks Dimstar)
+
+-------------------------------------------------------------------
Old:
----
hylafax-7.0.5.tar.gz
libtiff44.diff
New:
----
hylafax-7.0.6.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ hylafax+.spec ++++++
--- /var/tmp/diff_new_pack.9D8tp4/_old 2022-12-27 11:55:15.983382813 +0100
+++ /var/tmp/diff_new_pack.9D8tp4/_new 2022-12-27 11:55:15.991382857 +0100
@@ -19,7 +19,7 @@
%global faxspool %{_localstatedir}/spool/hylafax
%define lib_version %(echo %{version} | tr \. _)
Name: hylafax+
-Version: 7.0.5
+Version: 7.0.6
Release: 0
Summary: A fax server
License: BSD-3-Clause
@@ -41,8 +41,6 @@
Source15: hylafax-service.xml
Source16: hylafax-helper.xml
-Patch0: libtiff44.diff
-
BuildRequires: firewalld
BuildRequires: gcc-c++
BuildRequires: ghostscript
@@ -56,6 +54,7 @@
# needed together with devel for proper configure detection
BuildRequires: tiff
BuildRequires: pkgconfig(lcms2)
+BuildRequires: pkgconfig(libssl)
BuildRequires: pkgconfig(libtiff-4)
BuildRequires: pkgconfig(systemd)
BuildRequires: pkgconfig(zlib)
@@ -107,8 +106,6 @@
%prep
%setup -q -n hylafax-%{version}
-%autopatch -p1
-
cp %{SOURCE8} .
cp %{SOURCE9} .
++++++ hylafax-7.0.5.tar.gz -> hylafax-7.0.6.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hylafax-7.0.5/CHANGES new/hylafax-7.0.6/CHANGES
--- old/hylafax-7.0.5/CHANGES 2021-12-05 05:53:43.000000000 +0100
+++ new/hylafax-7.0.6/CHANGES 2022-06-24 21:36:27.000000000 +0200
@@ -2,6 +2,17 @@
New Changes
+* add support for libtiff v4.4 (10 Jun 2022)
+* cope with SSL Fax senders who skip Phase C (5 May 2022)
+* add ability to trace SSL Fax data reception (3 May 2022)
+* handle timeout OK response to +FRH=3 and +FRM=n (25 Apr 2022)
+* don't leave the modem waiting for a response when in SSL Fax (25 Apr 2022)
+* improve recovery from unexpected SSL Fax terminations during ECM (15, 18, 26 Apr 2022)
+* try to cope with false "no dialtone" results (4, 8 Apr 2022)
+* add initial support for SSL Fax Proxy servers (4, 23 Feb; 4, 19 Apr; 10, 24 Jun 2022)
+
+(7.0.5)
+
* extend Class1RecvAbortOK = 0 timeout to 500 ms (4 Dec 2021)
* cope with Si2435 V.34/V.8 connection glitch (17, 19 Nov 2021)
* cope with spurious +FCERROR or other delayed messages from modem (26 Oct 2021)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hylafax-7.0.5/VERSION new/hylafax-7.0.6/VERSION
--- old/hylafax-7.0.5/VERSION 2021-09-08 04:03:25.000000000 +0200
+++ new/hylafax-7.0.6/VERSION 2022-02-23 23:56:08.000000000 +0100
@@ -1 +1 @@
-7.0.5
+7.0.6
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hylafax-7.0.5/configure new/hylafax-7.0.6/configure
--- old/hylafax-7.0.5/configure 2021-07-25 23:16:27.000000000 +0200
+++ new/hylafax-7.0.6/configure 2022-06-10 16:21:28.000000000 +0200
@@ -2583,7 +2583,7 @@
echo '#define TIFFSTRIPBYTECOUNTS uint32_t'
echo '#define TIFFVERSION TIFF_VERSION'
echo '#define TIFFHEADER TIFFHeader';;
- 4.[0123]) tiff_runlen_t="uint32_t"
+ 4.[01234]) tiff_runlen_t="uint32_t"
tiff_offset_t="uint64_t"
echo '#define TIFFSTRIPBYTECOUNTS uint64_t'
echo '#define TIFFVERSION TIFF_VERSION_CLASSIC'
@@ -2625,7 +2625,7 @@
Incompatible TIFF Library.
HylaFAX ${VERSION} requires TIFF software distribution versions 3.4 through
-4.0. If you do not have up to date TIFF software on your system
+4.4. If you do not have up to date TIFF software on your system
then you can retrieve it from the location where you obtained this software.
The Home Page for version 3.5 and later is http://www.remotesensing.org/libtiff/
EOF
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hylafax-7.0.5/etc/faxsetup.sh.in new/hylafax-7.0.6/etc/faxsetup.sh.in
--- old/hylafax-7.0.5/etc/faxsetup.sh.in 2021-10-12 21:39:04.000000000 +0200
+++ new/hylafax-7.0.6/etc/faxsetup.sh.in 2022-06-09 01:48:18.000000000 +0200
@@ -2128,7 +2128,7 @@
echo
fi
if isOK "$ok"; then
- $OPENSSL req -x509 -nodes -days 9999 -newkey rsa:1024 -keyout $DIR_SPOOL/etc/ssl.pem -out $DIR_SPOOL/etc/ssl.pem
+ $OPENSSL req -x509 -nodes -days 9999 -newkey rsa:2048 -keyout $DIR_SPOOL/etc/ssl.pem -out $DIR_SPOOL/etc/ssl.pem
$CHOWN $faxUID $DIR_SPOOL/etc/ssl.pem; $CHGRP $faxGID $DIR_SPOOL/etc/ssl.pem
else
echo "Skipping creation of etc/ssl.pem for SSL Fax."
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hylafax-7.0.5/faxd/Class1.c++ new/hylafax-7.0.6/faxd/Class1.c++
--- old/hylafax-7.0.5/faxd/Class1.c++ 2021-12-05 05:52:46.000000000 +0100
+++ new/hylafax-7.0.6/faxd/Class1.c++ 2022-05-05 18:37:22.000000000 +0200
@@ -311,8 +311,8 @@
useSSLFax = false;
isSSLFax = false;
suppressSSLFax = false;
+ usingSSLFaxProxy = false;
setSSLFaxFd(0);
- if (sslWatchModem) abortReceive();
sslWatchModem = false;
wasSSLFax = true;
}
@@ -382,6 +382,7 @@
isSSLFax = false;
wasSSLFax = false;
suppressSSLFax = false;
+ usingSSLFaxProxy = false;
remoteCSAinfo = "";
sslFaxPasscode = randomString(10);
remoteCSAType = 0x00;
@@ -410,6 +411,7 @@
isSSLFax = false;
wasSSLFax = false;
suppressSSLFax = false;
+ usingSSLFaxProxy = false;
sslRcvCC = sslRcvNext = sslRcvBit = sslGotByte = 0;
sslSawBlockEnd = false;
sslWatchModem = false;
@@ -538,7 +540,7 @@
* T.30 5.3.6.2.12.
*/
void
-Class1Modem::encodeCSA(fxStr& binary, const fxStr& ascii)
+Class1Modem::encodeCSA(fxStr& binary, const fxStr& ascii, bool haspasscode)
{
u_int n = ascii.length();
if (n > 60) {
@@ -547,8 +549,10 @@
return;
}
fxStr url = ascii;
- url.insert('@');
- url.insert(sslFaxPasscode);
+ if (!haspasscode) {
+ url.insert('@');
+ url.insert(sslFaxPasscode);
+ }
url.insert("ssl://");
n = url.length();
u_int i, j = 0;
@@ -719,8 +723,8 @@
protoTrace("SSL FAX WRITE ERROR: %s", (const char*) sslFaxProcess.emsg);
useSSLFax = false;
isSSLFax = false;
+ usingSSLFaxProxy = false;
setSSLFaxFd(0);
- if (sslWatchModem) abortReceive();
sslWatchModem = false;
wasSSLFax = true;
params.br = storedBitrate;
@@ -750,6 +754,7 @@
if (wasSSLFax) {
// the abort already happened
wasSSLFax = false;
+ setTimeout(false);
return;
}
bool b = wasTimeout();
@@ -817,13 +822,16 @@
SSLFax sfp;
int r = sfp.read(sslFaxProcess, buf, 1, (sslWatchModem ? getModemFd() : 0), (ms ? ms : 60000));
if (r > 0) {
+ if (getSSLFaxTracing()) protoTrace("--> SSL Fax <%u:%.2X>", r, (buf[0] & 0xFF));
+ memmove(sslFaxPastData, sslFaxPastData+1, 10);
+ sslFaxPastData[10] = buf[0] & 0xFF;
return (buf[0] & 0xFF);
}
protoTrace("SSL FAX READ ERROR: %s", (const char*) sslFaxProcess.emsg);
useSSLFax = false;
isSSLFax = false;
+ usingSSLFaxProxy = false;
setSSLFaxFd(0);
- if (r != -1 && sslWatchModem) abortReceive();
sslWatchModem = false;
wasSSLFax = true;
params.br = storedBitrate;
@@ -866,8 +874,11 @@
}
// enable this to simulate a VERY noisy connection
// if (((int) Sys::now() & 1) && ((random() % 10000)/10000.0) > 0.95) return (1);
- if (sslGotByte == EOF) return (EOF);
- else if (sslGotByte & (0x80 >> --sslRcvBit)) return (1);
+ if (sslGotByte == EOF) {
+ sslSawBlockEnd = true;
+ sawBlockEnd();
+ return (EOF);
+ } else if (sslGotByte & (0x80 >> --sslRcvBit)) return (1);
else return (0);
}
@@ -1760,7 +1771,7 @@
}
}
} while (((u_int) Sys::now()-start < howmany(conf.t1Timer, 1000)) && !wasTimeout() &&
- (lastResponse == AT_FCERROR || lastResponse == AT_NOCARRIER || (lastResponse == AT_ERROR && onhooks <= conf.class1HookSensitivity)));
+ (lastResponse == AT_FCERROR || lastResponse == AT_NOCARRIER || lastResponse == AT_OK || (lastResponse == AT_ERROR && onhooks <= conf.class1HookSensitivity)));
}
if (readPending) {
stopTimeout("waiting for HDLC flags");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hylafax-7.0.5/faxd/Class1.h new/hylafax-7.0.6/faxd/Class1.h
--- old/hylafax-7.0.5/faxd/Class1.h 2021-07-25 23:16:27.000000000 +0200
+++ new/hylafax-7.0.6/faxd/Class1.h 2022-05-05 18:37:22.000000000 +0200
@@ -143,8 +143,10 @@
bool isSSLFax; // whether or not SSL Fax handshaking succeeded
bool wasSSLFax; // whether or not SSL Fax handshaking succeeded before
bool suppressSSLFax; // whether or not to suspend SSL Fax for this session
+ bool usingSSLFaxProxy; // whether or not an SSL Fax proxy is used
fxStr remoteCSAinfo; // remote CSA string (host:port)
u_char remoteCSAType; // remote CSA type
+ u_char sslFaxPastData[11]; // most recent 11 bytes of received SSL Fax data
#if defined(HAVE_SSL)
SSLFaxProcess sslFaxProcess;// contains data about SSL Fax process
#endif
@@ -200,7 +202,7 @@
virtual bool atCmd(const fxStr& cmd, ATResponse = AT_OK, long ms = 30*1000);
bool switchingPause(fxStr& emsg, u_int times = 1);
void encodeTSI(fxStr& binary, const fxStr& ascii);
- void encodeCSA(fxStr& binary, const fxStr& ascii);
+ void encodeCSA(fxStr& binary, const fxStr& ascii, bool haspasscode);
void encodeNSF(fxStr& binary, const fxStr& ascii);
const fxStr& decodeTSI(fxStr& ascii, const HDLCFrame& binary);
const fxStr& decodeCSA(fxStr& ascii, const HDLCFrame& binary);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hylafax-7.0.5/faxd/Class1Recv.c++ new/hylafax-7.0.6/faxd/Class1Recv.c++
--- old/hylafax-7.0.5/faxd/Class1Recv.c++ 2021-10-20 01:11:46.000000000 +0200
+++ new/hylafax-7.0.6/faxd/Class1Recv.c++ 2022-06-10 17:43:32.000000000 +0200
@@ -584,7 +584,7 @@
if (sslFaxProcess.emsg != "") protoTrace("SSL Fax: \"%s\"", (const char*) sslFaxProcess.emsg);
if (!sslFaxProcess.server) {
protoTrace("SSL Fax connection failed.");
- if (!conf.class1SSLFaxInfo.length()) useSSLFax = false;
+ if (!conf.class1SSLFaxInfo.length() && !conf.class1SSLFaxProxy.length()) useSSLFax = false;
} else {
protoTrace("SSL Fax connection was successful.");
ok = true;
@@ -748,7 +748,7 @@
if (sslFaxProcess.emsg != "") protoTrace("SSL Fax: \"%s\"", (const char*) sslFaxProcess.emsg);
if (!sslFaxProcess.server) {
protoTrace("SSL Fax connection failed.");
- if (!conf.class1SSLFaxInfo.length()) useSSLFax = false;
+ if (!conf.class1SSLFaxInfo.length() && !conf.class1SSLFaxProxy.length()) useSSLFax = false;
} else {
protoTrace("SSL Fax connection was successful.");
isSSLFax = true;
@@ -757,9 +757,38 @@
}
}
- if (!isSSLFax && useSSLFax && conf.class1SSLFaxInfo.length()) {
+ if (!isSSLFax && useSSLFax && (conf.class1SSLFaxInfo.length() || conf.class1SSLFaxProxy.length())) {
SSLFax sslfax;
- sslFaxProcess = sslfax.startServer(conf.class1SSLFaxInfo, conf.class1SSLFaxCert);
+ fxStr info = conf.class1SSLFaxInfo;
+ bool haspasscode = false;
+ if (conf.class1SSLFaxInfo.length()) {
+ sslFaxProcess = sslfax.startServer(conf.class1SSLFaxInfo, conf.class1SSLFaxCert);
+ } else {
+ u_int atpos = conf.class1SSLFaxProxy.next(0, '@');
+ fxStr passcode;
+ if (atpos < conf.class1SSLFaxProxy.length()) {
+ passcode = conf.class1SSLFaxProxy.extract(0, atpos);
+ } else {
+ passcode = "";
+ atpos = -1;
+ }
+ fxStr hostport = conf.class1SSLFaxProxy.extract(atpos+1, conf.class1SSLFaxProxy.length()-atpos-1);
+ protoTrace("Connecting to SSL Fax Proxy %s", (const char*) conf.class1SSLFaxProxy);
+
+ sslFaxProcess = sslfax.startClient(hostport, passcode, rtcRev, conf.class1SSLFaxServerTimeout);
+ if (sslFaxProcess.server) {
+ info = "";
+ haspasscode = true;
+ char buf[2];
+ int r;
+ do {
+ r = sslfax.read(sslFaxProcess, buf, 1, 0, 1000);
+ if (r > 0 && buf[0] != 0) info.append( buf[0]&0xFF );
+ } while (r > 0 && (buf[0]&0xFF) != 0);
+ protoTrace("Proxy SSL Fax info: \"%s\"", (const char*) info);
+ usingSSLFaxProxy = true;
+ }
+ }
if (sslFaxProcess.emsg.length()) protoTrace("SSL Fax: \"%s\"", (const char*) sslFaxProcess.emsg);
if (sslFaxProcess.server == 0 ) {
setSSLFaxFd(0);
@@ -767,7 +796,7 @@
}
if (useSSLFax) {
fxStr csa;
- encodeCSA(csa, conf.class1SSLFaxInfo);
+ encodeCSA(csa, info, haspasscode);
protoTrace("Send CSA frame to accept HylaFAX SSL fax feature.");
startTimeout(7550);
transmitFrame(FCF_CSA|FCF_RCVR, csa, false);
@@ -846,7 +875,7 @@
do {
(void) atCmd(rmCmd, AT_NOTHING);
rmResponse = atResponse(rbuf, conf.class1RMPersistence ? conf.t2Timer + 2900 : conf.t2Timer - 2900);
- } while ((rmResponse == AT_NOTHING || rmResponse == AT_FCERROR) && ++attempts < conf.class1RMPersistence && !getSSLFaxConnection());
+ } while ((rmResponse == AT_NOTHING || rmResponse == AT_FCERROR || rmResponse == AT_OK) && ++attempts < conf.class1RMPersistence && !getSSLFaxConnection());
#if defined(HAVE_SSL)
if (useSSLFax) {
SSLFax sslfax;
@@ -857,19 +886,23 @@
sslWatchModem = false;
setSSLFaxFd(0);
} else {
- protoTrace("SSL Fax connection detected.");
- sslfax.acceptClient(sslFaxProcess, sslFaxPasscode, getModemFd(), conf.class1SSLFaxClientTimeout);
- if (sslFaxProcess.emsg != "") protoTrace("SSL Fax accept client: %s", (const char*) sslFaxProcess.emsg);
+ if (!usingSSLFaxProxy) {
+ protoTrace("SSL Fax connection detected.");
+ sslfax.acceptClient(sslFaxProcess, sslFaxPasscode, getModemFd(), conf.class1SSLFaxClientTimeout);
+ if (sslFaxProcess.emsg != "") protoTrace("SSL Fax accept client: %s", (const char*) sslFaxProcess.emsg);
+ }
+ sslWatchModem = false;
+ setSSLFaxFd(0);
if (!sslFaxProcess.server) {
protoTrace("SSL Fax client accept failure. Expecting a traditional fax now.");
sslfax.cleanup(sslFaxProcess);
useSSLFax = false;
- sslWatchModem = false;
- setSSLFaxFd(0);
do {
rmResponse = atResponse(rbuf, conf.class1RMPersistence ? conf.t2Timer + 2900 : conf.t2Timer - 2900);
} while ((rmResponse == AT_NOTHING || rmResponse == AT_FCERROR) && ++attempts < conf.class1RMPersistence && atCmd(rmCmd, AT_NOTHING));
} else {
+ abortReceive();
+ setSSLFaxFd(sslFaxProcess.server);
isSSLFax = true;
storedBitrate = params.br;
params.br = BR_SSLFAX;
@@ -1470,7 +1503,7 @@
do {
(void) atCmd(rmCmd, AT_NOTHING);
lastResponse = atResponse(rbuf, conf.class1RMPersistence ? conf.t2Timer + 2900 : conf.t2Timer - 2900);
- } while ((lastResponse == AT_NOTHING || lastResponse == AT_FCERROR) && ++attempts < conf.class1RMPersistence && !getSSLFaxConnection());
+ } while ((lastResponse == AT_NOTHING || lastResponse == AT_FCERROR || lastResponse == AT_OK) && ++attempts < conf.class1RMPersistence && !getSSLFaxConnection());
#if defined(HAVE_SSL)
if (useSSLFax) {
SSLFax sslfax;
@@ -1481,19 +1514,23 @@
sslWatchModem = false;
setSSLFaxFd(0);
} else {
- protoTrace("SSL Fax connection detected.");
- sslfax.acceptClient(sslFaxProcess, sslFaxPasscode, getModemFd(), conf.class1SSLFaxClientTimeout);
- if (sslFaxProcess.emsg != "") protoTrace("SSL Fax accept client: %s", (const char*) sslFaxProcess.emsg);
+ if (!usingSSLFaxProxy) {
+ protoTrace("SSL Fax connection detected.");
+ sslfax.acceptClient(sslFaxProcess, sslFaxPasscode, getModemFd(), conf.class1SSLFaxClientTimeout);
+ if (sslFaxProcess.emsg != "") protoTrace("SSL Fax accept client: %s", (const char*) sslFaxProcess.emsg);
+ }
+ sslWatchModem = false;
+ setSSLFaxFd(0);
if (!sslFaxProcess.server) {
protoTrace("SSL Fax client accept failure. Expecting a traditional fax now.");
sslfax.cleanup(sslFaxProcess);
useSSLFax = false;
- sslWatchModem = false;
- setSSLFaxFd(0);
do {
lastResponse = atResponse(rbuf, conf.class1RMPersistence ? conf.t2Timer + 2900 : conf.t2Timer - 2900);
} while ((lastResponse == AT_NOTHING || lastResponse == AT_FCERROR) && ++attempts < conf.class1RMPersistence && atCmd(rmCmd, AT_NOTHING));
} else {
+ abortReceive();
+ setSSLFaxFd(sslFaxProcess.server);
isSSLFax = true;
storedBitrate = params.br;
params.br = BR_SSLFAX;
@@ -1633,17 +1670,20 @@
sslWatchModem = false;
setSSLFaxFd(0);
} else {
- protoTrace("SSL Fax connection detected.");
- sslfax.acceptClient(sslFaxProcess, sslFaxPasscode, getModemFd(), conf.class1SSLFaxClientTimeout);
- if (sslFaxProcess.emsg != "") protoTrace("SSL Fax accept client: %s", (const char*) sslFaxProcess.emsg);
+ if (!usingSSLFaxProxy) {
+ protoTrace("SSL Fax connection detected.");
+ sslfax.acceptClient(sslFaxProcess, sslFaxPasscode, getModemFd(), conf.class1SSLFaxClientTimeout);
+ if (sslFaxProcess.emsg != "") protoTrace("SSL Fax accept client: %s", (const char*) sslFaxProcess.emsg);
+ }
+ sslWatchModem = false;
+ setSSLFaxFd(0);
if (!sslFaxProcess.server) {
protoTrace("SSL Fax client accept failure. Expecting a traditional fax now.");
sslfax.cleanup(sslFaxProcess);
useSSLFax = false;
- sslWatchModem = false;
- setSSLFaxFd(0);
gotprimary = waitForDCEChannel(false); // resume V.34-Fax session
} else {
+ setSSLFaxFd(sslFaxProcess.server);
isSSLFax = true;
storedBitrate = params.br;
params.br = BR_SSLFAX;
@@ -1933,7 +1973,7 @@
}
} else {
dataseen = true; // assume that garbage was meant to be data
- if (wasTimeout()) break;
+ if (wasTimeout() || sslSawBlockEnd) break;
if (isSSLFax || !useV34) syncECMFrame();
if ((!isSSLFax && useV34) && (gotEOT || gotCTRL)) rcpcnt = 3;
}
@@ -1966,7 +2006,7 @@
}
}
}
- if (!isSSLFax && !useV34) {
+ if (!isSSLFax && !useV34 && !sslSawBlockEnd) {
// wait for message carrier to drop
time_t nocarrierstart = Sys::now();
bool gotnocarrier = false;
@@ -1976,6 +2016,8 @@
} while (!gotnocarrier && lastResponse != AT_EMPTYLINE && Sys::now() < (nocarrierstart + 5));
}
bool gotpps = false;
+ sslSawBlockEnd = false;
+ wasSSLFax = false;
HDLCFrame ppsframe(conf.class1FrameOverhead);
u_short recvFrameCount = 0;
do {
@@ -1998,9 +2040,17 @@
* believe that we've hung up. This latter option seems the
* least likely to be problematic, so that's what we're doing.
*/
- u_int br = useV34 ? primaryV34Rate : curcap->br + 1;
- long wait = br >= 1 && br <= 15 ? 273066 / br : conf.t2Timer;
- gotpps = recvFrame(ppsframe, FCF_RCVR, wait, false, false); // wait longer, no CRP
+ if (isSSLFax && fcount == 0 && rcpcnt == 1 && sslFaxPastData[0] == 0xFF && sslFaxPastData[1] == 0x13 && sslFaxPastData[2] == 0xBF) {
+ // For some reason the sender has skipped over Phase C data and sent PPS. Cope as best we can.
+ protoTrace("The sender seems to have skipped Phase C.");
+ for (u_int i = 0; i < 9; i++) ppsframe.put(frameRev[sslFaxPastData[i] & 0xFF]);
+ traceHDLCFrame("-->", ppsframe);
+ gotpps = true;
+ } else {
+ u_int br = useV34 ? primaryV34Rate : curcap->br + 1;
+ long wait = br >= 1 && br <= 15 ? 273066 / br : conf.t2Timer;
+ gotpps = recvFrame(ppsframe, FCF_RCVR, wait, false, false); // wait longer, no CRP
+ }
} while (!gotpps && gotCONNECT && !wasTimeout() && !gotEOT && ++recvFrameCount < 5);
if (gotpps) {
traceFCF("RECV recv", ppsframe.getFCF());
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hylafax-7.0.5/faxd/Class1Send.c++ new/hylafax-7.0.6/faxd/Class1Send.c++
--- old/hylafax-7.0.5/faxd/Class1Send.c++ 2021-11-19 15:29:34.000000000 +0100
+++ new/hylafax-7.0.6/faxd/Class1Send.c++ 2022-04-26 01:33:13.000000000 +0200
@@ -928,12 +928,42 @@
if (!frameSent)
return (false);
#if defined(HAVE_SSL)
- if (!suppressSSLFax && !isSSLFax && conf.class1SSLFaxSupport && conf.class1SSLFaxInfo.length() && \
+ if (!suppressSSLFax && !isSSLFax && conf.class1SSLFaxSupport && \
+ (conf.class1SSLFaxInfo.length() || conf.class1SSLFaxProxy.length()) && \
(dis_caps.features & FaxParams::FEATURE_SSLFAX || (dis_caps.isBitEnabled(FaxParams::BITNUM_T37) && dis_caps.isBitEnabled(FaxParams::BITNUM_T38)))) {
// We can't trust T.38 support indications to indicate that the remote device actually supports TSA frames.
useSSLFax = true;
SSLFax sslfax;
- sslFaxProcess = sslfax.startServer(conf.class1SSLFaxInfo, conf.class1SSLFaxCert);
+ fxStr info = conf.class1SSLFaxInfo;
+ bool haspasscode = false;
+ if (conf.class1SSLFaxInfo.length()) {
+ sslFaxProcess = sslfax.startServer(conf.class1SSLFaxInfo, conf.class1SSLFaxCert);
+ } else {
+ int atpos = conf.class1SSLFaxProxy.next(0, '@');
+ fxStr passcode;
+ if (atpos < conf.class1SSLFaxProxy.length()) {
+ passcode = conf.class1SSLFaxProxy.extract(0, atpos);
+ } else {
+ passcode = "";
+ atpos = -1;
+ }
+ fxStr hostport = conf.class1SSLFaxProxy.extract(atpos+1, conf.class1SSLFaxProxy.length()-atpos-1);
+ protoTrace("Connecting to SSL Fax Proxy %s", (const char*) conf.class1SSLFaxProxy);
+
+ sslFaxProcess = sslfax.startClient(hostport, passcode, rtcRev, conf.class1SSLFaxServerTimeout);
+ if (sslFaxProcess.server) {
+ info = "";
+ haspasscode = true;
+ char buf[2];
+ int r;
+ do {
+ r = sslfax.read(sslFaxProcess, buf, 1, 0, 1000);
+ if (r > 0 && buf[0] != 0) info.append( buf[0]&0xFF );
+ } while (r > 0 && (buf[0]&0xFF) != 0);
+ protoTrace("Proxy SSL Fax info: \"%s\"", (const char*) info);
+ usingSSLFaxProxy = true;
+ }
+ }
if (sslFaxProcess.emsg.length()) protoTrace("SSL Fax: \"%s\"", (const char*) sslFaxProcess.emsg);
if (sslFaxProcess.server == 0 ) {
setSSLFaxFd(0);
@@ -941,7 +971,7 @@
}
if (useSSLFax) {
fxStr tsa;
- encodeCSA(tsa, conf.class1SSLFaxInfo);
+ encodeCSA(tsa, info, haspasscode);
protoTrace("Sending TSA frame to initiate HylaFAX SSL fax feature.");
startTimeout(7550);
frameSent = sendFrame(FCF_TSA|FCF_SNDR, tsa, false);
@@ -1174,18 +1204,21 @@
sslWatchModem = false;
setSSLFaxFd(0);
} else {
- protoTrace("SSL Fax connection detected.");
- sslfax.acceptClient(sslFaxProcess, sslFaxPasscode, getModemFd(), conf.class1SSLFaxClientTimeout);
- if (sslFaxProcess.emsg != "") protoTrace("SSL Fax accept client: %s", (const char*) sslFaxProcess.emsg);
+ if (!usingSSLFaxProxy) {
+ protoTrace("SSL Fax connection detected.");
+ sslfax.acceptClient(sslFaxProcess, sslFaxPasscode, getModemFd(), conf.class1SSLFaxClientTimeout);
+ if (sslFaxProcess.emsg != "") protoTrace("SSL Fax accept client: %s", (const char*) sslFaxProcess.emsg);
+ }
+ sslWatchModem = false;
+ setSSLFaxFd(0);
if (!sslFaxProcess.server) {
protoTrace("SSL Fax client accept failure. Proceeding with a traditional fax now.");
sslfax.cleanup(sslFaxProcess);
useSSLFax = false;
- sslWatchModem = false;
- setSSLFaxFd(0);
} else {
+ abortReceive();
+ setSSLFaxFd(sslFaxProcess.server);
isSSLFax = true;
- sslWatchModem = true;
storedBitrate = params.br;
params.br = BR_SSLFAX;
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hylafax-7.0.5/faxd/ClassModem.c++ new/hylafax-7.0.6/faxd/ClassModem.c++
--- old/hylafax-7.0.5/faxd/ClassModem.c++ 2021-10-26 21:40:18.000000000 +0200
+++ new/hylafax-7.0.6/faxd/ClassModem.c++ 2022-04-08 20:37:50.000000000 +0200
@@ -161,7 +161,19 @@
}
}
emsg = "";
- CallStatus cs = (atCmd(dialcmd, AT_NOTHING) ? dialResponse(emsg) : FAILURE);
+ int nodialtones = 0;
+ bool repeat;
+ CallStatus cs;
+ do {
+ repeat = false;
+ cs = (atCmd(dialcmd, AT_NOTHING) ? dialResponse(emsg) : FAILURE);
+ if (cs == NODIALTONE && nodialtones++ < conf.noDialtoneRetries) {
+ repeat = true;
+ sleep(1);
+ atCmd(conf.onHookCmd, AT_OK, 5000);
+ sleep(3);
+ }
+ } while (repeat);
if (cs != OK && emsg == "") {
emsg = callStatus[cs];
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hylafax-7.0.5/faxd/FaxModem.c++ new/hylafax-7.0.6/faxd/FaxModem.c++
--- old/hylafax-7.0.5/faxd/FaxModem.c++ 2021-07-25 23:16:27.000000000 +0200
+++ new/hylafax-7.0.6/faxd/FaxModem.c++ 2022-05-04 05:38:19.000000000 +0200
@@ -771,6 +771,8 @@
{ return (server.getSessionTracing() & FAXTRACE_HDLC) != 0; }
bool FaxModem::getECMTracing()
{ return (server.getSessionTracing() & FAXTRACE_ECM) != 0; }
+bool FaxModem::getSSLFaxTracing()
+ { return (server.getSessionTracing() & FAXTRACE_SSLFAX) != 0; }
void FaxModem::setSSLFaxFd(int fd)
{ server.setSSLFaxFd(fd); }
int FaxModem::getSSLFaxFd()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hylafax-7.0.5/faxd/FaxModem.h new/hylafax-7.0.6/faxd/FaxModem.h
--- old/hylafax-7.0.5/faxd/FaxModem.h 2021-07-25 23:16:27.000000000 +0200
+++ new/hylafax-7.0.6/faxd/FaxModem.h 2022-05-04 05:38:19.000000000 +0200
@@ -148,6 +148,7 @@
// server-related stuff
bool getHDLCTracing();
bool getECMTracing();
+ bool getSSLFaxTracing();
void setSSLFaxFd(int fd);
int getModemFd();
int getSSLFaxFd();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hylafax-7.0.5/faxd/FaxTrace.h new/hylafax-7.0.6/faxd/FaxTrace.h
--- old/hylafax-7.0.5/faxd/FaxTrace.h 2015-07-27 02:46:05.000000000 +0200
+++ new/hylafax-7.0.6/faxd/FaxTrace.h 2022-05-04 05:38:19.000000000 +0200
@@ -48,6 +48,7 @@
const int FAXTRACE_DOCREFS = 0x20000; // document reference handling
const int FAXTRACE_TIFF = 0x40000; // TIFF library msgs
const int FAXTRACE_ECM = 0x80000; // ECM HDLC image data frames
+const int FAXTRACE_SSLFAX = 0x100000; // SSL Fax data
const int FAXTRACE_ANY = 0xffffffff;
const int FAXTRACE_MASK = 0xfffff;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hylafax-7.0.5/faxd/Makefile.in new/hylafax-7.0.6/faxd/Makefile.in
--- old/hylafax-7.0.5/faxd/Makefile.in 2018-11-09 22:12:30.000000000 +0100
+++ new/hylafax-7.0.6/faxd/Makefile.in 2022-02-04 23:47:09.000000000 +0100
@@ -98,6 +98,8 @@
faxGettyApp.c++ \
faxQueueApp.c++ \
faxSendApp.c++ \
+ sslfaxproxy.c++ \
+ sslfaxproxytest.c++ \
tagtest.c++ \
tsitest.c++ \
pageSendApp.c++
@@ -159,7 +161,7 @@
FAXGETTYOBJS= Getty.o Getty@GETTY@.o faxGettyApp.o
TARGETS=libfaxserver.${DSO} \
faxq faxsend faxgetty pagesend faxqclean \
- tsitest tagtest cqtest choptest
+ sslfaxproxy sslfaxproxytest tsitest tagtest cqtest choptest
default all::
@${MAKE} incdepend
@@ -199,6 +201,10 @@
pagesend:${PAGESENDOBJS} libfaxserver.${DSO} ${LIBS}
${C++F} -o $@ ${PAGESENDOBJS} ${LIBFAXSERVER} ${LDFLAGS}
+sslfaxproxy: sslfaxproxy.o libfaxserver.${DSO} ${LIBS}
+ ${C++F} -o $@ sslfaxproxy.o ${LIBFAXSERVER} ${LDFLAGS}
+sslfaxproxytest: sslfaxproxytest.o libfaxserver.${DSO} ${LIBS}
+ ${C++F} -o $@ sslfaxproxytest.o ${LIBFAXSERVER} ${LDFLAGS}
tagtest: tagtest.o libfaxserver.${DSO} ${LIBS}
${C++F} -o $@ tagtest.o ${LIBFAXSERVER} ${LDFLAGS}
cqtest: cqtest.o libfaxserver.${DSO} ${LIBS}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hylafax-7.0.5/faxd/ModemConfig.c++ new/hylafax-7.0.6/faxd/ModemConfig.c++
--- old/hylafax-7.0.5/faxd/ModemConfig.c++ 2021-08-16 19:18:24.000000000 +0200
+++ new/hylafax-7.0.6/faxd/ModemConfig.c++ 2022-04-08 20:37:50.000000000 +0200
@@ -172,6 +172,7 @@
{ "tiff2faxcmd", &ModemConfig::tiff2faxCmd, FAX_TIFF2FAXCMD },
{ "class1sslfaxinfo", &ModemConfig::class1SSLFaxInfo, "" },
{ "class1sslfaxcert", &ModemConfig::class1SSLFaxCert, "etc/ssl.pem" },
+{ "class1sslfaxproxy", &ModemConfig::class1SSLFaxProxy, "" },
{ "class2recvdatatrigger", &ModemConfig::class2RecvDataTrigger },
{ "ringdata", &ModemConfig::ringData },
{ "ringfax", &ModemConfig::ringFax },
@@ -212,6 +213,7 @@
{ "modemringsbeforeresponse", &ModemConfig::ringsBeforeResponse, 0 },
{ "modemsoftresetcmddelay", &ModemConfig::softResetCmdDelay, 3000 },
{ "modemnoautoanswercmddelay", &ModemConfig::noAutoAnswerCmdDelay, 0 },
+{ "modemnodialtoneretries", &ModemConfig::noDialtoneRetries, 1 },
{ "class1tcfrecvtimeout", &ModemConfig::class1TCFRecvTimeout, 4500 },
{ "class1recvabortok", &ModemConfig::class1RecvAbortOK, 200 },
{ "class1rmpersistence", &ModemConfig::class1RMPersistence, 2 },
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hylafax-7.0.5/faxd/ModemConfig.h new/hylafax-7.0.6/faxd/ModemConfig.h
--- old/hylafax-7.0.5/faxd/ModemConfig.h 2021-08-16 19:18:24.000000000 +0200
+++ new/hylafax-7.0.6/faxd/ModemConfig.h 2022-04-08 20:37:50.000000000 +0200
@@ -167,6 +167,7 @@
bool class1SSLFaxSupport; // to enable/disable SSL Fax
fxStr class1SSLFaxInfo; // host:port information for "SSL Fax" server feature
fxStr class1SSLFaxCert; // SSL encryption certificate for "SSL Fax" feature
+ fxStr class1SSLFaxProxy; // password@host:port information for "SSL Fax" proxy
fxStr class1TCFRecvHackCmd; // cmd to avoid +FCERROR before TCF
u_int class1TCFRecvTimeout; // timeout receiving TCF
u_int class1RecvAbortOK; // if non-zero, OK sent after recv abort
@@ -255,6 +256,7 @@
u_int maxConsecutiveBadLines; // max consecutive bad lines in page
u_int minAcceptedLineCount; // min accepted number of lines in page
u_int minSpeed; // minimum speed for fax transmits
+ u_int noDialtoneRetries; // maximum number of attempts to get dialtone
bool softRTFCC; // real-time fax compression conversion (software)
bool waitForConnect; // modem sends multiple answer responses
fxStr tagLineFmt; // format string for tag lines
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hylafax-7.0.5/faxd/sslfax.c++ new/hylafax-7.0.6/faxd/sslfax.c++
--- old/hylafax-7.0.5/faxd/sslfax.c++ 2020-01-31 19:41:10.000000000 +0100
+++ new/hylafax-7.0.6/faxd/sslfax.c++ 2022-02-04 23:47:09.000000000 +0100
@@ -32,6 +32,7 @@
#include
#include "sslfax.h"
#include "Sys.h"
+#include "Socket.h"
timeval currentTime() {
timeval curTime;
@@ -89,6 +90,7 @@
addr.sin_family = AF_INET;
addr.sin_port = htons (port);
addr.sin_addr.s_addr = INADDR_ANY;
+
if (bind (sd, (struct sockaddr*)&addr, sizeof (addr)) != 0) {
emsg = fxStr::format("Can't bind port %d: %s", port, strerror(errno));
return 0;
@@ -257,7 +259,7 @@
return (SSL_pending(sfp.ssl));
}
-int SSLFax::read(SSLFaxProcess& sfp, void *buf, size_t count, int modemFd, long ms)
+int SSLFax::read(SSLFaxProcess& sfp, void *buf, size_t count, int modemFd, long ms, bool sustain, bool carryon)
{
/*
* We cannot just use select() on the socket to see if there is data waiting
@@ -326,17 +328,19 @@
}
if (!selret) {
sfp.emsg = fxStr::format("Timeout waiting for SSL Fax read (wanting to %s).", (cerror == SSL_ERROR_WANT_READ ? "read" : "write"));
- cleanup(sfp);
+ cleanup(sfp, sustain);
return (0);
} else if (selret < 0) {
sfp.emsg = fxStr::format("Error waiting for SSL Fax read (wanting to %s): %s", (cerror == SSL_ERROR_WANT_READ ? "read" : "write"), strerror(errno));
- cleanup(sfp);
+ cleanup(sfp, sustain);
return (0);
}
if (modemFd && FD_ISSET(modemFd, &rfds)) {
// The modem got a signal. This probably means that SSL Fax is not happening.
- sfp.emsg = "Modem has data when waiting for SSL Fax read. Terminating SSL Fax.";
- cleanup(sfp);
+ if (!carryon) {
+ sfp.emsg = "Modem has data when waiting for SSL Fax read. Terminating SSL Fax.";
+ cleanup(sfp, sustain);
+ }
return (-1);
}
}
@@ -348,13 +352,13 @@
} else {
sfp.emsg = fxStr::format("Unable to read from SSL Fax connection. Error %d: %s", cerror, ssl_err_string());
}
- cleanup(sfp);
+ cleanup(sfp, sustain);
return (-2);
}
return (ret);
}
-int SSLFax::write(SSLFaxProcess& sfp, const u_char *buf, u_int count, const u_char* bitrev, int modemFd, long ms, bool filter)
+int SSLFax::write(SSLFaxProcess& sfp, const u_char *buf, u_int count, const u_char* bitrev, int modemFd, long ms, bool filter, bool sustain)
{
/*
* Similar approach here as with read() above; however...
@@ -406,17 +410,17 @@
}
if (!selret) {
sfp.emsg = fxStr::format("Timeout waiting for SSL Fax write (wanting to %s).", (cerror == SSL_ERROR_WANT_READ ? "read" : "write"));
- cleanup(sfp);
+ cleanup(sfp, sustain);
return (0);
} else if (selret < 0) {
sfp.emsg = fxStr::format("Error waiting for SSL Fax write (wanting to %s): %s", (cerror == SSL_ERROR_WANT_READ ? "read" : "write"), strerror(errno));
- cleanup(sfp);
+ cleanup(sfp, sustain);
return (0);
}
if (modemFd && FD_ISSET(modemFd, &rfds)) {
// The modem got a signal. This probably means that SSL Fax is not happening.
sfp.emsg = "Modem has data when waiting for SSL Fax write. Terminating SSL Fax.";
- cleanup(sfp);
+ cleanup(sfp, sustain);
return (-1);
}
}
@@ -428,7 +432,7 @@
} else {
sfp.emsg = fxStr::format("Unable to write to SSL Fax connection. Error %d: %s", cerror, ssl_err_string());
}
- cleanup(sfp);
+ cleanup(sfp, sustain);
return (-2);
}
if (filter && buf[pos] == bitrev[16] && !isDLE) {
@@ -439,7 +443,7 @@
isDLE = false;
}
}
- return (ret);
+ return (count);
}
SSLFaxProcess SSLFax::null()
@@ -571,6 +575,9 @@
sfp.emsg = fxStr::format("Could not determine port number from \"%s\", got \"%s\".", (const char*) info, (const char*) port);
return (sfp);
}
+ // portnum = 1 is a special case for dynamic port allocation by the server
+ if (portnum == 1) portnum = 0;
+
SSL_library_init(); /* Initialize the SSL library */
sfp.ctx = InitServerCTX(); /* initialize SSL */
if (sfp.ctx == NULL) {
@@ -599,7 +606,7 @@
return (sfp);
}
-void SSLFax::acceptClient(SSLFaxProcess& sfp, fxStr passcode, int modemFd, long ms)
+bool SSLFax::acceptClient1(SSLFaxProcess& sfp, long ms, bool sustain)
{
/* Now we wait for the client to connect. */
/* We can use select() here without SSL telling us to because SSL hasn't started yet. */
@@ -610,13 +617,13 @@
tv.tv_sec = (int) ms / 1000;
tv.tv_usec = (ms % 1000)*1000;
#if CONFIG_BADSELECTPROTO
- if (!select(sfp.server+1, (int*) &sfd, NULL, NULL, &tv)) {
+ if (!select(sfp.server+1, (int*) &sfd, NULL, NULL, ms == 0 ? NULL : &tv)) {
#else
- if (!select(sfp.server+1, &sfd, NULL, NULL, &tv)) {
+ if (!select(sfp.server+1, &sfd, NULL, NULL, ms == 0 ? NULL : &tv)) {
#endif
sfp.emsg = "Timeout waiting for SSL Fax client connection.";
- cleanup(sfp);
- return;
+ cleanup(sfp, sustain);
+ return (false);
}
/* A client is waiting... */
struct sockaddr_in addr;
@@ -624,8 +631,8 @@
sfp.client = accept(sfp.server, (struct sockaddr*) &addr, &len); /* accept connection as usual */
if (fcntl(sfp.client, F_SETFL, fcntl(sfp.client, F_GETFL, 0) | O_NONBLOCK) == -1) {
sfp.emsg.append("Unable to set client SSL Fax socket to non-blocking.");
- cleanup(sfp);
- return;
+ cleanup(sfp, sustain);
+ return (false);
}
char address[50];
if (inet_ntop(addr.sin_family, &addr.sin_addr, address, 50)) {
@@ -637,6 +644,11 @@
} else {
sfp.emsg = fxStr::format("SSL Fax connection: <unknown address>:%d ", ntohs(addr.sin_port));
}
+ return (true);
+}
+
+void SSLFax::acceptClient2(SSLFaxProcess& sfp, fxStr passcode, int modemFd, long ms, bool sustain)
+{
sfp.ssl = SSL_new(sfp.ctx); /* get new SSL state with context */
SSL_set_fd(sfp.ssl, sfp.client); /* set connection socket to SSL state */
@@ -676,17 +688,17 @@
}
if (!selret) {
sfp.emsg = fxStr::format("Timeout in waiting for SSL Fax accept (wanting to %s).", (cerror == SSL_ERROR_WANT_READ ? "read" : "write"));
- cleanup(sfp);
+ cleanup(sfp, sustain);
return;
} else if (selret < 0) {
sfp.emsg = fxStr::format("Error in waiting for SSL Fax accept (wanting to %s): %s", (cerror == SSL_ERROR_WANT_READ ? "read" : "write"), strerror(errno));
- cleanup(sfp);
+ cleanup(sfp, sustain);
return;
}
if (modemFd && FD_ISSET(modemFd, &rfds)) {
// The modem got a signal. This probably means that SSL Fax is not happening.
sfp.emsg = "Modem has data when waiting for SSL Fax accept. Terminating SSL Fax.";
- cleanup(sfp);
+ cleanup(sfp, sustain);
return;
}
}
@@ -698,7 +710,7 @@
} else {
sfp.emsg = fxStr::format("Unable to accept SSL Fax connection. Error %d: %s", cerror, ssl_err_string());
}
- cleanup(sfp);
+ cleanup(sfp, sustain);
return;
}
@@ -707,12 +719,12 @@
for (u_int i = 0; i < passcode.length(); i++) {
if (read(sfp, p, 1, modemFd, 1000) <= 0) {
sfp.emsg.append(" (passcode)");
- cleanup(sfp);
+ cleanup(sfp, sustain);
return;
}
if (p[0] != passcode[i]) {
sfp.emsg.append("Invalid Passcode");
- cleanup(sfp);
+ cleanup(sfp, sustain);
return;
}
}
@@ -720,23 +732,33 @@
return;
}
-void SSLFax::cleanup(SSLFaxProcess& sfp)
+void SSLFax::acceptClient(SSLFaxProcess& sfp, fxStr passcode, int modemFd, long ms)
+{
+ if (!acceptClient1(sfp, ms)) return;
+ acceptClient2(sfp, passcode, modemFd, (ms == 0) ? 1000 : ms); // Set a reasonable timeout after our indefinite wait for a client connection.
+ return;
+}
+
+void SSLFax::cleanup(SSLFaxProcess& sfp, bool sustain)
{
- if (sfp.ctx) {
- ERR_free_strings(); /* free memory from SSL_load_error_strings */
- EVP_cleanup(); /* free memory from OpenSSL_add_all_algorithms */
- SSL_CTX_free(sfp.ctx); /* release context */
- }
- sfp.ctx = NULL;
sfp.ssl = NULL;
- if (sfp.server) {
- /*
- * This is the client. We want the client-side to shut down
- * first so that the server-side is not left with TIME_WAIT.
- * We'll get the TIME_WAIT on the client-side, and that's okay.
- */
- shutdown(sfp.server, SHUT_RDWR);
- close(sfp.server);
+ if (!sustain) {
+ if (sfp.ctx) {
+ ERR_free_strings(); /* free memory from SSL_load_error_strings */
+ EVP_cleanup(); /* free memory from OpenSSL_add_all_algorithms */
+ SSL_CTX_free(sfp.ctx); /* release context */
+ }
+ sfp.ctx = NULL;
+ if (sfp.server) {
+ /*
+ * This is the client. We want the client-side to shut down
+ * first so that the server-side is not left with TIME_WAIT.
+ * We'll get the TIME_WAIT on the client-side, and that's okay.
+ */
+ shutdown(sfp.server, SHUT_RDWR);
+ close(sfp.server);
+ }
+ sfp.server = 0;
}
if (sfp.client) {
/*
@@ -772,7 +794,6 @@
} while (!done);
close(sfp.client);
}
- sfp.server = 0;
sfp.client = 0;
return;
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hylafax-7.0.5/faxd/sslfax.h new/hylafax-7.0.6/faxd/sslfax.h
--- old/hylafax-7.0.5/faxd/sslfax.h 2020-01-31 19:41:10.000000000 +0100
+++ new/hylafax-7.0.6/faxd/sslfax.h 2022-02-04 23:47:09.000000000 +0100
@@ -58,10 +58,12 @@
SSLFaxProcess startServer(fxStr info, fxStr pemFile);
SSLFaxProcess startClient(fxStr info, fxStr passcode, const u_char* bitrev, long ms);
void acceptClient(SSLFaxProcess& sfp, fxStr passcode, int modemFd, long ms);
- void cleanup(SSLFaxProcess& sfp);
+ bool acceptClient1(SSLFaxProcess& sfp, long ms, bool sustain = false);
+ void acceptClient2(SSLFaxProcess& sfp, fxStr passcode, int modemFd, long ms, bool sustain = false);
+ void cleanup(SSLFaxProcess& sfp, bool sustain = false);
int pending(SSLFaxProcess& sfp);
- int read(SSLFaxProcess& sfp, void *buf, size_t count, int modemFd, long ms);
- int write(SSLFaxProcess& sfp, const u_char *buf, u_int count, const u_char* bitrev, int modemFd, long ms, bool eod);
+ int read(SSLFaxProcess& sfp, void *buf, size_t count, int modemFd, long ms, bool sustain = false, bool carryon = false);
+ int write(SSLFaxProcess& sfp, const u_char *buf, u_int count, const u_char* bitrev, int modemFd, long ms, bool eod, bool sustain = false);
};
#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hylafax-7.0.5/faxd/sslfaxproxy.c++ new/hylafax-7.0.6/faxd/sslfaxproxy.c++
--- old/hylafax-7.0.5/faxd/sslfaxproxy.c++ 1970-01-01 01:00:00.000000000 +0100
+++ new/hylafax-7.0.6/faxd/sslfaxproxy.c++ 2022-06-24 21:36:08.000000000 +0200
@@ -0,0 +1,268 @@
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "config.h"
+#if defined(HAVE_SSL)
+#include "Sys.h"
+#include "ClassModem.h"
+#include "sslfax.h"
+
+const u_char* bitrev = TIFFGetBitRevTable(false);
+
+void
+printlog(FILE *fp, const char *fmt, ...)
+{
+ va_list ap;
+ char buf[32];
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+ time_t tt = tv.tv_sec;
+ strftime(buf, sizeof(buf), "[%Y-%m-%d %H:%M:%S", localtime(&tt));
+ fprintf(fp, "%s.%.6ld] ", buf, tv.tv_usec);
+
+ va_start(ap, fmt);
+ vfprintf(fp, fmt, ap);
+ va_end(ap);
+ fflush(fp);
+}
+
+timeval currentTime() {
+ timeval curTime;
+ gettimeofday(&curTime, 0);
+ return curTime;
+}
+
+/*
+ * Data structure for pthread argument for SSLFax endpoint thread.
+ */
+struct sslFaxThreadData {
+ int id, rfd, wfd;
+ SSLFax* sslfax;
+ SSLFaxProcess* sfp;
+};
+
+/*
+ * Wrapper function for SSLFax endpoint thread.
+ */
+void*
+sslFaxThread(void* sd)
+{
+ sslFaxThreadData *s = (sslFaxThreadData*) sd;
+
+ if (fcntl(s->rfd, F_SETFL, fcntl(s->rfd, F_GETFL, 0) | O_NONBLOCK) == -1) {
+ printlog(stderr, "Unable to set pipe read descriptor to non-blocking.\n");
+ return (NULL);
+ }
+
+ char buf[1024];
+ int cc;
+ int loops = 0;
+ while ((cc = s->sslfax->read(*(s->sfp), buf, 1024, s->rfd, 60000, true, true)) != 0) {
+ if (cc > 0) {
+ // Write read buf data to pipe.
+ cc = Sys::write(s->wfd, buf, cc);
+ if (cc <= 0) {
+ s->sfp->emsg = "Error writing to pipe";
+ break;;
+ }
+ } else if (cc == -1) {
+ // Data is waiting to be read from pipe.
+ while ((cc = Sys::read(s->rfd, buf, 1024)) > 0) {
+ loops = 0;
+ cc = s->sslfax->write(*(s->sfp), (u_char*) buf, cc, bitrev, 0, 60000, false, true);
+ if (cc <= 0) {
+ s->sfp->emsg = "Error writing to SSL Fax client";
+ goto done;
+ }
+ }
+ if (cc <= 0) {
+ if (loops++ > 100 || cc == 0 || errno != EAGAIN) {
+ s->sfp->emsg = "Error reading from pipe";
+ break;
+ }
+ }
+ } else {
+ // Some error occurred.
+ break;
+ }
+ }
+done:
+ Sys::close(s->wfd);
+ Sys::close(s->rfd);
+ return (NULL);
+}
+
+char*
+randomString(int len)
+{
+ static char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ int cs = sizeof(charset) - 1;
+ char* rstr = (char*) malloc((len + 1) * sizeof(char));
+ for (int i = 0; i < len; i++) rstr[i] = charset[rand() % cs];
+ rstr[len] = '\0';
+ return rstr;
+}
+
+void
+pairingThread(SSLFaxProcess* sfp, const char* infohost, const char* pemfile)
+{
+ // we have a client connection for proxy-server service. Now start up the other end...
+
+ SSLFax sslfax;
+ SSLFaxProcess sslFaxProcess2 = sslfax.startServer(":1", pemfile); // "1" indicates randomly assigned port
+
+ if (sslFaxProcess2.server) {
+ struct sockaddr_in data_addr;
+ socklen_t dlen = sizeof (data_addr);
+ if (getsockname(sslFaxProcess2.server, (struct sockaddr *) &data_addr, &dlen) < 0) {
+ printlog(stderr, "getsockname(ctrl): %s\n", strerror(errno));
+ }
+
+ srand(currentTime().tv_sec);
+ const char* passcode = randomString(10);
+
+ fxStr info = fxStr::format("%s@%s:%d", passcode, infohost, ntohs(data_addr.sin_port));
+ printlog(stdout, "Listening for paired client on: %s\n", (const char*) info);
+ const char* infostr = info;
+ int cs = sslfax.write(*sfp, (const u_char*) infostr, info.length(), bitrev, 0, 60000, false);
+ u_char buf[1];
+ buf[0] = 0;
+ cs = sslfax.write(*sfp, buf, 1, bitrev, 0, 60000, false);
+
+ sslfax.acceptClient(sslFaxProcess2, passcode, 0, 120000); // 2 min timeout for connection
+ printlog(stdout, "SSL Fax accept paired client: %s\n", (const char*) sslFaxProcess2.emsg);
+
+ if (sslFaxProcess2.ssl) {
+ // Make a pretty-looking log entry describing the communication path.
+ int str1len = sfp->emsg.next(20, ' ') - 20;
+ int str2len = sslFaxProcess2.emsg.next(20, ' ') - 20;
+ if (str1len > 0 && str2len > 0) {
+ printlog(stdout, "%s <--> %s <--> %s\n", (const char*) sfp->emsg.extract(20, str1len), (const char*) info, (const char*) sslFaxProcess2.emsg.extract(20, str2len));
+ }
+
+ /*
+ * We now have two SSLFax connections, one to each client, and we need simply exchange data
+ * between them. So, we just read bytes from each connection and write them to the other.
+ * To do both concurrently we'll start up a thread and set of pipes for each and pass data
+ * between the two threads.
+ */
+ int pfd1[2]; // read communication pipe for sslFaxProcess1 ("a")
+ int pfd2[2]; // read communication pipe for sslFaxProcess2 ("b")
+ if (pipe(pfd1) >= 0 && pipe(pfd2) >= 0) {
+ pthread_t at;
+ struct sslFaxThreadData *a = (struct sslFaxThreadData *) malloc(sizeof(struct sslFaxThreadData));
+ a->id = 1;
+ a->rfd = pfd1[0];
+ a->wfd = pfd2[1];
+ a->sslfax = &sslfax;
+ a->sfp = sfp;
+ pthread_t bt;
+ struct sslFaxThreadData *b = (struct sslFaxThreadData *) malloc(sizeof(struct sslFaxThreadData));
+ b->id = 2;
+ b->rfd = pfd2[0];
+ b->wfd = pfd1[1];
+ b->sslfax = &sslfax;
+ b->sfp = &sslFaxProcess2;
+ if (pthread_create(&at, NULL, &sslFaxThread, (void *) a) != 0) {
+ printlog(stderr, "Error starting thread a.\n");
+ }
+ if (pthread_create(&bt, NULL, &sslFaxThread, (void *) b) != 0) {
+ printlog(stderr, "Error starting thread b.\n");
+ }
+
+ pthread_join(at, NULL);
+ pthread_join(bt, NULL);
+
+ sslfax.cleanup(sslFaxProcess2, false);
+
+ printlog(stdout, "Terminating connection with client on: %s\n", (const char*) info);
+ } else {
+ printlog(stderr, "Error starting communication pipes.\n");
+ }
+ } else {
+ // Connection failure message would have been shown above.
+ }
+ } else {
+ printlog(stderr, "Error creating pairing SSL Fax service: %s\n", (const char*) sslFaxProcess2.emsg);
+ }
+ return;
+}
+
+int
+main(int argc, char* argv[])
+{
+ if (argc != 4 && argc != 5) {
+ printlog(stderr, "usage: %s port passcode infohost [pemfile]\n", argv[0]);
+ exit(-1);
+ }
+ printlog(stdout, "%s started\n", argv[0]);
+ const char* pemfile;
+ if (argc == 5) pemfile = argv[4];
+ else pemfile = "/var/spool/hylafax/etc/ssl.pem";
+
+ char portstr[7];
+ snprintf(portstr, sizeof(portstr), ":%s", argv[1]);
+
+ bool repeat = true;
+
+ SSLFax sslfax;
+ SSLFaxProcess sfp = sslfax.startServer(portstr, pemfile);
+
+ do {
+ SSLFaxProcess sslFaxProcess;
+ sslFaxProcess.ctx = sfp.ctx;
+ sslFaxProcess.ssl = NULL;
+ sslFaxProcess.emsg = sfp.emsg;
+ sslFaxProcess.server = sfp.server;
+ sslFaxProcess.client = 0;
+
+ if (sslFaxProcess.server && sslfax.acceptClient1(sslFaxProcess, 0, true)) {
+
+ switch (fork()) {
+ case 0: /* child */
+ {
+ sslfax.acceptClient2(sslFaxProcess, argv[2], 0, 1000, true);
+ if (!sslFaxProcess.ssl) {
+ printlog(stderr, "Error accepting SSL Fax client: %s\n", (const char*) sslFaxProcess.emsg);
+ } else {
+ printlog(stdout, "SSL Fax accept client: %s\n", (const char*) sslFaxProcess.emsg);
+ pairingThread(&sslFaxProcess, argv[3], pemfile);
+ }
+ sslfax.cleanup(sslFaxProcess, true);
+ exit(0);
+ }
+ case -1: /* fork failure */
+ printlog(stderr, "Error forking for SSL Fax service.\n");
+ break;
+ default: /* parent */
+ close(sslFaxProcess.client); // close parent thread's handle on the forked client
+ break;
+ }
+
+ } else {
+ printlog(stderr, "Error creating primary SSL Fax service: %s\n", (const char*) sslFaxProcess.emsg);
+ sleep(60);
+ if (!sslFaxProcess.server) {
+ sfp.emsg = "";
+ sfp = sslfax.startServer(portstr, pemfile);
+ }
+ }
+ int wstatus;
+ while (waitpid(-1, &wstatus, WNOHANG) > 0); // clean up defunct child processes
+ } while (repeat);
+
+ exit (0);
+}
+#else
+int
+main(int argc, char* argv[])
+{
+ printlog(stderr, "%s not available due to lack of SSL Fax support.\n", argv[0]);
+ exit (0);
+}
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hylafax-7.0.5/faxd/sslfaxproxytest.c++ new/hylafax-7.0.6/faxd/sslfaxproxytest.c++
--- old/hylafax-7.0.5/faxd/sslfaxproxytest.c++ 1970-01-01 01:00:00.000000000 +0100
+++ new/hylafax-7.0.6/faxd/sslfaxproxytest.c++ 2022-02-04 23:47:09.000000000 +0100
@@ -0,0 +1,63 @@
+#include
+#include
+#include
+
+#include "config.h"
+#include "ClassModem.h"
+#if defined(HAVE_SSL)
+#include "sslfax.h"
+#endif
+
+const u_char* bitrev = TIFFGetBitRevTable(false);
+
+int
+main(int argc, char* argv[])
+{
+ if (argc != 3) {
+ fprintf(stderr, "usage: %s info passcode\n", argv[0]);
+ exit(-1);
+ }
+
+ SSLFax sslfax;
+ SSLFaxProcess sslFaxProcess = sslfax.startClient(argv[1], argv[2], bitrev, 1000);
+ printf("%s\n", (const char*) sslFaxProcess.emsg);
+
+ char buf[1024];
+ int r;
+ fxStr info;
+ do {
+ r = sslfax.read(sslFaxProcess, buf, 1, 0, 60000);
+ if (r > 0 && buf[0] != 0) info.append( buf[0]&0xFF );
+ } while (r > 0 && (buf[0]&0xFF) != 0);
+ printf("Got info: %s\n", (const char*) info);
+
+ int atpos = info.next(0, '@');
+ fxStr passcode = info.extract(0, atpos);
+ fxStr hostport = info.extract(atpos+1, info.length()-atpos-1);
+ printf("Connecting to %s with passcode %s\n", (const char*) hostport, (const char*) passcode);
+
+ SSLFaxProcess sslFaxProcess2 = sslfax.startClient(hostport, passcode, bitrev, 1000);
+ printf("%s\n", (const char*) sslFaxProcess2.emsg);
+
+ u_char test[7] = { 0xFF, 0x13, 0x84, 0xEA, 0x7D, 0x10, 0x03 }; // a CFR signal
+
+ do {
+
+ int cs = sslfax.write(sslFaxProcess2, test, 7, bitrev, 0, 60000, false);
+ int cc = 0;
+ while (cc < 7) {
+ int cr = sslfax.read(sslFaxProcess, buf, 1024, 0, 60000);
+ if (cr > 0) cc += cr;
+ }
+ printf("%.2X/%.2X %.2X/%.2X %.2X/%.2X %.2X/%.2X %.2X/%.2X %.2X/%.2X %.2X/%.2X\n", buf[0]&0xFF, test[0], buf[1]&0xFF, test[1], buf[2]&0xFF, test[2], buf[3]&0xFF, test[3], buf[4]&0xFF, test[4], buf[5]&0xFF, test[5], buf[6]&0xFF, test[6]);
+
+ cs = sslfax.write(sslFaxProcess, test, 7, bitrev, 0, 60000, false);
+ cc = 0;
+ while (cc < 7) {
+ int cr = sslfax.read(sslFaxProcess2, buf, 1024, 0, 60000);
+ if (cr > 0) cc += cr;
+ }
+ printf("%.2X/%.2X %.2X/%.2X %.2X/%.2X %.2X/%.2X %.2X/%.2X %.2X/%.2X %.2X/%.2X\n", buf[0]&0xFF, test[0], buf[1]&0xFF, test[1], buf[2]&0xFF, test[2], buf[3]&0xFF, test[3], buf[4]&0xFF, test[4], buf[5]&0xFF, test[5], buf[6]&0xFF, test[6]);
+
+ } while (true);
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hylafax-7.0.5/man/hylafax-config.4f new/hylafax-7.0.6/man/hylafax-config.4f
--- old/hylafax-7.0.5/man/hylafax-config.4f 2021-12-05 05:57:28.000000000 +0100
+++ new/hylafax-7.0.6/man/hylafax-config.4f 2022-05-04 05:41:00.000000000 +0200
@@ -274,6 +274,7 @@
ModemModelQueryCmd string \- command for querying modem model
ModemNoAutoAnswerCmd string \s-1ATS0=0\s+1 command for disabling auto-answer
ModemNoAutoAnswerCmdDelay integer \s-10\s+1 time, in ms, to pause after a disabling auto-answer
+ModemNoDialtoneRetries integer \s-11\s+1 maximum number of attempts to get dialtone
ModemNoFlowCmd string \- command for disabling hardware flow control between \s-1DTE\s+1 and \s-1DCE\s+1
ModemOnHookCmd string \s-1ATH0\s+1 command for placing phone ``on hook''
ModemPageDoneTimeout integer \s-1180000\s+1 page send/receive timeout (ms)
@@ -351,6 +352,7 @@
Class1SSLFaxCert string \s-1etc/ssl.pem\s+1 Class 1/1.0: PEM certificate file for SSL Fax
Class1SSLFaxClientTimeout integer \s-15000\s+1 Class 1/1.0: timeout waiting for client connection
Class1SSLFaxInfo string \- Class 1/1.0: hostname and port number for SSL Fax
+Class1SSLFaxProxy string \- Class 1/1.0: hostname and port number for SSL Fax Proxy
Class1SSLFaxSupport boolean \s-1Yes\s+1 Class 1/1.0: support for SSL Fax
Class1SSLFaxServerTimeout integer \s-12000\s+1 Class 1/1.0: timeout waiting for server connection
Class1TCFRecvHackCmd string \s-1""\s+1 Class 1/1.0: command to avoid +FCERROR before TCF
@@ -1749,6 +1751,7 @@
131072 (0x20000) Docq Changes document reference handling
262144 (0x40000) TIFF library any messages produced by the TIFF library
524288 (0x80000) ECM Frames binary \s-1T.30-A HDLC\s+1 ECM frames
+1048576 (0x100000) SSL Fax data SSL Fax data bytes
.sp .5
.fi
For example, to enable tracing of server operations and
@@ -2500,6 +2503,9 @@
before any further commands are sent to the modem. All input from
the modem is flushed after pausing.
.TP
+.B ModemNoDialtoneRetries
+The maximum number of attempts that can be made to obtain dialtone from the line when placing a call.
+.TP
.B ModemNoFlowCmd
The command to disable flow control between
.SM DTE
@@ -3115,6 +3121,16 @@
is configured for one system, then it is always dependent on the remote
systems to operate as the SSL Fax server.
.TP
+.B Class1SSLFaxProxy
+The formatted password, hostname, and port number
+(``