From a4123fc91ed874d609cf74fcbf2a444f3f0b2aa5 Mon Sep 17 00:00:00 2001 From: Michiel Broek Date: Sun, 7 Sep 2003 20:25:33 +0000 Subject: [PATCH] A lot of changes in the binkp driver --- ChangeLog | 5 + TODO | 6 + mbcico/binkp.c | 419 ++++++++++++++++++++++++++-------------------- mbcico/binkp.h | 18 +- mbcico/statetbl.h | 43 ++--- 5 files changed, 276 insertions(+), 215 deletions(-) diff --git a/ChangeLog b/ChangeLog index 345327a5..fd38fcb9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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 diff --git a/TODO b/TODO index 9b699d11..c9525789 100644 --- a/TODO +++ b/TODO @@ -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. diff --git a/mbcico/binkp.c b/mbcico/binkp.c index 30064514..0e378cf0 100644 --- a/mbcico/binkp.c +++ b/mbcico/binkp.c @@ -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); diff --git a/mbcico/binkp.h b/mbcico/binkp.h index f33201f8..ce3ef92e 100644 --- a/mbcico/binkp.h +++ b/mbcico/binkp.h @@ -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 - diff --git a/mbcico/statetbl.h b/mbcico/statetbl.h index 8a9ceece..ea39b7da 100644 --- a/mbcico/statetbl.h +++ b/mbcico/statetbl.h @@ -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