From 77c11bd3e3cf1b16177b34c3673c1ef0c86a2391 Mon Sep 17 00:00:00 2001 From: "Jean-Marc Pigeon (Delson)" Date: Wed, 9 Jul 2025 07:09:08 -0400 Subject: [PATCH] Checking password against the hash function --- lib/devsql.c | 28 ++++---- lib/lvleml.c | 185 +++++++++------------------------------------------ lib/subrou.c | 20 +++++- lib/subrou.h | 3 + lib/unisql.c | 1 - lib/unisql.h | 3 +- 6 files changed, 65 insertions(+), 175 deletions(-) diff --git a/lib/devsql.c b/lib/devsql.c index 80e0bf9..d1c6788 100644 --- a/lib/devsql.c +++ b/lib/devsql.c @@ -41,17 +41,6 @@ typedef struct { char *name; //field name; }FLDTYP; -//field available in table "emails" -const FLDTYP usrfield[]={ - {1,"email"}, - {2,"password"}, - {3,"space"}, - {4,"mxspace"}, - {5,"locked"}, - {6,"hash"}, - {0,(char *)0} - }; - //field available in table "sessions" const char *sesfield[]={ "sessid", @@ -319,6 +308,16 @@ static USRTYP *select_user(SQLTYP *sql,char *email) #define OPEP "devsql.c:select_user," #define SELUSR "SELECT * FROM "EMAILS" WHERE email=%s" +//field available in table "emails" +static const FLDTYP usrfield[]={ + {1,"email"}, + {2,"hash"}, + {3,"space"}, + {4,"mxspace"}, + {5,"locked"}, + {0,(char *)0} + }; + USRTYP *usr; SQLRES *rs; char cmd[300]; @@ -367,8 +366,8 @@ while (proceed==true) { case 1 : //user email usr->email=strdup(locval); break; - case 2 : //user passwd - usr->passwd=strdup(locval); + case 2 : //'email:realm:password' MD5 + usr->hash=strdup(locval); break; case 3 : //user used space usr->space=atoi(locval); @@ -379,9 +378,6 @@ while (proceed==true) { case 5 : //lock status usr->lock=atoi(locval); break; - case 6 : //'email:realm:password' MD5 - usr->hash=strdup(locval); - break; default : (void) rou_alert(0,"%s field <%d:%s> not implemented (Bug?)", OPEP,usrfield[i].num,usrfield[i].name); diff --git a/lib/lvleml.c b/lib/lvleml.c index 810f830..7f8aa28 100644 --- a/lib/lvleml.c +++ b/lib/lvleml.c @@ -359,11 +359,13 @@ static _Bool checklogin(CONTYP *contact,char **rmtpass,char *sequence) _Bool isok; char *data[3]; +char *givenhash; int phase; _Bool proceed; isok=false; (void) memset(data,'\000',sizeof(data)); +givenhash=(char *)0; phase=0; proceed=true; while (proceed==true) { @@ -382,42 +384,37 @@ while (proceed==true) { phase=999; //No need to go further } break; - case 2 : { //checking user password + case 2 : { //computing the given md5 + char *seq; + MD5TYP *givenmd5; + + (void) rou_asprintf(&seq,"%s:%s:%s",data[1],rou_getrealm(),data[2]); + givenmd5=dig_hashmd5((unsigned char *)seq,strlen(seq)); + if (givenmd5!=(MD5TYP *)0) { + givenhash=cnv_tohexa((char *)givenmd5,sizeof(MD5TYP)); + (void) free(givenmd5); + } + if (givenhash==(char *)0) { + (void) rou_alert(0,"%s Unable to have md5 for <%s> (Bug?)",seq); + phase=999; //trouble trouble + } + seq=rou_freestr(seq); + } + break; + case 3 : { //checking user password USRTYP *usr; usr=(USRTYP *)0; contact->authname=rou_freestr(contact->authname); contact->authname=strdup(data[1]); + *rmtpass=strdup(data[2]); if (sql_mngusr(contact->sqlptr,sql_select,data[1],&usr)==true) { - char *givenpass; - - givenpass=data[2]; - if (usr->passwd==(char *)0) { - (void) rou_alert(0,"%s usr=<%s> password empty, assigning one", + if (usr->hash==(char *)0) { + usr->hash=cnv_getrndstr(10); + (void) rou_alert(0,"%s usr=<%s> password empty, using random hash", OPEP,data[1]); - usr->passwd=cnv_getrndstr(10); } - if (givenpass!=(char *)0) - *rmtpass=strdup(givenpass); - if (usr->passwd[0]=='$') { - char *ptr; - char idsalt[100]; - - (void) memset(idsalt,'\000',sizeof(idsalt)); - (void) strncpy(idsalt,usr->passwd,sizeof(idsalt)-1); - if ((ptr=strrchr(idsalt,'$'))!=(char *)0) { - ptr++; - *ptr='\000'; - } - if ((ptr=crypt(givenpass,idsalt))==(char *)0) { - (void) rou_alert(0,"%s Trouble to crypt (Bug?) givenpass=<%s> " - "salt=<%s> (error=<%s>)", - OPEP,givenpass,idsalt,strerror(errno)); - ptr=data[2]; //trying to overcome - } - givenpass=ptr; - } - isok=(strcmp(givenpass,usr->passwd)==0); + isok=(strcmp(givenhash,usr->hash)==0); usr=sql_freeusr(usr); } } @@ -428,6 +425,7 @@ while (proceed==true) { } phase++; } +givenhash=rou_freestr(givenhash); for (int i=0;i<3;i++) data[i]=rou_freestr(data[i]); return isok; @@ -521,126 +519,6 @@ if (strlen(local)>0) /********************************************************/ /* */ /* Procedure to manage authentication in */ -/* cram_md5 mode. */ -/* Return a builded "decoded" string from */ -/* the exchange with the remote sereur */ -/* */ -/********************************************************/ -static void get_auth_cram_md5(CONTYP *contact,char **rmtpass) - -{ -#define OPEP "lvleml.c:get_auth_cram_md5," - -char challenge[300]; -char answer[300]; -char name[300]; -char passwd[300]; -int phase; -_Bool proceed; - -(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) { - //(void) rou_alert(0,"%s JMPDBG phase='%d'",OPEP,phase); - switch (phase) { - case 0 : { //Building the challenge sequence - TIMESPEC cur; - char *sessid; - - (void) clock_gettime(CLOCK_REALTIME,&cur); - cur.tv_nsec/=10000; //100 millisec - sessid=contact->session->sessid; - (void) snprintf(challenge,sizeof(challenge),"%05lu-%s",cur.tv_nsec,sessid); - } - break; - case 1 : { //sending challenge to remote - char *b64; - - b64=cnv_setb64(challenge); - (void) transmit(contact,true,"%d %s",SENDB64,b64); - b64=rou_freestr(b64); - } - break; - case 2 : { //getting the challenge answer - char *line; - - if (tcp_getline(contact->socptr,contact->delay,&line)>0) { - char *res; - - res=cnv_getb64(line); - (void) snprintf(answer,sizeof(answer),"%s",res); - res=rou_freestr(res); - line=rou_freestr(line); - } - if (strlen(answer)==0) - phase=999; //no need to go further - } - break; - case 3 : { //working with challenge answer - char *ptr; - - if ((ptr=strchr(answer,' '))!=(char *)0) { - *ptr='\000'; - ptr++; - (void) strncpy(name,answer,sizeof(name)); - (void) memmove(answer,ptr,strlen(ptr)+1); - } - if (strlen(name)==0) - phase=999; //no need to go further - } - break; - case 4 : { //extracting user information - USRTYP *usr; - - contact->authname=rou_freestr(contact->authname); - contact->authname=strdup(name); - if (sql_mngusr(contact->sqlptr,sql_select,name,&usr)==true) { - (void) snprintf(passwd,sizeof(passwd),"%s",usr->passwd); - usr=sql_freeusr(usr); - } - if (strlen(passwd)==0) - phase=999; //no need to go further - } - break; - case 5 : //check if password is in clear text - if (passwd[0]=='$') { //local password crypted? - (void) transmit(contact,true,"%d-5.8.1 password is crypted",BADPAR); - phase=999; //no need to go further - } - break; //exiting from loop - case 6 : { //comparing challenge answer - char *local; - char *hexa; - - local=dig_cryptmd5(passwd,(unsigned char *)challenge); - hexa=cnv_tohexa(local,strlen(local)); - //(void) rou_alert(0,"%s anwr=<%s>",OPEP,answer); - //(void) rou_alert(0,"%s hexa=<%s>",OPEP,hexa); - contact->authenticated=(strcmp(hexa,answer)==0); - hexa=rou_freestr(hexa); - local=rou_freestr(local); - } - break; - default : //SAFE Guard - proceed=false; - break; - } - phase++; - } - -#undef OPEP -} -/* -^L -*/ -/********************************************************/ -/* */ -/* Procedure to manage authentication in */ /* digest-md5 mode. */ /* Return a builded "decoded" string from */ /* the exchange with the remote sereur */ @@ -804,7 +682,7 @@ static _Bool getauth(CONTYP *contact,char *buffer) { #define OPEP "lvleml.c:getauth," -static char *vocloc[]={"PLAIN","LOGIN","CRAM-MD5","DIGEST-MD5",(char *)0}; +static char *vocloc[]={"PLAIN","LOGIN","DIGEST-MD5",(char *)0}; int code; char *rmtpass; @@ -866,10 +744,7 @@ while (proceed==true) { else (void) transmit(contact,true,"%d 5.7.4 Unsafe LOGIN auth mode",FAILED); break; - case 2 : //AUTH CRAM-MD5 - (void) get_auth_cram_md5(contact,&rmtpass); - break; - case 3 : //AUTH DIGEST-MD5 + case 2 : //AUTH DIGEST-MD5 (void) get_auth_digest_md5(contact,&rmtpass); break; default : //not yet implemented @@ -1320,8 +1195,8 @@ static struct { char *str; //the message to display }ehlo[]={ {1,"STARTTLS"}, - {1,"AUTH CRAM-MD5 DIGEST-MD5"}, - {2,"AUTH PLAIN LOGIN CRAM-MD5 DIGEST-MD5"}, + {1,"AUTH DIGEST-MD5"}, + {2,"AUTH PLAIN LOGIN DIGEST-MD5"}, {0,"SIZE "MXMSIZE}, {0,"8BITMIME"}, {0,"ENHANCEDSTATUSCODES"}, diff --git a/lib/subrou.c b/lib/subrou.c index 749198d..6b8421b 100644 --- a/lib/subrou.c +++ b/lib/subrou.c @@ -108,7 +108,7 @@ if ((debug>2)&&(current!=onoff)) { /* */ /* Procedure to assign enough memory to format */ /* a string with va_list parameter. */ -/* Known as vasprintf in GNU_SOURCE. */ +/* Known as vasprintf in GNU_SOURCE. */ /* */ /********************************************************/ PUBLIC int rou_vasprintf(char **str,const char *fmt,va_list ap) @@ -130,6 +130,24 @@ return taille; */ /********************************************************/ /* */ +/* Procedure to return the current application */ +/* working realm */ +/* */ +/********************************************************/ +PUBLIC const char *rou_getrealm() + +{ +const char *realm; + +if ((realm=getenv("REALM"))==(const char *)0) + realm=REALM; +return realm; +} +/* + +*/ +/********************************************************/ +/* */ /* Procedure to assign enough memory to format */ /* a string. */ /* Known as asprintf in GNU_SOURCE. */ diff --git a/lib/subrou.h b/lib/subrou.h index 1a3c786..298d7a8 100644 --- a/lib/subrou.h +++ b/lib/subrou.h @@ -45,6 +45,9 @@ extern int rou_vasprintf(char **str,const char *fmt,va_list ap); //procedure to assign memory according a format and parameter list extern int rou_asprintf(char **str,const char *fmt,...); +//procedure to return the application working realm +extern const char *rou_getrealm(); + //procedure to create needed subdirectory extern _Bool rou_do_mkpdir(char *dirpath); diff --git a/lib/unisql.c b/lib/unisql.c index 909a356..76a1d28 100644 --- a/lib/unisql.c +++ b/lib/unisql.c @@ -107,7 +107,6 @@ PUBLIC USRTYP *sql_freeusr(USRTYP *usr) { if (usr!=(USRTYP *)0) { usr->hash=rou_freestr(usr->hash); - usr->passwd=rou_freestr(usr->passwd); usr->email=rou_freestr(usr->email); (void) free(usr); usr=(USRTYP *)0; diff --git a/lib/unisql.h b/lib/unisql.h index e0dcab8..4dcf553 100644 --- a/lib/unisql.h +++ b/lib/unisql.h @@ -20,11 +20,10 @@ typedef enum { //structure about user within the database typedef struct { char *email; //user emails - char *passwd; //user password + char *hash; //'email:realm:password' MD5 u_int lock; //account is lock u_long space; //user space used u_long mxspace; //user maximun space - char *hash; //'email:realm:password' MD5 }USRTYP; //structure about an email session -- 2.47.3