A lot of changes in the binkp driver

This commit is contained in:
Michiel Broek 2003-09-07 20:25:33 +00:00
parent 1cfa9dac7d
commit a4123fc91e
5 changed files with 276 additions and 215 deletions

View File

@ -58,6 +58,11 @@ v0.37.6 10-Aug-2003
For FTS-0001 sessions the mail password was used instead of the
session password. Also improved the password check.
The product code was not entered in the FTS-0001 packet headers.
The binkp driver now always reports 1.0 again.
Revised some state tables in the binkp session setup stage.
Fixed a possible buffer overflow in the binkp driver.
Fixed aborting binkp session when the remote sent a empty CRAM
password for unprotected session.
mbfido:
The rfc to ftn gate now drops the headerlines starting with

6
TODO
View File

@ -20,6 +20,8 @@ everything:
L: Implement IPv6.
L: Document error return codes in the manual.
install:
N: On some (unsupported) distro's with xinetd the installation script
also adds entries to inetd.conf.
@ -111,6 +113,10 @@ mbcico:
N: Implement binkp resync when getting files. Transmit works.
Under test now!
N: With binkp, if the other node is a binkp/1.0 mailer without MB
mode and we did send a FREQ, a poll must be created after the
session to pickup the result of the FREQ.
mbfile:
L: Add a check to see if the magic filenames are (still) valid.

View File

