]> SAFE projects GIT repository - jmp/mailleur/commitdiff
Major change aubout authentication within lvleml.c
authorJean-Marc Pigeon (Delson) <jmp@safe.ca>
Tue, 8 Jul 2025 19:45:36 +0000 (15:45 -0400)
committerJean-Marc Pigeon (Delson) <jmp@safe.ca>
Tue, 8 Jul 2025 19:45:36 +0000 (15:45 -0400)
lib/lvleml.c
lib/lvleml.h

index b40fe0248bbb733f57eb367f1dd631a52df8bac5..6db3a6d458b20190a23313e3de5165c2543ae663 100644 (file)
@@ -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
 }
 /*
index bac4e0637773c9d694d8be0c64fb120bdf42ef80..7aec7b0f86ce751b46097dde0fddc2627ccff96a 100644 (file)
@@ -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