521 lines
15 KiB
C
521 lines
15 KiB
C
/*****************************************************************************
|
|
*
|
|
* $Id$
|
|
* Purpose ...............: Fidonet mailer
|
|
*
|
|
*****************************************************************************
|
|
* Copyright (C) 1997-2007
|
|
*
|
|
* Michiel Broek FIDO: 2:280/2802
|
|
* Beekmansbos 10
|
|
* 1971 BV IJmuiden
|
|
* the Netherlands
|
|
*
|
|
* This file is part of MBSE BBS.
|
|
*
|
|
* This BBS is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2, or (at your option) any
|
|
* later version.
|
|
*
|
|
* MBSE BBS is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with MBSE BBS; see the file COPYING. If not, write to the Free
|
|
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
|
*****************************************************************************/
|
|
|
|
#include "../config.h"
|
|
#include "../lib/mbselib.h"
|
|
#include "../lib/users.h"
|
|
#include "../lib/nodelist.h"
|
|
#include "../lib/mbsedb.h"
|
|
#include "emsi.h"
|
|
#include "session.h"
|
|
#include "lutil.h"
|
|
#include "config.h"
|
|
#include "emsidat.h"
|
|
#include "filetime.h"
|
|
|
|
|
|
extern int Loaded;
|
|
extern int mypid;
|
|
extern int emsi_akas;
|
|
|
|
|
|
|
|
/*
|
|
* Encode EMSI string. If called with a NULL pointer memory is freed.
|
|
*/
|
|
char *emsiencode(char *s)
|
|
{
|
|
char Base16Code[]="0123456789ABCDEF";
|
|
static char *buf;
|
|
char *p, *q;
|
|
|
|
if (buf)
|
|
free(buf);
|
|
buf = NULL;
|
|
if (s == NULL)
|
|
return NULL;
|
|
|
|
if ((buf = malloc(2 * strlen(s) + 1 * sizeof(char))) == NULL) {
|
|
Syslog('+', "emsiencode:out of memory:string too long:\"%s\"", s);
|
|
return s;
|
|
}
|
|
for (p = s, q = buf; *p != '\0';) {
|
|
switch (*p) {
|
|
case '\\': *q++ = '\\'; *q++ = *p++; break;
|
|
case '[':
|
|
case ']':
|
|
case '{':
|
|
case '}': *q++ = '\\';
|
|
*q++ = Base16Code[(*p >> 4) & 0x0f];
|
|
*q++ = Base16Code[*p & 0x0f];
|
|
p++; break;
|
|
default: *q++ = *p++; break;
|
|
}
|
|
}
|
|
*q = '\0';
|
|
|
|
return buf;
|
|
}
|
|
|
|
|
|
|
|
char *mkemsidat(int caller)
|
|
{
|
|
time_t tt;
|
|
char cbuf[16], *p;
|
|
faddr *primary;
|
|
int i;
|
|
|
|
p = xstrcpy((char *)"EMSI_DAT0000{EMSI}{");
|
|
|
|
primary = bestaka_s(remote->addr);
|
|
p = xstrcat(p, ascfnode(primary, 0x1f));
|
|
|
|
for (i = 0; i < 40; i++)
|
|
if ((CFG.aka[i].zone) && (CFG.akavalid[i]) &&
|
|
((CFG.aka[i].zone != primary->zone) || (CFG.aka[i].net != primary->net) ||
|
|
(CFG.aka[i].node != primary->node) || (CFG.aka[i].point!= primary->point))) {
|
|
p = xstrcat(p, (char *)" ");
|
|
p = xstrcat(p, aka2str(CFG.aka[i]));
|
|
}
|
|
|
|
p=xstrcat(p,(char *)"}{");
|
|
tidy_faddr(primary);
|
|
|
|
if (emsi_local_password)
|
|
p=xstrcat(p,emsi_local_password);
|
|
else if (strlen(nodes.Spasswd)) {
|
|
p = xstrcat(p, nodes.Spasswd);
|
|
}
|
|
|
|
if (emsi_local_opts & OPT_EII) {
|
|
p = xstrcat(p, (char *)"}{");
|
|
|
|
if (emsi_local_lcodes & LCODE_FNC)
|
|
p = xstrcat(p, (char *)"FNC,");
|
|
if (emsi_local_lcodes & LCODE_RMA)
|
|
p = xstrcat(p, (char *)"RMA,");
|
|
if (emsi_local_lcodes & LCODE_RH1)
|
|
p = xstrcat(p, (char *)"RH1,");
|
|
|
|
if (emsi_local_lcodes & LCODE_PUA)
|
|
p=xstrcat(p,(char *)"PUA,");
|
|
else if (emsi_local_lcodes & LCODE_PUP)
|
|
p=xstrcat(p,(char *)"PUP,");
|
|
else if (emsi_local_lcodes & LCODE_NPU)
|
|
p=xstrcat(p,(char *)"NPU,");
|
|
if (emsi_local_lcodes & LCODE_HAT)
|
|
p=xstrcat(p,(char *)"HAT,");
|
|
if (emsi_local_lcodes & LCODE_HXT)
|
|
p=xstrcat(p,(char *)"HXT,");
|
|
if (emsi_local_lcodes & LCODE_HRQ)
|
|
p=xstrcat(p,(char *)"HRQ,");
|
|
if (*(p+strlen(p)-1) == ',')
|
|
*(p+strlen(p)-1) = '}';
|
|
else
|
|
p=xstrcat(p,(char *)"}");
|
|
} else {
|
|
p=xstrcat(p,(char *)"}{8N1");
|
|
if (emsi_local_lcodes & LCODE_RH1)
|
|
p = xstrcat(p, (char *)",RH1");
|
|
if (caller) {
|
|
if (emsi_local_lcodes & LCODE_PUA)
|
|
p=xstrcat(p,(char *)",PUA");
|
|
else if (emsi_local_lcodes & LCODE_PUP)
|
|
p=xstrcat(p,(char *)",PUP");
|
|
else if (emsi_local_lcodes & LCODE_NPU)
|
|
p=xstrcat(p,(char *)",NPU");
|
|
} else {
|
|
if (emsi_local_lcodes & LCODE_HAT)
|
|
p=xstrcat(p,(char *)",HAT");
|
|
if (emsi_local_lcodes & LCODE_HXT)
|
|
p=xstrcat(p,(char *)",HXT");
|
|
if (emsi_local_lcodes & LCODE_HRQ)
|
|
p=xstrcat(p,(char *)",HRQ");
|
|
}
|
|
|
|
p = xstrcat(p, (char *)"}");
|
|
}
|
|
|
|
p=xstrcat(p,(char *)"{");
|
|
if (emsi_local_protos & PROT_TCP)
|
|
p=xstrcat(p,(char *)"TCP,");
|
|
if (emsi_local_protos & PROT_HYD)
|
|
p=xstrcat(p,(char *)"HYD,");
|
|
if (emsi_local_protos & PROT_JAN)
|
|
p=xstrcat(p,(char *)"JAN,");
|
|
if (emsi_local_protos & PROT_ZAP)
|
|
p=xstrcat(p,(char *)"ZAP,");
|
|
if (emsi_local_protos & PROT_ZMO)
|
|
p=xstrcat(p,(char *)"ZMO,");
|
|
if (emsi_local_protos & PROT_DZA);
|
|
p=xstrcat(p,(char *)"DZA,");
|
|
if (emsi_local_protos & PROT_KER)
|
|
p=xstrcat(p,(char *)"KER,");
|
|
if (emsi_local_protos == 0)
|
|
p=xstrcat(p,(char *)"NCP,");
|
|
if (emsi_local_opts & OPT_NRQ)
|
|
p=xstrcat(p,(char *)"NRQ,");
|
|
if (emsi_local_opts & OPT_ARC)
|
|
p=xstrcat(p,(char *)"ARC,");
|
|
if (emsi_local_opts & OPT_XMA)
|
|
p=xstrcat(p,(char *)"XMA,");
|
|
if (emsi_local_opts & OPT_FNC)
|
|
p=xstrcat(p,(char *)"FNC,");
|
|
if (emsi_local_opts & OPT_CHT)
|
|
p=xstrcat(p,(char *)"CHT,");
|
|
if (emsi_local_opts & OPT_SLK)
|
|
p=xstrcat(p,(char *)"SLK,");
|
|
if (emsi_local_opts & OPT_EII)
|
|
p=xstrcat(p,(char *)"EII,");
|
|
if (emsi_local_opts & OPT_DFB)
|
|
p=xstrcat(p,(char *)"DFB,");
|
|
if (emsi_local_opts & OPT_FRQ)
|
|
p=xstrcat(p,(char *)"FRQ,");
|
|
if (*(p+strlen(p)-1) == ',')
|
|
*(p+strlen(p)-1) = '}';
|
|
else
|
|
p=xstrcat(p,(char *)"}");
|
|
|
|
snprintf(cbuf,16,"{%X}",PRODCODE);
|
|
p=xstrcat(p,cbuf);
|
|
p=xstrcat(p,(char *)"{mbcico}{");
|
|
p=xstrcat(p,(char *)VERSION);
|
|
p=xstrcat(p,(char *)"}{");
|
|
p=xstrcat(p,(char *)__DATE__);
|
|
p=xstrcat(p,(char *)"}{IDENT}{[");
|
|
p=xstrcat(p,name?emsiencode(name):(char *)"Unknown");
|
|
p=xstrcat(p,(char *)"][");
|
|
p=xstrcat(p,emsiencode(CFG.location));
|
|
p=xstrcat(p,(char *)"][");
|
|
p=xstrcat(p,emsiencode(CFG.sysop_name));
|
|
p=xstrcat(p,(char *)"][");
|
|
p=xstrcat(p,phone?emsiencode(phone):(char *)"-Unpublished-");
|
|
p=xstrcat(p,(char *)"][");
|
|
if ((CFG.IP_Speed) && (emsi_local_protos & PROT_TCP))
|
|
snprintf(cbuf,16,"%u",CFG.IP_Speed);
|
|
else
|
|
strcpy(cbuf,"9600");
|
|
p=xstrcat(p,cbuf);
|
|
p=xstrcat(p,(char *)"][");
|
|
p=xstrcat(p,flags?emsiencode(flags):(char *)"");
|
|
p=xstrcat(p,(char *)"]}{TRX#}{[");
|
|
tt = time(NULL);
|
|
snprintf(cbuf,16,"%08X", (unsigned int)mtime2sl(tt));
|
|
p=xstrcat(p,cbuf);
|
|
p=xstrcat(p,(char *)"]}{TZUTC}{[");
|
|
p=xstrcat(p,gmtoffset(tt));
|
|
p=xstrcat(p,(char *)"]}");
|
|
|
|
snprintf(cbuf,16,"%04X",(unsigned int)strlen(p+12));
|
|
memcpy(p+8,cbuf,4);
|
|
emsiencode(NULL); /* Free memory */
|
|
return p;
|
|
}
|
|
|
|
|
|
|
|
char *sel_brace(char*);
|
|
char *sel_brace(char *s)
|
|
{
|
|
static char *save;
|
|
char *p,*q;
|
|
int i;
|
|
|
|
if (s == NULL)
|
|
s=save;
|
|
for (;*s && (*s != '{');s++);
|
|
if (*s == '\0') {
|
|
save=s;
|
|
return NULL;
|
|
} else
|
|
s++;
|
|
|
|
for (p=s,q=s;*p;p++)
|
|
switch (*p) {
|
|
case '}': if (*(p+1) == '}')
|
|
*q++=*p++;
|
|
else {
|
|
*q='\0';
|
|
save=p+1;
|
|
goto exit;
|
|
}
|
|
break;
|
|
case '\\': if (*(p+1) == '\\')
|
|
*q++=*p++;
|
|
else {
|
|
sscanf(p+1,"%02x",&i);
|
|
*q++=i;
|
|
p+=2;
|
|
}
|
|
break;
|
|
default: *q++=*p;
|
|
break;
|
|
}
|
|
exit:
|
|
return s;
|
|
}
|
|
|
|
|
|
|
|
char *sel_bracket(char*);
|
|
char *sel_bracket(char *s)
|
|
{
|
|
static char *save;
|
|
char *p,*q;
|
|
int i;
|
|
|
|
if (s == NULL)
|
|
s=save;
|
|
for (;*s && (*s != '[');s++);
|
|
if (*s == '\0') {
|
|
save=s;
|
|
return NULL;
|
|
} else
|
|
s++;
|
|
|
|
for (p=s,q=s;*p;p++)
|
|
switch (*p) {
|
|
case ']': if (*(p+1) == ']')
|
|
*q++=*p++;
|
|
else {
|
|
*q='\0';
|
|
save=p+1;
|
|
goto exit;
|
|
}
|
|
break;
|
|
case '\\': if (*(p+1) == '\\')
|
|
*q++=*p++;
|
|
else {
|
|
sscanf(p+1,"%02x",&i);
|
|
*q++=i;
|
|
p+=2;
|
|
}
|
|
break;
|
|
default: *q++=*p;
|
|
break;
|
|
}
|
|
exit:
|
|
return s;
|
|
}
|
|
|
|
|
|
|
|
int scanemsidat(char *buf)
|
|
{
|
|
fa_list **tmp, *tmpa;
|
|
faddr *fa;
|
|
char *p, *q, *mailer_prod, *mailer_name, *mailer_version, *mailer_serial;
|
|
int dupe, ttt;
|
|
|
|
p = sel_brace(buf);
|
|
if (strcasecmp(p,"EMSI") != 0) {
|
|
Syslog('?', "This can never occur. Got \"%s\" instead of \"EMSI\"",p);
|
|
return 1;
|
|
}
|
|
p = sel_brace(NULL);
|
|
|
|
/*
|
|
* Clear remote address list, and build a new one from EMSI data
|
|
*/
|
|
tidy_falist(&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) {
|
|
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('i', "Double address %s", ascfnode(tmpa->addr, 0x1f));
|
|
break;
|
|
}
|
|
}
|
|
if (!dupe) {
|
|
*tmp = (fa_list*)malloc(sizeof(fa_list));
|
|
(*tmp)->next = NULL;
|
|
(*tmp)->addr = fa;
|
|
tmp = &((*tmp)->next);
|
|
}
|
|
}
|
|
}
|
|
|
|
tmp = &remote;
|
|
while (*tmp) {
|
|
if (nodelock((*tmp)->addr, mypid)) {
|
|
Syslog('+', "address : %s is locked, removed from aka list",ascfnode((*tmp)->addr,0x1f));
|
|
tmpa=*tmp;
|
|
*tmp=(*tmp)->next;
|
|
free(tmpa);
|
|
} else {
|
|
/*
|
|
* With the loaded flag we prevent removing the noderecord
|
|
* when the remote presents us an address we don't know about.
|
|
*/
|
|
emsi_akas++;
|
|
Syslog('+', "address : %s",ascfnode((*tmp)->addr,0x1f));
|
|
if (!Loaded) {
|
|
if (noderecord((*tmp)->addr))
|
|
Loaded = TRUE;
|
|
}
|
|
tmp = &((*tmp)->next);
|
|
}
|
|
}
|
|
|
|
if (emsi_akas) { /* Only if any aka's left */
|
|
history.aka.zone = remote->addr->zone;
|
|
history.aka.net = remote->addr->net;
|
|
history.aka.node = remote->addr->node;
|
|
history.aka.point = remote->addr->point;
|
|
snprintf(history.aka.domain, 13, "%s", printable(remote->addr->domain, 0));
|
|
}
|
|
|
|
if (emsi_remote_password)
|
|
free(emsi_remote_password);
|
|
emsi_remote_password=xstrcpy(sel_brace(NULL));
|
|
|
|
p=sel_brace(NULL);
|
|
Syslog('+', "link : %s", MBSE_SS(p));
|
|
for (q=strtok(p,",");q;q=strtok(NULL,",")) {
|
|
if (((q[0] >= '5') && (q[0] <= '8')) && ((toupper(q[1]) == 'N') || (toupper(q[1]) == 'O') ||
|
|
(toupper(q[1]) == 'E') || (toupper(q[1]) == 'S') || (toupper(q[1]) == 'M')) && ((q[2] == '1') || (q[2] == '2'))) {
|
|
strncpy(emsi_remote_comm,q,3);
|
|
}
|
|
else if (strcasecmp(q,"PUA") == 0) emsi_remote_lcodes |= LCODE_PUA;
|
|
else if (strcasecmp(q,"PUP") == 0) emsi_remote_lcodes |= LCODE_PUP;
|
|
else if (strcasecmp(q,"NPU") == 0) emsi_remote_lcodes |= LCODE_NPU;
|
|
else if (strcasecmp(q,"HAT") == 0) emsi_remote_lcodes |= LCODE_HAT;
|
|
else if (strcasecmp(q,"HXT") == 0) emsi_remote_lcodes |= LCODE_HXT;
|
|
else if (strcasecmp(q,"HRQ") == 0) emsi_remote_lcodes |= LCODE_HRQ;
|
|
else if (strcasecmp(q,"FNC") == 0) emsi_remote_lcodes |= LCODE_FNC;
|
|
else if (strcasecmp(q,"RMA") == 0) emsi_remote_lcodes |= LCODE_RMA;
|
|
else if (strcasecmp(q,"RH1") == 0) emsi_remote_lcodes |= LCODE_RH1;
|
|
else Syslog('+', "unrecognized EMSI link code: \"%s\"",q);
|
|
}
|
|
|
|
p=sel_brace(NULL);
|
|
Syslog('+', "comp : %s", p);
|
|
for (q=strtok(p,",");q;q=strtok(NULL,",")) {
|
|
if (strcasecmp(q,"DZA") == 0) emsi_remote_protos |= PROT_DZA;
|
|
else if (strcasecmp(q,"ZAP") == 0) emsi_remote_protos |= PROT_ZAP;
|
|
else if (strcasecmp(q,"ZMO") == 0) emsi_remote_protos |= PROT_ZMO;
|
|
else if (strcasecmp(q,"JAN") == 0) emsi_remote_protos |= PROT_JAN;
|
|
else if (strcasecmp(q,"HYD") == 0) emsi_remote_protos |= PROT_HYD;
|
|
else if (strcasecmp(q,"KER") == 0) emsi_remote_protos |= PROT_KER;
|
|
else if (strcasecmp(q,"TCP") == 0) emsi_remote_protos |= PROT_TCP;
|
|
else if (strcasecmp(q,"NCP") == 0) emsi_remote_protos = 0;
|
|
else if (strcasecmp(q,"NRQ") == 0) emsi_remote_opts |= OPT_NRQ;
|
|
else if (strcasecmp(q,"ARC") == 0) emsi_remote_opts |= OPT_ARC;
|
|
else if (strcasecmp(q,"XMA") == 0) emsi_remote_opts |= OPT_XMA;
|
|
else if (strcasecmp(q,"FNC") == 0) emsi_remote_opts |= OPT_FNC;
|
|
else if (strcasecmp(q,"CHT") == 0) emsi_remote_opts |= OPT_CHT;
|
|
else if (strcasecmp(q,"SLK") == 0) emsi_remote_opts |= OPT_SLK;
|
|
else if (strcasecmp(q,"EII") == 0) emsi_remote_opts |= OPT_EII;
|
|
else if (strcasecmp(q,"DFB") == 0) emsi_remote_opts |= OPT_DFB;
|
|
else if (strcasecmp(q,"FRQ") == 0) emsi_remote_opts |= OPT_FRQ;
|
|
else if (strcasecmp(q,"BBS") == 0) Syslog('+', "remote has BBS activity now");
|
|
else Syslog('+', "unrecognized EMSI proto/option code: \"%s\"",q);
|
|
}
|
|
if ((emsi_remote_opts & OPT_FNC) == 0)
|
|
remote_flags &= ~SESSION_FNC;
|
|
|
|
mailer_prod=sel_brace(NULL);
|
|
mailer_name=sel_brace(NULL);
|
|
mailer_version=sel_brace(NULL);
|
|
mailer_serial=sel_brace(NULL);
|
|
Syslog('+', "uses : %s [%s] version %s/%s", mailer_name, mailer_prod, mailer_version, mailer_serial);
|
|
|
|
while ((p=sel_brace(NULL))) {
|
|
if (strcasecmp(p,"IDENT") == 0) {
|
|
p=sel_brace(NULL);
|
|
Syslog('+', "system : %s",(p=sel_bracket(p)));
|
|
strncpy(history.system_name, p, 35);
|
|
Syslog('+', "location: %s",(p=sel_bracket(NULL)));
|
|
strncpy(history.location, p, 35);
|
|
Syslog('+', "operator: %s",(p=sel_bracket(NULL)));
|
|
strncpy(history.sysop, p, 35);
|
|
if (remote && remote->addr)
|
|
remote->addr->name=xstrcpy(p);
|
|
Syslog('+', "phone : %s",sel_bracket(NULL));
|
|
Syslog('+', "baud : %s",sel_bracket(NULL));
|
|
Syslog('+', "flags : %s",sel_bracket(NULL));
|
|
} else if (strcasecmp(p, "TZUTC") == 0) {
|
|
p = sel_brace(NULL);
|
|
p = sel_bracket(p);
|
|
if ((strlen(p) == 4) || (strlen(p) == 5))
|
|
Syslog('+', "timezone: %s", p);
|
|
else
|
|
Syslog('+', "TZUTC : %s", p);
|
|
} else if (strcasecmp(p,"TRX#") == 0) {
|
|
time_t tt, now;
|
|
char ctt[32];
|
|
|
|
now = time(NULL);
|
|
p=sel_brace(NULL);
|
|
p=sel_bracket(p);
|
|
if (sscanf(p,"%08x",&ttt) == 1) {
|
|
tt = (time_t)ttt;
|
|
strcpy(ctt,date(sl2mtime(tt)));
|
|
Syslog('+', "time : %s",ctt);
|
|
Syslog('+', "tranx : %08lX/%08lX [%ld]", now, sl2mtime(tt), now - sl2mtime(tt));
|
|
} else
|
|
Syslog('+', "remote TRX#: %s",p);
|
|
} else if (strcasecmp(p, "TRAF") == 0) {
|
|
unsigned int tt, tt1;
|
|
|
|
p = sel_brace(NULL);
|
|
if (sscanf(p, "%08x %08x", &tt, &tt1) == 2) {
|
|
Syslog('+', "netmail : %u byte(s)", tt);
|
|
Syslog('+', "echomail: %u byte(s)", tt1);
|
|
} else {
|
|
Syslog('+', "TRAF : %s", p);
|
|
}
|
|
} else if (strcasecmp(p, "MOH#") == 0) {
|
|
unsigned int tt;
|
|
|
|
p = sel_brace(NULL);
|
|
p = sel_bracket(p);
|
|
if (sscanf(p, "%08x", &tt) == 1)
|
|
Syslog('+', "on hold : %u byte(s)", tt);
|
|
else
|
|
Syslog('+', "MOH# : %s", p);
|
|
} else {
|
|
q=sel_brace(NULL);
|
|
Syslog('+', "extra : \"%s\" value: \"%s\"",p,q);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|