@ -62,7 +62,14 @@
#define BNKCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@&=+%$-_.!()#|"
static char rbuf[2048];
static char rbuf[MAX_BLKSIZE + 1];
static char *bstate[] = {
(char *)"NUL", (char *)"ADR", (char *)"PWD", (char *)"FILE", (char *)"OK",
(char *)"EOB", (char *)"GOT", (char *)"ERR", (char *)"BSY", (char *)"GET",
(char *)"SKIP"
};
/*
@ -71,7 +78,7 @@ static char rbuf[2048];
char *unix2binkp(char *);
char *binkp2unix(char *);
int binkp_expired(void);
void b_banner(int);
void b_banner(void);
void b_nul(char *);
void fill_binkp_list(binkp_list **, file_list *, off_t);
void debug_binkp_list(binkp_list **);
@ -89,6 +96,8 @@ extern char *ttystat[];
extern int Loaded;
extern pid_t mypid;
extern struct sockaddr_in peeraddr;
extern int most_debug;
extern unsigned long sentbytes;
extern unsigned long rcvdbytes;
@ -97,24 +106,25 @@ typedef enum {RxWaitFile, RxAcceptFile, RxReceData, RxWriteData, RxEndOfBatch, R
typedef enum {TxGetNextFile, TxTryRead, TxReadSend, TxWaitLastAck, TxDone} TxType;
typedef enum {InitTransfer, Switch, Receive, Transmit} TransferType;
typedef enum {Ok, Failure, Continue} TrType;
typedef enum {No, WeCan, TheyWant, Active} OptionState;
static int RxState;
static int TxState;
static int TfState;
static int RxState; /* Receiver state */
static int TxState; /* Transmitter state */
//static int TfState;
static time_t Timer;
static int NRflag = FALSE;
static int MBflag = FALSE;
static int NDflag = FALSE;
static int CRYPTflag = FALSE;
static int CRAMflag = FALSE;
static int CRCflag = FALSE;
static int Remote_1_1 = FALSE;
unsigned long nethold, mailhold;
int transferred = FALSE;
static int MBflag = WeCan; /* MB option flag */
static int CRAMflag = FALSE; /* CRAM option flag */
static int CRCflag = WeCan; /* CRC option flag */
static int Major = 1; /* Remote major protocol version */
static int Minor = 0; /* Remote minor protocol version */
static int Secure = FALSE; /* Secure session */
unsigned long nethold, mailhold; /* Trafic for the remote */
int transferred = FALSE; /* Anything transferred in batch */
int batchnr = 0, crc_errors = 0;
unsigned char *MD_challenge = NULL; /* Received CRAM challenge data */
unsigned char *MD_challenge = NULL; /* Received CRAM challenge data */
int ext_rand = 0;
int binkp(int role)
{
int rc = MBERR_OK;
@ -122,6 +132,7 @@ int binkp(int role)
file_list *tosend = NULL, *request = NULL, *respond = NULL, *tmpfl;
char *nonhold_mail;
most_debug = TRUE;
if (role == 1) {
if (orgbinkp()) {
rc = MBERR_SESSION_ERROR;
@ -137,15 +148,9 @@ int binkp(int role)
return rc;
}
/*
* Adjust file requests support. We only send requests to binkp/1.1
* systems and if file requests are not forbidden by setup.
*/
if (Remote_1_1 == FALSE)
localoptions |= NOFREQS;
if (localoptions & NOFREQS)
session_flags &= ~SESSION_WAZOO;
else
// if (localoptions & NOFREQS)
// session_flags &= ~SESSION_WAZOO;
// else
session_flags |= SESSION_WAZOO;
Syslog('b', "Binkp: WAZOO requests: %s", (session_flags & SESSION_WAZOO) ? "True":"False");
@ -174,7 +179,7 @@ int binkp(int role)
tidy_filelist(tosend, (rc == 0));
tosend = NULL;
if ((rc == 0) && transferred && MBflag) {
if ((rc == 0) && transferred && (MBflag == Active)) {
/*
* Running Multiple Batch, only if last batch actually
* did transfer some data.
@ -194,10 +199,11 @@ int binkp(int role)
Syslog('+', "Binkp: end transfer rc=%d", rc);
closetcp();
if (!MBflag) {
if (MBflag != Active) {
/*
* In singe batch mode we process filerequests after the batch.
* The results will be put on hold for the calling node.
* This method is also known as "dual session mode".
*/
respond = respond_wazoo();
for (tmpfl = respond; tmpfl; tmpfl = tmpfl->next) {
@ -321,6 +327,8 @@ void binkp_send_data(char *buf, int len)
{
unsigned short header = 0;
Syslog('B', "Binkp: send_data len=%d", len);
header = ((BINKP_DATA_BLOCK + len) & 0xffff);
PUTCHAR((header >> 8) & 0x00ff);
@ -355,6 +363,7 @@ void binkp_send_control(int id,...)
sz = 1;
}
Syslog('B', "Binkp: send_ctl %s \"%s\"", bstate[id], buf);
frame.header = ((BINKP_CONTROL_BLOCK + sz) & 0xffff);
frame.id = (char)id;
frame.data = buf;
@ -386,7 +395,7 @@ int binkp_recv_frame(char *buf, int *len, int *cmd)
*len = *cmd = 0;
b0 = GETCHAR(180);
b0 = GETCHAR(BINKP_TIMEOUT);
if (tty_status)
goto to;
if (b0 & 0x80)
@ -399,7 +408,7 @@ int binkp_recv_frame(char *buf, int *len, int *cmd)
*len = (b0 & 0x7f) << 8;
*len += b1;
GET(buf, *len, 120);
GET(buf, *len, BINKP_TIMEOUT / 2);
buf[*len] = '\0';
if (tty_status)
goto to;
@ -431,7 +440,7 @@ int binkp_expired(void)
void b_banner(int Norequests)
void b_banner(void)
{
time_t t;
@ -441,8 +450,7 @@ void b_banner(int Norequests)
binkp_send_control(MM_NUL,"NDL %s", CFG.Flags);
t = time(NULL);
binkp_send_control(MM_NUL,"TIME %s", rfcdate(t));
Syslog('b', "Binkp: M_NUL VER mbcico/%s/%s-%s binkp/1.%d", VERSION, OsName(), OsCPU(), Norequests ? 0 : 1);
binkp_send_control(MM_NUL,"VER mbcico/%s/%s-%s binkp/1.%d", VERSION, OsName(), OsCPU(), Norequests ? 0 : 1);
binkp_send_control(MM_NUL,"VER mbcico/%s/%s-%s %s/%s", VERSION, OsName(), OsCPU(), PRTCLNAME, PRTCLVER);
if (strlen(CFG.Phone))
binkp_send_control(MM_NUL,"PHN %s", CFG.Phone);
if (strlen(CFG.comment))
@ -453,6 +461,8 @@ void b_banner(int Norequests)
void b_nul(char *msg)
{
char *p, *q;
if (strncmp(msg, "SYS ", 4) == 0) {
Syslog('+', "System : %s", msg+4);
strncpy(history.system_name, msg+4, 35);
@ -468,10 +478,10 @@ void b_nul(char *msg)
Syslog('+', "Time : %s", msg+5);
else if (strncmp(msg, "VER ", 4) == 0) {
Syslog('+', "Uses : %s", msg+4);
if (strstr(msg+4, "binkp/1.1")) {
Remote_1_1 = TRUE;
} else {
Remote_1_1 = FALSE;
if ((p = strstr(msg+4, PRTCLNAME "/")) && (q = strstr(p, "."))) {
Major = atoi(p + 6);
Minor = atoi(q + 1);
Syslog('b', "Remote protocol version %d.%d", Major, Minor);
}
}
else if (strncmp(msg, "PHN ", 4) == 0)
@ -482,16 +492,8 @@ void b_nul(char *msg)
Syslog('+', "Binkp: remote has %s mail/files for us", msg+4);
else if (strncmp(msg, "OPT ", 4) == 0) {
Syslog('+', "Options : %s", msg+4);
if (strstr(msg, (char *)"NR") != NULL)
NRflag = TRUE;
if (strstr(msg, (char *)"MB") != NULL)
MBflag = TRUE;
if (strstr(msg, (char *)"ND") != NULL)
NDflag = TRUE;
if (strstr(msg, (char *)"CRYPT") != NULL) {
CRYPTflag = TRUE;
// Syslog('+', "Remote requests CRYPT mode");
}
if ((strstr(msg, (char *)"MB") != NULL) && (MBflag == WeCan))
MBflag = TheyWant;
if (strstr(msg, (char *)"CRAM-MD5-") != NULL) { /* No SHA-1 support */
if (CFG.NoMD5) {
Syslog('+', "Binkp: Remote supports MD5, but it's turned off here");
@ -501,9 +503,8 @@ void b_nul(char *msg)
MD_challenge = MD_getChallenge(msg, NULL);
}
}
if (strstr(msg, (char *)"CRC") != NULL) {
CRCflag = TRUE;
Syslog('b', "Binkp: remote supports CRC32 mode");
if ((strstr(msg, (char *)"CRC") != NULL) && (CRCflag == WeCan)) {
CRCflag = TheyWant;
}
} else
Syslog('+', "Binkp: M_NUL \"%s\"", msg);
@ -516,41 +517,50 @@ void b_nul(char *msg)
*/
SM_DECL(orgbinkp, (char *)"orgbinkp")
SM_STATES
waitconn,
sendpass,
waitaddr,
authremote,
waitok
ConnInit,
WaitConn,
SendPasswd,
WaitAddr,
AuthRemote,
IfSecure,
WaitOk,
Opts
SM_NAMES
(char *)"waitconn",
(char *)"sendpass",
(char *)"waitaddr",
(char *)"authremote",
(char *)"waitok"
(char *)"ConnInit",
(char *)"WaitConn",
(char *)"SendPasswd",
(char *)"WaitAddr",
(char *)"AuthRemote",
(char *)"IfSecure",
(char *)"WaitOk",
(char *)"Opts"
SM_EDECL
faddr *primary;
char *p, *q;
int i, rc, bufl, cmd, dupe;
char *p, *q, *pwd;
int i, rc, bufl, cmd, dupe, SendPass = FALSE;
fa_list **tmp, *tmpa;
int SendPass = FALSE;
faddr *fa, ra;
SM_START(waitconn)
SM_START(ConnInit)
SM_STATE(waitconn)
SM_STATE(ConnInit)
SM_PROCEED(WaitConn)
SM_STATE(WaitConn)
Loaded = FALSE;
Syslog('+', "Binkp: node %s", ascfnode(remote->addr, 0x1f));
IsDoing("Connect binkp %s", ascfnode(remote->addr, 0xf));
if ((noderecord(remote->addr)) && nodes.CRC32 && !CFG.NoCRC32) {
binkp_send_control(MM_NUL,"OPT MB CRC");
} else {
binkp_send_control(MM_NUL,"OPT MB");
}
if (((noderecord(remote->addr)) && nodes.NoFreqs) || CFG.NoFreqs)
b_banner(TRUE);
else
b_banner(FALSE);
p = xstrcpy((char *)"OPT");
if (MBflag == WeCan)
p = xstrcat(p, (char *)" MB");
if ((noderecord(remote->addr)) && nodes.CRC32 && !CFG.NoCRC32)
p = xstrcat(p, (char *)" CRC");
if (strcmp(p, (char *)"OPT"))
binkp_send_control(MM_NUL, p);
free(p);
b_banner();
/*
* Build a list of aka's to send, the primary aka first.
@ -577,9 +587,9 @@ SM_STATE(waitconn)
binkp_send_control(MM_ADR, "%s", p);
free(p);
tidy_faddr(primary);
SM_PROCEED(waitaddr)
SM_PROCEED(WaitAddr)
SM_STATE(waitaddr)
SM_STATE(WaitAddr)
for (;;) {
if ((rc = binkp_recv_frame(rbuf, &bufl, &cmd))) {
@ -591,22 +601,22 @@ SM_STATE(waitaddr)
if (rbuf[0] == MM_ADR) {
p = xstrcpy(&rbuf[1]);
tidy_falist(&remote);
remote = NULL;
tmp = &remote;
remote = NULL;
tmp = &remote;
for (q = strtok(p, " "); q; q = strtok(NULL, " "))
if ((fa = parsefnode(q))) {
dupe = FALSE;
for (tmpa = remote; tmpa; tmpa = tmpa->next) {
for (q = strtok(p, " "); q; q = strtok(NULL, " ")) {
if ((fa = parsefnode(q))) {
dupe = FALSE;
for (tmpa = remote; tmpa; tmpa = tmpa->next) {
if ((tmpa->addr->zone == fa->zone) && (tmpa->addr->net == fa->net) &&
(tmpa->addr->node == fa->node) && (tmpa->addr->point == fa->point) &&
(strcmp(tmpa->addr->domain, fa->domain) == 0)) {
dupe = TRUE;
Syslog('b', "Binkp: double address %s", ascfnode(tmpa->addr, 0x1f));
break;
(tmpa->addr->node == fa->node) && (tmpa->addr->point == fa->point) &&
(strcmp(tmpa->addr->domain, fa->domain) == 0)) {
dupe = TRUE;
Syslog('b', "Binkp: double address %s", ascfnode(tmpa->addr, 0x1f));
break;
}
}
if (!dupe) {
if (!dupe) {
*tmp = (fa_list*)malloc(sizeof(fa_list));
(*tmp)->next = NULL;
(*tmp)->addr = fa;
@ -614,14 +624,15 @@ SM_STATE(waitaddr)
}
} else {
Syslog('!', "Binkp: bad remote address: \"%s\"", printable(q, 0));
binkp_send_control(MM_ERR, "Bad address");
binkp_send_control(MM_ERR, "Bad address");
}
}
for (tmpa = remote; tmpa; tmpa = tmpa->next) {
for (tmpa = remote; tmpa; tmpa = tmpa->next) {
Syslog('+', "Address : %s", ascfnode(tmpa->addr, 0x1f));
if (nodelock(tmpa->addr)) {
binkp_send_control(MM_BSY, "Address %s locked", ascfnode(tmpa->addr, 0x1f));
SM_ERROR;
binkp_send_control(MM_BSY, "Address %s locked", ascfnode(tmpa->addr, 0x1f));
SM_ERROR;
}
/*
@ -629,60 +640,64 @@ SM_STATE(waitaddr)
* when the remote presents us an address we don't know about.
*/
if (!Loaded) {
if (noderecord(tmpa->addr))
Loaded = TRUE;
if (noderecord(tmpa->addr))
Loaded = TRUE;
}
}
history.aka.zone = remote->addr->zone;
history.aka.net = remote->addr->net;
history.aka.node = remote->addr->node;
history.aka.point = remote->addr->point;
sprintf(history.aka.domain, "%s", remote->addr->domain);
SM_PROCEED(sendpass)
history.aka.zone = remote->addr->zone;
history.aka.net = remote->addr->net;
history.aka.node = remote->addr->node;
history.aka.point = remote->addr->point;
sprintf(history.aka.domain, "%s", remote->addr->domain);
SM_PROCEED(SendPasswd)
} else if (rbuf[0] == MM_BSY) {
Syslog('!', "Binkp: M_BSY \"%s\"", printable(&rbuf[1], 0));
SM_ERROR;
SM_ERROR;
} else if (rbuf[0] == MM_ERR) {
Syslog('!', "Binkp: M_ERR \"%s\"", printable(&rbuf[1], 0));
SM_ERROR;
} else if (rbuf[0] == MM_NUL) {
b_nul(&rbuf[1]);
} else {
binkp_send_control(MM_ERR, "Unexpected frame");
SM_ERROR;
}
}
}
SM_STATE(sendpass)
SM_STATE(SendPasswd)
if (MD_challenge && strlen(nodes.Spasswd)) {
char *pw = NULL, *tp = NULL;
pw = xstrcpy(nodes.Spasswd);
tp = MD_buildDigest(pw, MD_challenge);
if (Loaded && strlen(nodes.Spasswd)) {
pwd = xstrcpy(nodes.Spasswd);
SendPass = TRUE;
} else {
pwd = xstrcpy((char *)"-");
}
if (MD_challenge) {
char *tp = NULL;
tp = MD_buildDigest(pwd, MD_challenge);
if (!tp) {
Syslog('!', "Unable to build MD5 digest");
SM_ERROR;
}
SendPass = TRUE;
CRAMflag = TRUE;
binkp_send_control(MM_PWD, "%s", tp);
free(tp);
free(pw);
} else {
if (strlen(nodes.Spasswd)) {
SendPass = TRUE;
binkp_send_control(MM_PWD, "%s", nodes.Spasswd);
} else {
binkp_send_control(MM_PWD, "-");
}
binkp_send_control(MM_PWD, "%s", pwd);
}
SM_PROCEED(authremote)
free(pwd);
SM_PROCEED(AuthRemote)
SM_STATE(authremote)
SM_STATE(AuthRemote)
rc = 0;
for (tmpa = remote; tmpa; tmpa = tmpa->next) {
@ -693,14 +708,18 @@ SM_STATE(authremote)
}
if (rc) {
SM_PROCEED(waitok)
SM_PROCEED(IfSecure)
} else {
Syslog('!', "Binkp: error, the wrong node is reached");
binkp_send_control(MM_ERR, "No AKAs in common or all AKAs busy");
SM_ERROR;
}
SM_STATE(waitok)
SM_STATE(IfSecure)
SM_PROCEED(WaitOk)
SM_STATE(WaitOk)
for (;;) {
if ((rc = binkp_recv_frame(rbuf, &bufl, &cmd))) {
@ -711,26 +730,38 @@ SM_STATE(waitok)
if (cmd) {
if (rbuf[0] == MM_OK) {
Syslog('!', "Binkp: M_OK \"%s\"", printable(&rbuf[1], 0));
if (SendPass)
Syslog('+', "Binkp: %spassword protected session", CRAMflag ? "MD5 ":"");
else
Syslog('+', "Binkp: unprotected session");
SM_SUCCESS;
if (SendPass)
Secure = TRUE;
Syslog('+', "Binkp: %s%sprotected session", CRAMflag ? "MD5 ":"", Secure ? "":"un");
SM_PROCEED(Opts)
} else if (rbuf[0] == MM_BSY) {
Syslog('!', "Binkp: M_BSY \"%s\"", printable(&rbuf[1], 0));
SM_ERROR;
SM_ERROR;
} else if (rbuf[0] == MM_ERR) {
Syslog('!', "Binkp: M_ERR \"%s\"", printable(&rbuf[1], 0));
SM_ERROR;
SM_ERROR;
} else if (rbuf[0] == MM_NUL) {
b_nul(&rbuf[1]);
} else {
binkp_send_control(MM_ERR, "Unexpected frame");
SM_ERROR;
}
}
}
SM_STATE(Opts)
/*
* Room to negotiate more protocol options.
* When we are binkp/1.1 and remote is 1.0 we should
* negotiate MB mode here.
*/
SM_SUCCESS;
SM_END
SM_RETURN
@ -741,25 +772,29 @@ SM_RETURN
*/
SM_DECL(ansbinkp, (char *)"ansbinkp")
SM_STATES
waitconn,
waitaddr,
waitpwd,
pwdack
WaitConn,
WaitAddr,
IsPasswd,
WaitPwd,
PwdAck,
Opts
SM_NAMES
(char *)"waitconn",
(char *)"waitaddr",
(char *)"waitpwd",
(char *)"pwdack"
(char *)"WaitConn",
(char *)"WaitAddr",
(char *)"IsPasswd",
(char *)"WaitPwd",
(char *)"PwdAck",
(char *)"Opts"
SM_EDECL
char *p, *q;
int i, rc, bufl, cmd, dupe;
char *p, *q, *pw;
int i, rc, bufl, cmd, dupe, we_have_pwd = FALSE;
fa_list **tmp, *tmpa;
faddr *fa;
SM_START(waitconn)
SM_START(WaitConn)
SM_STATE(waitconn)
SM_STATE(WaitConn)
Loaded = FALSE;
@ -780,7 +815,7 @@ SM_STATE(waitconn)
Syslog('b', "Binkp: sending \"%s\"", s);
binkp_send_control(MM_NUL, "%s", s);
}
b_banner(CFG.NoFreqs);
b_banner();
p = xstrcpy((char *)"");
for (i = 0; i < 40; i++)
@ -791,9 +826,9 @@ SM_STATE(waitconn)
binkp_send_control(MM_ADR, "%s", p);
free(p);
SM_PROCEED(waitaddr)
SM_PROCEED(WaitAddr)
SM_STATE(waitaddr)
SM_STATE(WaitAddr)
for (;;) {
if ((rc = binkp_recv_frame(rbuf, &bufl, &cmd))) {
@ -858,17 +893,19 @@ SM_STATE(waitaddr)
if (nlent)
rdoptions(Loaded);
if (MBflag) {
if (MBflag == TheyWant) {
Syslog('b', "Binkp: remote supports MB");
binkp_send_control(MM_NUL,"OPT MB");
MBflag = Active;
}
if (CRCflag) {
if (CRCflag == TheyWant) {
if (Loaded && nodes.CRC32 && !CFG.NoCRC32) {
binkp_send_control(MM_NUL,"OPT CRC");
Syslog('+', "Binkp: using file transfers with CRC32 checking");
CRCflag = Active;
} else {
Syslog('b', "Binkp: CRC32 support is diabled here");
CRCflag = FALSE;
CRCflag = No;
}
}
@ -878,7 +915,7 @@ SM_STATE(waitaddr)
history.aka.point = remote->addr->point;
sprintf(history.aka.domain, "%s", remote->addr->domain);
SM_PROCEED(waitpwd)
SM_PROCEED(IsPasswd)
} else if (rbuf[0] == MM_ERR) {
Syslog('!', "Binkp: M_ERR \"%s\"", printable(&rbuf[1], 0));
@ -886,11 +923,23 @@ SM_STATE(waitaddr)
} else if (rbuf[0] == MM_NUL) {
b_nul(&rbuf[1]);
} else if (rbuf[0] <= MM_MAX) {
binkp_send_control(MM_ERR, "Unexpected frame");
SM_ERROR;
}
}
}
SM_STATE(waitpwd)
SM_STATE(IsPasswd)
if (Loaded && strlen(nodes.Spasswd)) {
we_have_pwd = TRUE;
}
Syslog('b', "We %s have a password", we_have_pwd ?"do":"don't");
SM_PROCEED(WaitPwd)
SM_STATE(WaitPwd)
for (;;) {
if ((rc = binkp_recv_frame(rbuf, &bufl, &cmd))) {
@ -900,67 +949,71 @@ SM_STATE(waitpwd)
if (cmd) {
if (rbuf[0] == MM_PWD) {
SM_PROCEED(pwdack)
SM_PROCEED(PwdAck)
} else if (rbuf[0] == MM_ERR) {
Syslog('!', "Binkp: M_ERR \"%s\"", printable(&rbuf[1], 0));
SM_ERROR;
} else if (rbuf[0] == MM_NUL) {
b_nul(&rbuf[1]);
} else if (rbuf[0] <= MM_MAX) {
binkp_send_control(MM_ERR, "Unexpected frame");
SM_ERROR;
}
}
}
SM_STATE(pwdack)
SM_STATE(PwdAck)
tmpa = remote;
if ((strncmp(&rbuf[1], "CRAM-", 5) == 0) && CRAMflag && Loaded) {
char *sp, *pw;
if (we_have_pwd) {
pw = xstrcpy(nodes.Spasswd);
} else {
pw = xstrcpy((char *)"-");
}
if ((strncmp(&rbuf[1], "CRAM-", 5) == 0) && CRAMflag) {
char *sp;
sp = MD_buildDigest(pw, MD_challenge);
free(pw);
if (sp != NULL) {
if (strcmp(&rbuf[1], sp)) {
Syslog('+', "Binkp: bad MD5 crypted password");
binkp_send_control(MM_ERR, "*** Password error, check setup ***");
binkp_send_control(MM_ERR, "Bad password");
free(sp);
sp = NULL;
free(pw);
SM_ERROR;
} else {
free(sp);
sp = NULL;
Syslog('+', "Binkp: MD5 password OK, protected session");
inbound_open(tmpa->addr, TRUE);
binkp_send_control(MM_OK, "secure");
SM_SUCCESS;
if (we_have_pwd)
Secure = TRUE;
}
} else {
free(pw);
Syslog('!', "Binkp: could not build MD5 digest");
binkp_send_control(MM_ERR, "*** Internal error ***");
SM_ERROR;
}
} else if ((strcmp(&rbuf[1], "-") == 0) && !Loaded) {
Syslog('+', "Binkp: node not in setup, unprotected session");
inbound_open(tmpa->addr, FALSE);
binkp_send_control(MM_OK, "");
SM_SUCCESS;
} else if ((strcmp(&rbuf[1], "-") == 0) && Loaded && !strlen(nodes.Spasswd)) {
Syslog('+', "Binkp: node in setup but no session password, unprotected session");
inbound_open(tmpa->addr, FALSE);
binkp_send_control(MM_OK, "");
SM_SUCCESS;
} else if ((strcmp(&rbuf[1], nodes.Spasswd) == 0) && Loaded) {
Syslog('+', "Binkp: password OK, protected session");
inbound_open(tmpa->addr, TRUE);
binkp_send_control(MM_OK, "secure");
SM_SUCCESS;
} else if ((strcmp(&rbuf[1], pw) == 0)) {
if (we_have_pwd)
Secure = TRUE;
} else {
free(pw);
Syslog('?', "Binkp: password error: expected \"%s\", got \"%s\"", nodes.Spasswd, &rbuf[1]);
binkp_send_control(MM_ERR, "*** Password error, check setup ***");
binkp_send_control(MM_ERR, "Bad password");
SM_ERROR;
}
free(pw);
Syslog('+', "Binkp: %s%sprotected session", CRAMflag ? "MD5 ":"", Secure ? "":"un");
inbound_open(remote->addr, Secure);
binkp_send_control(MM_OK, "%ssecure", Secure ? "":"non-");
SM_PROCEED(Opts)
SM_STATE(Opts)
SM_SUCCESS;
SM_END
SM_RETURN
@ -1048,7 +1101,7 @@ int binkp_batch(file_list *to_send, int role)
rname = calloc(512, sizeof(char));
lname = calloc(512, sizeof(char));
gname = calloc(512, sizeof(char));
TfState = Switch;
// TfState = Switch;
RxState = RxWaitFile;
TxState = TxGetNextFile;
binkp_settimer(BINKP_TIMEOUT);
@ -1141,7 +1194,7 @@ int binkp_batch(file_list *to_send, int role)
txflock.l_start = 0L;
txflock.l_len = 0L;
if (CRCflag)
if (CRCflag == Active)
tcrc = file_crc(tmp->local, FALSE);
else
tcrc = 0;
@ -1168,7 +1221,7 @@ int binkp_batch(file_list *to_send, int role)
txpos = stxpos = tmp->offset;
Syslog('+', "Binkp: send \"%s\" as \"%s\"", MBSE_SS(tmp->local), MBSE_SS(tmp->remote));
if (CRCflag && tcrc) {
if ((CRCflag == Active) && tcrc) {
Syslog('+', "Binkp: size %lu bytes, dated %s, crc %lx", (unsigned long)tmp->size, date(tmp->date), tcrc);
binkp_send_control(MM_FILE, "%s %lu %ld %ld %lx", MBSE_SS(tmp->remote),
(unsigned long)tmp->size, (long)tmp->date, (unsigned long)tmp->offset, tcrc);
@ -1332,7 +1385,7 @@ int binkp_batch(file_list *to_send, int role)
* Check against buffer overflow
*/
rcrc = 0;
if (CRCflag) {
if (CRCflag == Active) {
sscanf(rxbuf+1, "%s %ld %ld %ld %lx", rname, &rsize, &rtime, &roffs, &rcrc);
} else {
sscanf(rxbuf+1, "%s %ld %ld %ld", rname, &rsize, &rtime, &roffs);
@ -1345,13 +1398,13 @@ int binkp_batch(file_list *to_send, int role)
}
break;
default: Syslog('+', "Binkp: Unexpected frame %d", rxbuf[0]);
default: Syslog('+', "Binkp: Unexpected frame %d \"%s\"", rxbuf[0], printable(rxbuf+1, 0));
}
} else {
if (blklen) {
if (RxState == RxReceData) {
written = fwrite(rxbuf, 1, blklen, rxfp);
if (CRCflag)
if (CRCflag == Active)
rxcrc = upd_crc32(rxbuf, rxcrc, blklen);
if (!written && blklen) {
Syslog('+', "Binkp: file write error");
@ -1360,7 +1413,7 @@ int binkp_batch(file_list *to_send, int role)
rxpos += written;
if (rxpos == rsize) {
RxState = RxWaitFile;
if (CRCflag && rcrc) {
if ((CRCflag == Active) && rcrc) {
rxcrc = rxcrc ^ 0xffffffff;
if (rcrc == rxcrc) {
binkp_send_control(MM_GOT, "%s %ld %ld %lx", rname, rsize, rtime, rcrc);
@ -1411,7 +1464,7 @@ int binkp_batch(file_list *to_send, int role)
break;
case RxAcceptFile:
if (CRCflag)
if (CRCflag == Active)
Syslog('+', "Binkp: receive file \"%s\" date %s size %ld offset %ld crc %lx",
rname, date(rtime), rsize, roffs, rcrc);
else
@ -1439,7 +1492,7 @@ int binkp_batch(file_list *to_send, int role)
* be deleted at the remote.
*/
Syslog('+', "Binkp: already got %s, sending GOT", rname);
if (CRCflag && rcrc)
if ((CRCflag == Active) && rcrc)
binkp_send_control(MM_GOT, "%s %ld %ld %lx", rname, rsize, rtime, rcrc);
else
binkp_send_control(MM_GOT, "%s %ld %ld", rname, rsize, rtime);
@ -1450,7 +1503,7 @@ int binkp_batch(file_list *to_send, int role)
* Some error, request to skip it
*/
Syslog('+', "Binkp: error file %s, sending SKIP", rname);
if (CRCflag && rcrc)
if ((CRCflag == Active) && rcrc)
binkp_send_control(MM_SKIP, "%s %ld %ld %lx", rname, rsize, rtime, rcrc);
else
binkp_send_control(MM_SKIP, "%s %ld %ld", rname, rsize, rtime);

View File

@ -1,6 +1,8 @@
#ifndef _BINKP_H
#define _BINKP_H
/* $Id$ */
/*
binkp's frames:
@ -17,7 +19,8 @@
/* protocol version */
#define BINKP_VERSION "1.1"
#define PRTCLNAME "binkp"
#define PRTCLVER "1.0"
#define MAX_BLKSIZE 0x7fff /* Don't change! */
#define BLK_HDR_SIZE 2 /* 2 bytes header */
@ -28,7 +31,7 @@
#define MM_ADR 1 /* System aka's */
#define MM_PWD 2 /* Password */
#define MM_FILE 3
#define MM_OK 4 /* The password is ok (data ignored) */
#define MM_OK 4 /* The password is ok */
#define MM_EOB 5 /* End-of-batch (data ignored) */
#define MM_GOT 6 /* File received */
#define MM_ERR 7 /* Misc errors */
@ -68,17 +71,6 @@ typedef struct _binkp_list {
} binkp_list;
/*
* state.NR_flag: state of binkp when in NR mode
*/
#define NO_NR 0
#define WANT_NR 1
#define WE_NR 2
#define THEY_NR 3
int binkp(int);
#endif

View File

@ -4,45 +4,50 @@
#define SM_DECL(proc,name) \
int proc(void)\
{\
int sm_success=0;\
char *sm_name=name;
int sm_success=0;\
char *sm_name=name;
#define SM_STATES \
enum {
enum {
#define SM_NAMES \
} sm_state; \
char * sm_sname[] = {
} sm_state; \
char * sm_sname[] = {
#define SM_EDECL \
};
};
#define SM_START(x) \
sm_state=x;\
Syslog('S', "Statemachine %s start %s (%d)",sm_name,sm_sname[sm_state],sm_state); \
while (!sm_success) switch (sm_state)\
{\
default: WriteError("Statemachine %s error: state=%d",sm_name,sm_state);\
sm_success=-1;
sm_state=x;\
Syslog('S', "SM (%s): Start => %s", sm_name, sm_sname[sm_state]); \
while (!sm_success) switch (sm_state)\
{\
default: WriteError("Statemachine %s error: state=%d",sm_name,sm_state);\
sm_success=-1;
#define SM_STATE(x) \
break;\
case x:
break;\
case x:
#define SM_END \
}\
}\
#define SM_RETURN \
return (sm_success != 1);\
return (sm_success != 1);\
}
#define SM_PROCEED(x) \
sm_state=x; break;
if (x != sm_state) {\
Syslog('S', "SM (%s): %s => %s", sm_name, sm_sname[sm_state], sm_sname[x]);\
}\
sm_state=x; break;
#define SM_SUCCESS \
sm_success=1; break;
Syslog('S', "SM (%s): %s => Success", sm_name, sm_sname[sm_state]);\
sm_success=1; break;
#define SM_ERROR \
sm_success=-1; break;
Syslog('S', "SM (%s): %s => Error", sm_name, sm_sname[sm_state]);\
sm_success=-1; break;
#endif