From: Jean-Marc Pigeon (Delson) Date: Tue, 8 Jul 2025 19:45:36 +0000 (-0400) Subject: Major change aubout authentication within lvleml.c X-Git-Tag: tag-0.13~22 X-Git-Url: https://jmp-git.ovh.safe.ca/?a=commitdiff_plain;h=c4b4848a282743f190d514fda4f9b98173fa1ff7;p=jmp%2Fmailleur Major change aubout authentication within lvleml.c --- diff --git a/lib/lvleml.c b/lib/lvleml.c index b40fe02..6db3a6d 100644 --- a/lib/lvleml.c +++ b/lib/lvleml.c @@ -87,6 +87,7 @@ if (contact!=(CONTYP *)0) { contact->logptr=log_closelog(contact->logptr); contact->recipients=(RCPTYP **)rou_freelist((void **)contact->recipients, (genfree_t)eml_freerecipient); + contact->authname=rou_freestr(contact->authname); contact->mailfrom=rou_freestr(contact->mailfrom); contact->mainsesid=rou_freestr(contact->mainsesid); contact->fqdn=rou_freestr(contact->fqdn); @@ -314,17 +315,120 @@ return status; */ /********************************************************/ /* */ +/* Procedure to split a plain authentication string*/ +/* Match with the user provided. */ +/* */ +/********************************************************/ +static void split_auth_plain(char *sequence,char *data[3]) + +{ +char *locdata[3]; +char *dup; +char *ptr; +int count; + +(void) memset(locdata,'\000',sizeof(locdata)); +dup=strdup(sequence); +ptr=dup; +for (count=0;(count<3)&&(ptr!=(char *)0);count++) { + char *mark; + + if ((mark=strstr(ptr,IOBNULL))!=(char *)0) { + *mark='\000'; + mark+=strlen(IOBNULL); + } + locdata[count]=strdup(ptr); + ptr=mark; + } +(void) memmove(data,locdata,sizeof(locdata)); +dup=rou_freestr(dup); +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to check if the password submitted */ +/* Match with the user provided. */ +/* */ +/********************************************************/ +static _Bool checklogin(SQLPTR *sqlptr,char *sequence) + +{ +#define OPEP "lvleml.c:checklogin," + +_Bool isok; +char *data[3]; +int phase; +_Bool proceed; + +isok=false; +(void) memset(data,'\000',sizeof(data)); +phase=0; +proceed=true; +while (proceed==true) { + switch (phase) { + case 0 : //make sure we have data + (void) split_auth_plain(sequence,data); + if ((data[1]==(char *)0)||(data[2]==(char *)0)) { + (void) rou_alert(0,"%s missing data from <%s> (Bug?)",OPEP,sequence); + phase=999; //No need to go further + } + break; + case 1 : //do we have valide data? + if ((strlen(data[1])==0)||(strlen(data[2])==0)) { + (void) rou_alert(0,"%s data[1]=<%s> or data[2]=<%s> missing (Bug?)", + OPEP,data[1],data[2]); + phase=999; //No need to go further + } + break; + case 2 : { //checking user password + USRTYP *usr; + + usr=(USRTYP *)0; + if (sql_mngusr(sqlptr,sql_select,data[1],&usr)==true) { + char *crypted; + + crypted=data[2]; + if (usr->passwd[0]=='$') + crypted=crypt(data[2],usr->passwd); + if ((crypted!=(char *)0)&&(strcmp(crypted,usr->passwd)==0)) + isok=true; //Passord match + usr=sql_freeusr(usr); + } + } + break; + default : //SAFE Guard + proceed=false; + break; + } + phase++; + } +for (int i=0;i<3;i++) + data[i]=rou_freestr(data[i]); +return isok; + +#undef OPEP +} +/* +^L +*/ +/********************************************************/ +/* */ /* Procedure to manage authentication in "plain" */ /* mode, return "decoded", NULL if not extracted */ /* */ /********************************************************/ -static char *get_auth_plain(CONTYP *contact,char *received) +static _Bool get_auth_plain(CONTYP *contact,char *received,char **rmtpass) { #define OPEP "lvleml.c:get_auth_plain," +_Bool goodpass; char *decoded; +goodpass=false; +*rmtpass=(char *)0; decoded=(char *)0; if ((received==(char *)0)||(strlen(received)==0)) { char *line; @@ -339,9 +443,13 @@ if ((received==(char *)0)||(strlen(received)==0)) { line=rou_freestr(line); } } -else +else decoded=cnv_getb64(received); -return decoded; +if (decoded!=(char *)0) { + goodpass=checklogin(contact->sqlptr,decoded); + decoded=rou_freestr(decoded); + } +return goodpass; #undef OPEP } @@ -350,18 +458,62 @@ return decoded; */ /********************************************************/ /* */ +/* Procedure to manage authentication in "login" */ +/* mode, return goodpass true if successful */ +/* */ +/********************************************************/ +static _Bool get_auth_login(CONTYP *contact,char **rmtpass) + +{ +static char *logdat[]={"VXNlcm5hbWU6", //Username: in B64 + "UGFzc3dvcmQ6", //Password: in B64 + (char *)0}; +_Bool goodpass; +char local[200]; + +goodpass=false; +(void) memset(local,'\000',sizeof(local)); +for (int i=0;i<2;i++) { + char *line; + char *ptr; + int got; + + (void) strcat(local,IOBNULL); + (void) transmit(contact,true,"%d %s",SENDB64,logdat[i]); + got=tcp_getline(contact->socptr,contact->delay,&line); + if (got<=0) { + (void) strcpy(local,""); + (void) transmit(contact,true,"%d 5.7.2 auth sequence missing",UKNUSER); + break; //exiting from loop + } + (void) log_fprintlog(contact->logptr,false,"%s",line); + if ((ptr=cnv_getb64(line))!=(char *)0) { + (void) strncat(local,ptr,(sizeof(local)-1)-strlen(ptr)); + ptr=rou_freestr(ptr); + } + line=rou_freestr(line); + } +if (strlen(local)>0) + goodpass=checklogin(contact->sqlptr,local); +return goodpass; +} +/* +^L +*/ +/********************************************************/ +/* */ /* Procedure to manage authentication in */ /* cram_md5 mode. */ /* Return a builded "decoded" string from */ /* the exchange with the remote sereur */ /* */ /********************************************************/ -static char *get_auth_cram_md5(CONTYP *contact) +static _Bool get_auth_cram_md5(CONTYP *contact,char **rmtpass) { #define OPEP "lvleml.c:get_auth_cram_md5," -char *decoded; +_Bool goodpass; char challenge[300]; char answer[300]; char name[300]; @@ -369,11 +521,12 @@ char passwd[300]; int phase; _Bool proceed; -decoded=(char *)0; +goodpass=false; (void) memset(challenge,'\000',sizeof(challenge)); (void) memset(answer,'\000',sizeof(answer)); (void) memset(name,'\000',sizeof(name)); (void) memset(passwd,'\000',sizeof(passwd)); +*rmtpass=strdup("$1(ukn as cram_md5)"); phase=0; proceed=true; while (proceed==true) { @@ -444,21 +597,17 @@ while (proceed==true) { hexa=cnv_tohexa(local,strlen(local)); //(void) rou_alert(0,"%s anwr=<%s>",OPEP,answer); //(void) rou_alert(0,"%s hexa=<%s>",OPEP,hexa); - if (strcmp(hexa,answer)!=0) - (void) strncpy(passwd,"$1(ukn as cram_md5)",sizeof(passwd)-1); - (void) rou_asprintf(&decoded,"%s%s%s%s",IOBNULL,name,IOBNULL,passwd); + goodpass=(strcmp(hexa,answer)==0); hexa=rou_freestr(hexa); local=rou_freestr(local); } default : //SAFE Guard - (void) memset(passwd,'\000',sizeof(passwd)); proceed=false; break; } phase++; } -//(void) rou_alert(0,"%s JMPDBG decoded=<%s>",OPEP,decoded); -return decoded; +return goodpass; #undef OPEP } @@ -475,22 +624,21 @@ return decoded; /* */ /* */ /********************************************************/ -static char *get_auth_digest_md5(CONTYP *contact) +static void get_auth_digest_md5(CONTYP *contact,char **rmtpass) { #define OPEP "lvleml.c:get_auth_digest_md5," -char *decoded; +char *tmppass; char *challenge; -char *curpass; RSPTYP *resp; char answer[300]; int phase; _Bool proceed; -decoded=(char *)0; +tmppass="bigre"; //JMPDBG need to be improved +*rmtpass=strdup("$1(ukn as digest_md5)"); challenge=(char *)0; -curpass=(char *)0; resp=(RSPTYP *)0; (void) memset(answer,'\000',sizeof(answer)); phase=0; @@ -539,20 +687,15 @@ while (proceed==true) { USRTYP *usr; if (sql_mngusr(contact->sqlptr,sql_select,resp->username,&usr)==true) { - if (usr->passwd!=(char *)0) - curpass=strdup(usr->passwd); usr=sql_freeusr(usr); } - if (curpass==(char *)0) - phase=999; //No user found } break; case 5 : { //sending the rspauth sequence. char *HAS; char *rspauth; char *b64; - - if ((HAS=dig_hashresp(resp,"",curpass))==(char *)0) { + if ((HAS=dig_hashresp(resp,"",tmppass))==(char *)0) { (void) rou_alert(0,"%s Unable to get the hash rspauth (Bug!)",OPEP); break; } @@ -579,22 +722,14 @@ while (proceed==true) { case 7 : { //comparing result. char *HA0; - if ((HA0=dig_hashresp(resp,"AUTHENTICATE",curpass))==(char *)0) { + if ((HA0=dig_hashresp(resp,"AUTHENTICATE",tmppass))==(char *)0) { (void) rou_alert(0,"%s Unable to get the hash response (Bug!)",OPEP); break; } - if (strcmp(HA0,resp->response)!=0) { - //user authentication failed - curpass=rou_freestr(curpass); - (void) rou_asprintf(&curpass,"$1(ukn as digest_md5)"); - } + contact->authenticated=(strcmp(HA0,resp->response)==0); HA0=rou_freestr(HA0); } break; - case 8 : //comparing answer - (void) rou_asprintf(&decoded,"%s%s%s%s",IOBNULL,resp->username, - IOBNULL,curpass); - break; default : //SAFE Guard proceed=false; break; @@ -602,9 +737,7 @@ while (proceed==true) { phase++; } resp=dig_freeresp(resp); -curpass=rou_freestr(curpass); challenge=rou_freestr(challenge); -return decoded; #undef OPEP } @@ -613,150 +746,6 @@ return decoded; */ /********************************************************/ /* */ -/* Procedure to manage authentication in "login" */ -/* mode, return "decoded", NULL if not extracted */ -/* */ -/********************************************************/ -static char *get_auth_login(CONTYP *contact) - -{ -static char *logdat[]={"VXNlcm5hbWU6", //Username: in B64 - "UGFzc3dvcmQ6", //Password: in B64 - (char *)0}; -char *decoded; -char local[200]; - -decoded=(char *)0; -(void) memset(local,'\000',sizeof(local)); -for (int i=0;i<2;i++) { - char *line; - char *ptr; - int got; - - (void) strcat(local,IOBNULL); - (void) transmit(contact,true,"%d %s",SENDB64,logdat[i]); - got=tcp_getline(contact->socptr,contact->delay,&line); - if (got<=0) { - (void) strcpy(local,""); - (void) transmit(contact,true,"%d 5.7.2 auth sequence missing",UKNUSER); - break; //exiting from loop - } - (void) log_fprintlog(contact->logptr,false,"%s",line); - if ((ptr=cnv_getb64(line))!=(char *)0) { - (void) strncat(local,ptr,(sizeof(local)-1)-strlen(ptr)); - ptr=rou_freestr(ptr); - } - line=rou_freestr(line); - } -if (strlen(local)>0) - decoded=strdup(local); -return decoded; -} -/* -^L -*/ -/********************************************************/ -/* */ -/* Procedure to split a plain authentication string*/ -/* Match with the user provided. */ -/* */ -/********************************************************/ -static void split_auth_plain(char *sequence,char *data[3]) - -{ -char *locdata[3]; -char *dup; -char *ptr; -int count; - -(void) memset(locdata,'\000',sizeof(locdata)); -dup=strdup(sequence); -ptr=dup; -for (count=0;(count<3)&&(ptr!=(char *)0);count++) { - char *mark; - - if ((mark=strstr(ptr,IOBNULL))!=(char *)0) { - *mark='\000'; - mark+=strlen(IOBNULL); - } - locdata[count]=strdup(ptr); - ptr=mark; - } -(void) memmove(data,locdata,sizeof(locdata)); -dup=rou_freestr(dup); -} -/* -^L -*/ -/********************************************************/ -/* */ -/* Procedure to check if the password submitted */ -/* Match with the user provided. */ -/* */ -/********************************************************/ -static _Bool checklogin(SQLPTR *sqlptr,char *sequence) - -{ -#define OPEP "lvleml.c:checklogin," - -_Bool isok; -char *data[3]; -int phase; -_Bool proceed; - -isok=false; -(void) memset(data,'\000',sizeof(data)); -phase=0; -proceed=true; -while (proceed==true) { - switch (phase) { - case 0 : //make sure we have data - (void) split_auth_plain(sequence,data); - if ((data[1]==(char *)0)||(data[2]==(char *)0)) { - (void) rou_alert(0,"%s missing data from <%s> (Bug?)",OPEP,sequence); - phase=999; //No need to go further - } - break; - case 1 : //do we have valide data? - if ((strlen(data[1])==0)||(strlen(data[2])==0)) { - (void) rou_alert(0,"%s data[1]=<%s> or data[2]=<%s> missing (Bug?)", - OPEP,data[1],data[2]); - phase=999; //No need to go further - } - break; - case 2 : { //checking user password - USRTYP *usr; - - usr=(USRTYP *)0; - if (sql_mngusr(sqlptr,sql_select,data[1],&usr)==true) { - char *crypted; - - crypted=data[2]; - if (usr->passwd[0]=='$') - crypted=crypt(data[2],usr->passwd); - if ((crypted!=(char *)0)&&(strcmp(crypted,usr->passwd)==0)) - isok=true; //Passord match - usr=sql_freeusr(usr); - } - } - break; - default : //SAFE Guard - proceed=false; - break; - } - phase++; - } -for (int i=0;i<3;i++) - data[i]=rou_freestr(data[i]); -return isok; - -#undef OPEP -} -/* -^L -*/ -/********************************************************/ -/* */ /* Procedure to extract authentication info. */ /* return a login sequence as */ /* 'username password' if successful */ @@ -770,16 +759,14 @@ static _Bool getauth(CONTYP *contact,char *buffer) static char *vocloc[]={"PLAIN","LOGIN","CRAM-MD5","DIGEST-MD5",(char *)0}; -_Bool isok; int code; -char *decoded; +char *rmtpass; char local[200]; int phase; _Bool proceed; -isok=false; code=-1; -decoded=(char *)0; +rmtpass=(char *)0; (void) memset(local,'\000',sizeof(memset)); phase=0; proceed=true; @@ -822,61 +809,46 @@ while (proceed==true) { switch (code) { case 0 : //AUTH PLAIN if (soc_iscrypted(contact->socptr)==true) - decoded=get_auth_plain(contact,local); + (void) get_auth_plain(contact,local,&rmtpass); else (void) transmit(contact,true,"%d 5.7.3 Unsafe PLAIN auth mode",FAILED); break; case 1 : //AUTH LOGIN if (soc_iscrypted(contact->socptr)==true) - decoded=get_auth_login(contact); + (void) get_auth_login(contact,&rmtpass); else - (void) transmit(contact,true,"%d 5.7.3 Unsafe LOGIN auth mode",FAILED); + (void) transmit(contact,true,"%d 5.7.4 Unsafe LOGIN auth mode",FAILED); break; case 2 : //AUTH CRAM-MD5 - decoded=get_auth_cram_md5(contact); + (void) get_auth_cram_md5(contact,&rmtpass); break; case 3 : //AUTH DIGEST-MD5 - decoded=get_auth_digest_md5(contact); + (void) get_auth_digest_md5(contact,&rmtpass); break; default : //not yet implemented - (void) transmit(contact,true,"%d 5.7.3 Unknown auth mode",FAILED); + (void) transmit(contact,true,"%d 5.7.5 Unknown auth mode",FAILED); (void) rou_alert(0,"%s auth type <%d> not yet implemented",OPEP); phase=999; break; } break; - case 4 : //do we have a decoded sequence?? - if (decoded==(char *)0) { - (void) transmit(contact,true,"%d 5.7.4 empty auth sequence",FAILED); - phase=999; + case 4 : { //do we have a decoded sequence?? + char *fmt; + char *auth; + + fmt=" Auth accepted for user=<%s>"; + auth=contact->authname; + if (contact->authenticated==false) { + fmt=" Auth Rejected status='%d' for user=<%s> pass=<%s>"; + (void) log_fprintlog(contact->logptr,true,fmt,BADAUTH,auth,rmtpass); + (void) sleep(2); + (void) transmit(contact,true,"%d 5.7.4 authentication failed",BADAUTH); } - break; - case 5 : //we have a decoded sequence, check password - isok=checklogin(contact->sqlptr,decoded); - contact->authenticated=true; - break; - case 6 : //we have login status - if (strlen(decoded)>0) { //always - char *data[3]; - const char *fmt; - - (void) memset(data,'\000',sizeof(data)); - (void) split_auth_plain(decoded,data); - fmt=" Auth accepted for user=<%s>"; - if (isok==false) { - fmt=" Auth Rejected status='%d' for user=<%s> pass=<%s>"; - (void) log_fprintlog(contact->logptr,true,fmt,BADAUTH,data[1],data[2]); - (void) sleep(2); - (void) transmit(contact,true,"%d 5.7.4 authentication failed",BADAUTH); - } - else { - (void) log_fprintlog(contact->logptr,true,fmt,data[1]); - (void) transmit(contact,true,"%d 5.7.5 Authentication successful",IDOK); - } - for (int i=0;i<3;i++) - data[i]=rou_freestr(data[i]); + else { + (void) log_fprintlog(contact->logptr,true,fmt,auth[1]); + (void) transmit(contact,true,"%d 5.7.5 Authentication successful",IDOK); } - decoded=rou_freestr(decoded); + } break; default : //SAFE Guard proceed=false; @@ -884,7 +856,8 @@ while (proceed==true) { } phase++; } -return isok; +rmtpass=rou_freestr(rmtpass); +return contact->authenticated; #undef OPEP } /* diff --git a/lib/lvleml.h b/lib/lvleml.h index bac4e06..7aec7b0 100644 --- a/lib/lvleml.h +++ b/lib/lvleml.h @@ -22,6 +22,7 @@ typedef struct { char *fqdn; //fully qualified domain from peer char *locip; //socket local IP num _Bool authenticated; //Link is authenticated + char *authname; //Link is authenticated name AFNTYP **localafn; //local IP as an AFNUM char *locname; //socket local hostname char *locserv; //local service port