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 For FTS-0001 sessions the mail password was used instead of the
session password. Also improved the password check. session password. Also improved the password check.
The product code was not entered in the FTS-0001 packet headers. 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: mbfido:
The rfc to ftn gate now drops the headerlines starting with The rfc to ftn gate now drops the headerlines starting with

6
TODO
View File

@ -20,6 +20,8 @@ everything:
L: Implement IPv6. L: Implement IPv6.
L: Document error return codes in the manual.
install: install:
N: On some (unsupported) distro's with xinetd the installation script N: On some (unsupported) distro's with xinetd the installation script
also adds entries to inetd.conf. also adds entries to inetd.conf.
@ -111,6 +113,10 @@ mbcico:
N: Implement binkp resync when getting files. Transmit works. N: Implement binkp resync when getting files. Transmit works.
Under test now! 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: mbfile:
L: Add a check to see if the magic filenames are (still) valid. L: Add a check to see if the magic filenames are (still) valid.

View File

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

View File

@ -1,6 +1,8 @@
#ifndef _BINKP_H #ifndef _BINKP_H
#define _BINKP_H #define _BINKP_H
/* $Id$ */
/* /*
binkp's frames: binkp's frames:
@ -17,7 +19,8 @@
/* protocol version */ /* protocol version */
#define BINKP_VERSION "1.1" #define PRTCLNAME "binkp"
#define PRTCLVER "1.0"
#define MAX_BLKSIZE 0x7fff /* Don't change! */ #define MAX_BLKSIZE 0x7fff /* Don't change! */
#define BLK_HDR_SIZE 2 /* 2 bytes header */ #define BLK_HDR_SIZE 2 /* 2 bytes header */
@ -28,7 +31,7 @@
#define MM_ADR 1 /* System aka's */ #define MM_ADR 1 /* System aka's */
#define MM_PWD 2 /* Password */ #define MM_PWD 2 /* Password */
#define MM_FILE 3 #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_EOB 5 /* End-of-batch (data ignored) */
#define MM_GOT 6 /* File received */ #define MM_GOT 6 /* File received */
#define MM_ERR 7 /* Misc errors */ #define MM_ERR 7 /* Misc errors */
@ -68,17 +71,6 @@ typedef struct _binkp_list {
} 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); int binkp(int);
#endif #endif

View File

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