modules/ep/mail_parser.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following functions.
  1. InitializeMailDescr
  2. EP_ParseMail
  3. EP_ParseText
  4. EP_MIMEParse
  5. EP_InitializeRootNode
  6. EP_InitializeNode
  7. EP_DefineNewNode
  8. EP_TreeCleanUp
  9. MailHeaderFieldCleanUp
  10. EP_MailDescrCleanUp
  11. EP_BuildFilename
  12. EP_ShowTree
  13. EP_DefineNewToken
  14. AddKeyInfo
  15. RemoveKeyInfo
  16. ep_GetPasswords
  17. EP_GetTokens
  18. EP_PrintTokens
  19. EP_CleanTokens

   1 /***************************************
   2   $Revision: 1.33 $
   3 
   4   Email Parser module (ep) - wrapping functions to parse email,
   5   calling MM and PA.
   6 
   7   Status: NOT REVUED, TESTED
   8 
   9   ******************/ /******************
  10   Filename            : mail_parser.c
  11   Authors             : Filippo Portera, Daniele Arena
  12   OSs Tested          : Solaris 7
  13   ******************/ /******************
  14   Copyright (c) 2000,2001,2002                    RIPE NCC
  15  
  16   All Rights Reserved
  17   
  18   Permission to use, copy, modify, and distribute this software and its
  19   documentation for any purpose and without fee is hereby granted,
  20   provided that the above copyright notice appear in all copies and that
  21   both that copyright notice and this permission notice appear in
  22   supporting documentation, and that the name of the author not be
  23   used in advertising or publicity pertaining to distribution of the
  24   software without specific, written prior permission.
  25   
  26   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  27   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  28   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  29   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  30   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  31   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  32   ***************************************/
  33 
  34 #include <stdio.h>
  35 #include <string.h>
  36 #include <stdlib.h>
  37 #include <netdb.h>
  38 #include <sys/param.h>
  39 
  40 #include "mm.h"
  41 #include "gpg.h"
  42 #include "mail_parser.h"
  43 
  44 /* Parse the mail message stored in inputFile and develop it
  45    in distinct text files, writing them on the outputPath
  46    directory and using the variable keyRing to read public
  47    keys needed for the verification process.   
  48    
  49    The common use of this parse should look like this:
  50    
  51    p = EP_ParseMessage("mail.001", "/tmp", "~/.gnupg/pubring.gpg");
  52 
  53    < parse the tree: p->tree >
  54 
  55    EP_TreeCleanUp(p);
  56  
  57 */
  58 
  59 /* Globals to store shared data for tree nodes */
  60 
  61 char EP_outputPrefix[FILENAME_LENGTH];
  62 /* char EP_keyRing[FILENAME_LENGTH];
  63    char EP_gpgcmd[FILENAME_LENGTH]; */
  64 int  EP_TreeHeight;
  65 int  EP_Node_ID;
  66 int  EP_Debug;
  67 
  68 const char *vS_strRC[] = { "IS_VALID",
  69                            "IS_NOT_PGP",
  70                            "KO",
  71                            "CRC_ERROR",
  72                            "NO_PUBLIC_KEY",
  73                            "NO_OPENPGP_DATA",
  74                            "NO_IN_FILES",
  75                            "NO_OUT_FILES",
  76                            "TO_BE_PGPVERIFIED",
  77                            "UNABLE_TO_WRITE_FILE",
  78                            "UNMATCHED_PGP_DELIMITERS"
  79                          };
  80 
  81 #define EP_TREEMAXHEIGHT 10;
  82 
  83 EP_Mail_DescrPtr InitializeMailDescr( const char *inputFile ) {
     /* [<][>][^][v][top][bottom][index][help] */
  84 
  85   EP_Mail_DescrPtr ptr;
  86   /*  EPNodePtr rootNode; */
  87   int retcode;
  88   long debug = 0;
  89 
  90   ptr = UT_malloc(sizeof(EP_Mail_Descr));
  91 
  92   ptr->from = ptr->subject = ptr->date = 
  93   ptr->message_id = ptr->reply_to = ptr->cc = 
  94   ptr->content_type = NULL ;
  95 
  96 
  97   /* Obtain headers */
  98   retcode = MM_get_headers(inputFile, ptr, debug);
  99 
 100   ptr->tree = EP_InitializeRootNode(inputFile);
 101   
 102   return ptr;
 103 }
 104 
 105 /* ------------------------------------------------- */
 106 
 107 EP_Mail_DescrPtr EP_ParseMail(const char *inputFile,
     /* [<][>][^][v][top][bottom][index][help] */
 108                               const char *outputPath) {
 109   EP_Mail_DescrPtr ptr;
 110   char hostname[MAXHOSTNAMELEN];
 111   int retcode;
 112   long debug = 0;
 113   char mail_file[FILENAMELEN];
 114 
 115   EP_Debug = debug;
 116 
 117   gethostname(hostname, MAXHOSTNAMELEN);
 118   sprintf(EP_outputPrefix, "%s/EPMtmp.%s.%d.", outputPath,
 119           hostname, getpid());
 120   PA_SetOutputPrefix(EP_outputPrefix);
 121 
 122   /*
 123   strcpy(EP_keyRing, keyRing);
 124   strcpy(EP_gpgcmd, gpgcmd);
 125   */
 126 
 127   sprintf (mail_file,"%sunprocessed", EP_outputPrefix);      /* the file where the mail message will be stored */
 128 
 129   /* if ((retcode = MM_store((char*)inputFile,mail_file, debug)) != 0)
 130     exit (retcode); */
 131 
 132   MM_store((char*)inputFile,mail_file, debug, 0);
 133   
 134   ptr = InitializeMailDescr(mail_file);
 135   /* Invoke the MIME parser */
 136   retcode = MM_extract_mime(mail_file, NULL, ptr->tree, debug);
 137 
 138   return ptr;
 139 }
 140 
 141 /* ------------------------------------------------- */
 142 
 143 EPNodePtr EP_ParseText(const char *inputFile,
     /* [<][>][^][v][top][bottom][index][help] */
 144                        const char *outputPath) {
 145   EPNodePtr ptr;
 146   char hostname[MAXHOSTNAMELEN];
 147 
 148   EP_Debug = 0;
 149 
 150   gethostname(hostname, MAXHOSTNAMELEN);
 151   sprintf(EP_outputPrefix, "%s/EPTtmp.%s.%d.", outputPath,
 152           hostname, getpid());
 153 
 154   /*
 155   strcpy(EP_keyRing, keyRing);
 156   strcpy(EP_gpgcmd, gpgcmd);
 157   */
 158 
 159   ptr = EP_InitializeRootNode(inputFile);
 160 
 161   PA_SetOutputPrefix(EP_outputPrefix);
 162   return PA_ParseMessage(ptr);
 163 }
 164 
 165 
 166 /* ------------------------------------------------- */
 167 
 168 EPNodePtr EP_MIMEParse(const EPNodePtr p)
     /* [<][>][^][v][top][bottom][index][help] */
 169 {
 170   char mail_file[FILENAMELEN];
 171   int retcode;
 172   FILE * fin;
 173   char *strptr;
 174   int found = 0, headers_end = 0;
 175   char txt[MAX_LINE_BUF];
 176 
 177   sprintf (mail_file,"%s%d.unprocessed", EP_outputPrefix, p->nodeID);      /* the file where the mail message will be stored */
 178   
 179   PA_SetOutputPrefix(EP_outputPrefix);
 180   /* Quest for a mail header:
 181      look for a mail header of type (content-type || mime version).
 182   */
 183 
 184   if ((fin = fopen(p->file, "r")) != NULL) { 
 185     while ( !headers_end && !found && 
 186             (strptr = fgets(txt, MAX_LINE_BUF, fin)) != NULL) {
 187       if ( do_regex_test("^Content-Type:", txt) || 
 188            do_regex_test("^MIME-Version:", txt)) {
 189         found = 1;
 190         fclose(fin);
 191         
 192         /* if ((retcode = MM_store((char*)p->file,mail_file, EP_Debug)) != 0) {
 193            fprintf(stderr, "Error on MM_Store: %d\n", retcode );
 194            } */
 195 
 196         MM_store((char*)p->file,mail_file, EP_Debug, 0);
 197 
 198         /* Invoke the MIME parser */
 199         retcode = MM_extract_mime(mail_file, NULL, p, EP_Debug);
 200       } else
 201         if ( do_regex_test("^ *\n", txt) ) 
 202           headers_end = 1; 
 203     }
 204 
 205     if (!found) {
 206       fclose(fin);
 207       PA_SetOutputPrefix(EP_outputPrefix);
 208 
 209       PA_ParseMessage(p);
 210 
 211     }
 212 
 213   } else {
 214     p->isValidPGPSignature = vS_NO_IN_FILES;
 215   }
 216 
 217   return p;
 218 }
 219 
 220 /* ------------------------------------------------- */
 221 
 222 EPNodePtr EP_InitializeRootNode( const char *inputFile ) {
     /* [<][>][^][v][top][bottom][index][help] */
 223   EPNodePtr rootNode;
 224 
 225   EP_TreeHeight = EP_Node_ID = 0;
 226 
 227   rootNode = UT_malloc(sizeof(struct EPNode));
 228 
 229   rootNode->nodeID = 0;
 230   rootNode->isValidPGPSignature = vS_IS_NOT_PGP;
 231   rootNode->keyID = 0;
 232   rootNode->MIMEContentType = -1;
 233   rootNode->strMIMEContentType = NULL;
 234   rootNode->file = strdup(inputFile);
 235   rootNode->inner = NULL;
 236   rootNode->next = NULL;
 237 
 238   return rootNode; 
 239 }
 240 
 241 /* ------------------------------------------------- */
 242 
 243 EPNodePtr EP_InitializeNode( const char *inputFile, const int nodeID ) {
     /* [<][>][^][v][top][bottom][index][help] */
 244   EPNodePtr node;
 245 
 246   node = UT_malloc(sizeof(struct EPNode));
 247 
 248   node->nodeID = nodeID;
 249   node->isValidPGPSignature = vS_IS_NOT_PGP;
 250   node->keyID = 0;
 251   node->MIMEContentType = -1;
 252   node->strMIMEContentType = NULL;
 253   node->file = strdup(inputFile);
 254   node->inner = NULL;
 255   node->next = NULL;
 256 
 257   return node; 
 258 }
 259 
 260 /* ------------------------------------------------- */
 261 
 262 EPNodePtr EP_DefineNewNode( const int nodeID,
     /* [<][>][^][v][top][bottom][index][help] */
 263                             const short isValidPGPSignature,
 264                             const t_MM_type MIMEContentType,
 265                             const char *strMIMEContentType,
 266                             const u32 keyID) {
 267   EPNodePtr node;
 268 
 269   node = (EPNodePtr) UT_malloc(sizeof(EP_mail_node));
 270 
 271   /*  printf("node: %d, %p\n", nodeID, node); */
 272 
 273   node->nodeID = nodeID;
 274   node->isValidPGPSignature = isValidPGPSignature;
 275   node->keyID = keyID;
 276   node->MIMEContentType = MIMEContentType;
 277   node->strMIMEContentType = (strMIMEContentType == NULL ? NULL : 
 278                               strdup(strMIMEContentType) );
 279   node->inner = NULL;
 280   node->next = NULL;
 281   EP_BuildFilename(node);
 282 
 283   return node; 
 284 }
 285 
 286 /* ------------------------------------------------- */
 287 /* Deallocate parsing tree and remove files */
 288 
 289 void EP_TreeCleanUp(const EPNodePtr ptr) {
     /* [<][>][^][v][top][bottom][index][help] */
 290 
 291   if (ptr->file != NULL) {
 292     unlink(ptr->file);
 293     /*    printf("node: %d, %p\n", ptr->nodeID, ptr); */
 294     free(ptr->file);
 295   }
 296   if (ptr->strMIMEContentType != NULL) {
 297     free(ptr->strMIMEContentType);
 298   }
 299 
 300   if (ptr->inner != NULL) EP_TreeCleanUp(ptr->inner);
 301   if (ptr->next != NULL) EP_TreeCleanUp(ptr->next);
 302 
 303   free(ptr);
 304 }
 305 
 306 /* ------------------------------------------------- */
 307 void MailHeaderFieldCleanUp(Mail_Header_FieldPtr p) {
     /* [<][>][^][v][top][bottom][index][help] */
 308   Mail_Header_FieldPtr ptmp = p, prev; 
 309 
 310   while (ptmp != NULL) {
 311     prev = ptmp;
 312     ptmp = ptmp->next;
 313     if (prev->field != NULL)
 314       free(prev->field);
 315     free(prev);
 316   }
 317 }
 318 
 319 
 320 /* ------------------------------------------------- */
 321 
 322 /* Deallocate parsing tree and remove files */
 323 
 324 void EP_MailDescrCleanUp(const EP_Mail_DescrPtr ptr) {
     /* [<][>][^][v][top][bottom][index][help] */
 325 
 326   if (ptr != NULL) {
 327 
 328     MailHeaderFieldCleanUp(ptr->from);
 329     MailHeaderFieldCleanUp(ptr->subject);
 330     MailHeaderFieldCleanUp(ptr->date);
 331     MailHeaderFieldCleanUp(ptr->message_id);
 332     MailHeaderFieldCleanUp(ptr->reply_to);
 333     MailHeaderFieldCleanUp(ptr->cc);
 334     MailHeaderFieldCleanUp(ptr->content_type);
 335 
 336     EP_TreeCleanUp(ptr->tree);
 337     free(ptr);
 338   }
 339 }
 340 
 341 /* ------------------------------------------------- */
 342 /* Build a node filename */
 343 
 344 void EP_BuildFilename(const EPNodePtr ptr) {
     /* [<][>][^][v][top][bottom][index][help] */
 345   char file[FILENAME_LENGTH];
 346 
 347   sprintf(file, "%s%d", EP_outputPrefix, ptr->nodeID);
 348   ptr->file = strdup(file);
 349 }
 350 
 351 /* ------------------------------------------------- */
 352 
 353 void EP_ShowTree(const EPNodePtr p) {
     /* [<][>][^][v][top][bottom][index][help] */
 354   if (p != NULL) {
 355     /* if (EP_HasContent(p)) { */
 356       printf("Node ID: %d\n", p->nodeID);
 357       printf("isValidPGPSignature: %s\n",  vS_strRC[p->isValidPGPSignature]);  
 358       printf("MIMEContentType: %d\n", p->MIMEContentType);
 359       printf("Key ID: %0X\n", p->keyID);
 360       printf("file: %s\n\n\n", p->file);
 361       /* } */
 362     if (p->inner != NULL)
 363       EP_ShowTree(p->inner);
 364     if (p->next != NULL)
 365       EP_ShowTree(p->next);
 366   }
 367 }
 368 
 369 /* ------------------------------------------------- */
 370 
 371 EPTokenPtr EP_DefineNewToken( const t_MM_type MIMEContentType,
     /* [<][>][^][v][top][bottom][index][help] */
 372                               const char *file,
 373                               const EPTokenKeysPtr keysList ) {
 374   EPTokenPtr token;
 375   EPTokenKeysPtr head = NULL, p = keysList, pnew, prev = NULL;
 376   
 377   token = (EPTokenPtr) UT_malloc(sizeof(EPToken));
 378   token->file = (char*)file;
 379   token->MIMEContentType = MIMEContentType;
 380 
 381 
 382   /* generate head, and build the key list for this result node */
 383   if (p != NULL) {
 384     pnew = (EPTokenKeysPtr) UT_malloc(sizeof(EPTokenKeys));
 385     pnew->isValidPGPSignature = p->isValidPGPSignature;
 386     pnew->keyID = p->keyID;
 387     pnew->next = NULL;
 388     head = prev = pnew;
 389     p = p->next;
 390   }
 391 
 392   while (p != NULL) {
 393     pnew = (EPTokenKeysPtr) UT_malloc(sizeof(EPTokenKeys));
 394     pnew->isValidPGPSignature = p->isValidPGPSignature;
 395     pnew->keyID = p->keyID;
 396     pnew->next = NULL;
 397     prev->next = pnew;
 398     prev = pnew;
 399     p = p->next;
 400   }
 401 
 402   token->keys = head;
 403   token->next = token->prev = NULL;
 404 
 405   return token;   
 406 }
 407 
 408 /* ------------------------------------------------- */
 409 
 410 EPTokenKeysPtr AddKeyInfo( EPTokenKeysPtr keysList, const EPNodePtr p ){
     /* [<][>][^][v][top][bottom][index][help] */
 411   EPTokenKeysPtr ptk;
 412 
 413   ptk = (EPTokenKeysPtr) UT_malloc(sizeof(EPTokenKeys));
 414   ptk->isValidPGPSignature = p->isValidPGPSignature;
 415   ptk->keyID = p->keyID;
 416   ptk->next = NULL;
 417   if (keysList == NULL)
 418     return ptk;
 419   else {
 420     ptk->next = keysList;
 421     return ptk;
 422   }
 423 }
 424 
 425 /* ------------------------------------------------- */
 426 
 427 EPTokenKeysPtr RemoveKeyInfo( const EPTokenKeysPtr keysHead ) {
     /* [<][>][^][v][top][bottom][index][help] */
 428   EPTokenKeysPtr tmp = keysHead->next;
 429 
 430   free(keysHead);
 431   return tmp;
 432 }
 433 
 434 /* ------------------------------------------------- */
 435 
 436 /*
 437  ep_GetPasswords: collects all passwords in the current mail chunk
 438  */
 439 GSList* ep_GetPasswords(char *file) {
     /* [<][>][^][v][top][bottom][index][help] */
 440   FILE *input_file;
 441   gchar line[1024];
 442   GSList *password_list = NULL;
 443   
 444   if ((input_file = fopen(file, "r")) == NULL) {
 445     ER_perror(FAC_UP, UP_CANTOPEN, "Couldn't open the file %s\n", file);
 446     exit(1);  
 447   }
 448   
 449   while (fgets(line, 1024, input_file) != NULL) {
 450     if (strncasecmp(line, "password:", 9) == 0 &&
 451         strlen(line) > 9) { // 9 = strlen 'password:'
 452       //printf("pwd add %s\n", g_strstrip(strdup(line + 9)));
 453       password_list = g_slist_append(password_list, 
 454                                     g_strstrip(strdup(line + 9)));
 455     }
 456   }
 457   
 458   fclose (input_file);
 459   return password_list;
 460 }
 461 
 462 /* ------------------------------------------------- */
 463 
 464 /*
 465 
 466   Password transporting works as follows:
 467   Current node and siblings receive passwords from parent.
 468   Child nodes of the current one receive the ones that the
 469     current received plus the ones specified on the current.
 470  */
 471 EPTokenPtr EP_GetTokens(const EPNodePtr p, const EPTokenPtr head, 
     /* [<][>][^][v][top][bottom][index][help] */
 472                         EPTokenKeysPtr keysList, GSList *passwords) {
 473   EPTokenPtr pt, ptmp = head;
 474   EPTokenKeysPtr kl = keysList;
 475   GSList *node_passwords = NULL;
 476 
 477   if (p != NULL) {
 478     if (p->isValidPGPSignature != vS_IS_NOT_PGP ) {
 479       kl = AddKeyInfo(kl, p);
 480     }
 481     if (EP_HasContent(p)) {
 482       pt = EP_DefineNewToken(p->MIMEContentType, p->file, kl);
 483       pt->passwords = passwords;
 484       if (ptmp != NULL) {
 485         pt->next = ptmp;
 486         ptmp->prev = pt;
 487         ptmp = pt;
 488       } else 
 489         ptmp = pt;
 490     }
 491     else {
 492       if (p->MIMEContentType<3) { //UGLY
 493         node_passwords = ep_GetPasswords(p->file);
 494         node_passwords = g_slist_concat(node_passwords, passwords);
 495       }
 496 
 497       ptmp = EP_GetTokens(p->inner, ptmp, kl, node_passwords);
 498     }
 499 
 500     if (p->isValidPGPSignature != vS_IS_NOT_PGP ) {
 501       kl = RemoveKeyInfo(kl);
 502     }
 503 
 504     ptmp = EP_GetTokens(p->next, ptmp, kl, passwords);
 505   }
 506   return ptmp;
 507 }
 508 
 509 /* ------------------------------------------------- */
 510 void EP_PrintTokens(EPTokenPtr head) {
     /* [<][>][^][v][top][bottom][index][help] */
 511   EPTokenPtr p = head;
 512   EPTokenKeysPtr ptk;
 513 
 514   while (p != NULL) {
 515     printf("Token: %s, MIMEtype: %d\n", p->file, p->MIMEContentType);
 516     ptk = p->keys;
 517     while (ptk != NULL) {
 518       printf("     key: %0X, isValid: %s\n", 
 519              ptk->keyID, vS_strRC[ptk->isValidPGPSignature]);
 520       ptk = ptk->next;
 521     }
 522     p = p->next;
 523   }
 524 }
 525 
 526 /* ------------------------------------------------- */
 527 
 528 
 529 void EP_CleanTokens(const EPTokenPtr head) {
     /* [<][>][^][v][top][bottom][index][help] */
 530   EPTokenPtr prevp, p = head;
 531   EPTokenKeysPtr ptk, prevptk;
 532 
 533   while (p != NULL) {
 534     ptk = p->keys;
 535     while (ptk != NULL) {
 536       prevptk = ptk;
 537       ptk = ptk->next;
 538       free(prevptk);
 539     }
 540     prevp = p;
 541     p = p->next;
 542     free(prevp);
 543   }
 544 }
 545 
 546 

/* [<][>][^][v][top][bottom][index][help] */