SOCTYP *soc;
soc=(SOCTYP *)socptr;
+iterations=0;
if (soc!=(SOCTYP *)0)
iterations=soc->iteration;
return iterations;
phase=999; //never reached
}
break;
- case 1 : //shuting dow the TCP link
+ case 1 : //shutting down the TCP link
switch (soc->proto) {
case pro_smtp : //plain socket
case pro_starttls : //plain socket + STARTTLS
return status;
#undef OPEP
}
+/*
+^L
+*/
+/********************************************************/
+/* */
+/* Procedure to switch a plain socket channel to */
+/* crypted channel, return true is successful. */
+/* */
+/********************************************************/
+_Bool soc_starttls(SOCPTR *socptr,_Bool server)
+
+{
+_Bool ok;
+SOCTYP *soc;
+
+ok=false;
+soc=(SOCTYP *)socptr;
+if ((soc!=(SOCTYP *)0)&&(soc->modtls==false)) {
+ if ((soc->tls=tls_opentls(soc->handle,server))!=(TLSTYP *)0) {
+ soc->modtls=true;
+ ok=true;
+ }
+ }
+return ok;
+}
//procedure to release/clsoe socket
extern SOCPTR *soc_release(SOCPTR *socptr);
+//procedure to initiate crypted mode on plain channel
+extern _Bool soc_starttls(SOCPTR *socptr,_Bool server);
+
//homework to be done before starting/stopping module.
extern int soc_modedevsoc(_Bool mode);
#define OPEP "gesttcp.c:freecontact"
if (contact!=(CONTYP *)0) {
+ contact->fqdn=rou_freestr(contact->fqdn);
contact->peerip=rou_freestr(contact->peerip);
contact->locname=rou_freestr(contact->locname);
contact->locserv=rou_freestr(contact->locserv);
break; //no need to read line
default : //char available
phase=0; //check for new line
- if (soc_receive(contact->socptr)==0) {
- got=0;
+ if (soc_receive(contact->socptr)<0) {
+ got=-1;
phase=999; //remote disconnected?
}
break;
*/
/********************************************************/
/* */
+/* Procedure to send a signon on the current */
+/* channel (either plain of crypted). */
+/* Return the number of char transmitted. */
+/* */
+/********************************************************/
+PUBLIC int tcp_signon(CONTYP *contact)
+
+{
+#define OPEP "gestcp.c:tcp_signon"
+#define FMT "%d %s ESMTP %s-%s; %s%s"
+
+int sent;
+
+sent=0;
+if (contact!=(CONTYP *)0) {
+ char signon[100];
+
+ (void) snprintf(signon,sizeof(signon),FMT,
+ SIGNON,contact->locname,
+ appname,rou_getversion(),
+ rou_ascsysstamp(time((time_t *)0)),CRLF);
+ if ((sent=tcp_write(contact,signon,strlen(signon)))<0)
+ (void) rou_alert(0,"%s Unable to send signon to remote",OPEP);
+ }
+#undef FMT
+#undef OPEP
+return sent;
+}
+/*
+^L
+*/
+/********************************************************/
+/* */
/* Procedure to wait for a remote client. */
/* return all reference to the established contact.*/
/* */
}
break;
case 3 : //contact is good sending signon
- if (contact!=(CONTYP *)0) { //always
- #define FMT "%d %s ESMTP %s-%s; %s%s"
-
- char signon[100];
-
- (void) prc_settitle("Contact from peer '%s' started at %s",
- contact->peerip,
- rou_ascsysstamp(time((time_t *)0)));
- (void) snprintf(signon,sizeof(signon),FMT,
- SIGNON,contact->locname,
- appname,rou_getversion(),
- rou_ascsysstamp(time((time_t *)0)),CRLF);
- if (tcp_write(contact,signon,strlen(signon))<0) {
- (void) rou_alert(0,"%s Unable to send signon to remote",OPEP);
- contact=freecontact(contact);
- phase=999; //no contact
- }
- #undef FMT
+ if (tcp_signon(contact)<=0) {
+ contact=freecontact(contact);
+ phase=999; //no contact
}
break;
default : //SAFE guard
typedef struct {
SOCPTR *socptr; //established contact context
+ _Bool tlsok; //link is in crypted mode
+ char *fqdn; //fully qualified domain from peer
char *locname; //socket local hostname
char *locserv; //local service port
char *peerip; //socket remote peer IP
//Transmit formated data to the contact channel
extern int tcp_write(CONTYP *contact,char *buffer,int tosend);
+//send signon on channel
+extern int tcp_signon(CONTYP *contact);
+
//wait for an incoming contact
extern CONTYP *tcp_getcontact(SOCPTR *socptr,int pos);
va_end(args);
}
/*
+\f
+*/
+/************************************************/
+/* */
+/* Procedure to send an "HELO" message */
+/* if EHLO message is not accepted. */
+/* */
+/************************************************/
+static _Bool doehlo(CONTYP *contact,char *line)
+
+{
+static char *ehlostr[]= {
+ "-8BITMIME",
+ "-STARTTLS",
+ "-ENHANCEDSTATUSCODES",
+ "-AUTH PLAIN LOGIN",
+ " HELP",
+ (char *)0
+ };
+
+#define OPEP "unieml.c:doehlo"
+#define DETAIL "syntax error (domain part missing), disconnecting"
+
+_Bool done;
+char *fqdn;
+int phase;
+_Bool proceed;
+
+done=false;
+phase=0;
+proceed=true;
+while (proceed==true) {
+ switch (phase) {
+ case 0 : //Do we have
+ fqdn=strchr(line,' ');
+ if (fqdn!=(char *)0) {
+ while ((*fqdn==' ')||(*fqdn=='\t'))
+ fqdn++;
+ }
+ if ((fqdn==(char *)0)||(strlen(fqdn)==0)) {
+ (void) transmit(contact,"%d 5.5.4 %s",BADPAR,DETAIL);
+ phase=999; //Trouble trouble
+ }
+ break;
+ case 1 : //thereis an FQDN
+ contact->fqdn=rou_freestr(contact->fqdn);
+ contact->fqdn=strdup(fqdn);
+ (void) transmit(contact,"%d-%s ready, your IP=[%s]",
+ CMDOK,contact->locname,contact->peerip);
+ (void) transmit(contact,"%d-SIZE %ld",CMDOK,MXMSIZE);
+ for (int i=0;ehlostr[i]!=(char *)0;i++) {
+ (void) transmit(contact,"%d%s",CMDOK,ehlostr[i]);
+ }
+ done=true;
+ break;
+ default : //SAFE guard
+ proceed=false;
+ break;
+ }
+ phase++;
+ }
+return done;
+#undef DETAIL
+#undef OPEP
+}
+/*
^L
*/
/********************************************************/
status=tcp_getline(contact,&attend,&line);
if (status<=0) //timeout or trouble?
break; //no need to go further
+ (void) printf("JMPDBG getline got <%s>\n",line);
switch (eml_getcode(line)) {
- case c_quit : //quit SMTP protocol
- (void) transmit(contact,"%d closing connection",QUITOK);
+ case c_ehlo : //EHLO SMTP protocol
+ proceed=doehlo(contact,line);
+ break;
+ case c_quit : //QUIT SMTP protocol
+ (void) transmit(contact,"%d 2.0.0 Bye, closing connection",QUITOK);
proceed=false;
break;
+ case c_starttls : //EHLO start encryptel link
+ switch (soc_starttls(contact->socptr,true)) {
+ case true : //link now in TLS crypted mode
+ (void) tcp_signon(contact);
+ break;
+ case false : //unable to establish link
+ (void) transmit(contact,"%d 5.3.3 command starttls not successful",
+ CMDBAD);
+ status=-1;
+ proceed=false;
+ break;
+ }
+ break;
case c_unknown : //uknown keyword
- (void) transmit(contact,"%d command <%s> is unknown",CMDBAD,line);
+ (void) rou_alert(0,"Command <%s> from [%s] is unknown (config?)",
+ line,contact->peerip);
+ (void) transmit(contact,"%d 5.5.1 command <%s> is unknown",CMDBAD,line);
break;
default :
(void) rou_alert(0,"Unable to find keyword for <%s> (Bug?)",OPEP,line);
//version definition
#define VERSION "0.3"
-#define RELEASE "36"
+#define RELEASE "37"
//Public variables
PUBLIC int debug=0; //debug level
char *dropzone;
char command[100];
-dropzone=rou_apppath("/tmp/"APPNAME"-crash");
+(void) strcpy(command,"/tmp/");
+(void) strcat(command,APPNAME);
+(void) strcat(command,"-crash");
+dropzone=rou_apppath(command);
(void) snprintf(command,sizeof(command)-2,"mkdir -p %s",dropzone);
(void) system(command);
return dropzone;
char *root;
char *newpath;
int taille;
-char loc[3];
+char loc[300];
root="";
newpath=(char *)0;
//this list order by key length
static VOCTYP vocsmtp[]={
+ {c_ehlo,"EHLO"},
{c_quit,"QUIT"},
+ {c_starttls,"STARTTLS"},
{c_unknown,(const char *)0}
};
/*
code=c_unknown;
for (ptr=vocsmtp;ptr->code!=c_unknown;ptr++) {
- if (strcasecmp(ptr->key,keyword)==0) {
+ if (strncasecmp(ptr->key,keyword,strlen(ptr->key))==0) {
code=ptr->code;
break;
}
#ifndef UNIEML
#define UNIEML
+#define MXMSIZE 52428800 //52 Megabytes
#define CRLF "\r\n" //EOL within SMTP protocol
#define SIGNON 220 //signon information
#define QUITOK 221 //status on quit
+#define CMDOK 250 //Everything OK
+#define BADPAR 501 //error in parameters
#define CMDBAD 502 //command not implemented
//list of keyword
typedef enum { //list of SMTP protocol keyword
+ c_ehlo, //EHLO command
c_quit, //quit exchange
+ c_starttls, //Starting a TLS crypted link
c_unknown //key word unknown
}CODTYP;
phase=0;
proceed=true;
while (proceed==true) {
+ (void) printf("JMPDBG opentls phase='%d'\n",phase);
switch (phase) {
case 0 : //prepare the structure first;
tls=(TLSTYP *)calloc(1,sizeof(TLSTYP));
int sofar;
proceed=true;
+ (void) printf("JMPDBG sending <%s>\n",buffer);
while (proceed==true) {
proceed=false;
sofar=SSL_write(tls->ssl,buffer,tosend);
got=-1;
if (tls!=(TLSTYP *)0) {
- if ((got=SSL_read(tls->ssl,buffer,maxread))<=0)
+ if ((got=SSL_read(tls->ssl,buffer,maxread))<=0) {
(void) showtlserror(tls,got,"Trouble to read data");
+ got=-1;
+ }
}
return got;
}