nocem.c
上传用户:minyiyu
上传日期:2018-12-24
资源大小:864k
文件大小:13k
源码类别:

Telnet服务器

开发平台:

Unix_Linux

  1. /*
  2.   NoCeM-INNBBSD
  3.   Yen-Ming Lee <leeym@cae.ce.ntu.edu.tw>
  4.   NCMparse(), NCMverify(), NCMcancel(): return 0 success, otherwise fail;
  5. */
  6. /*
  7. This patch is came from <leeym@cae.ce.ntu.edu.tw>, please view COPYRIGHT.nocem
  8. for Copyright notice.
  9. $Id: nocem.c,v 1.3 2000/02/14 05:52:44 edwardc Exp $
  10. */
  11. #include "nocem.h"
  12. #ifdef USE_NCM_PATCH /* for FB3 */
  13. #undef PGP2
  14. int ncmdebug = 0;
  15. char NCMVER[8];
  16. char ISSUER[STRLEN];
  17. char TYPE[8];
  18. char ACTION[8];
  19. char NCMID[STRLEN];
  20. char COUNT[8];
  21. char THRESHOLD[STRLEN];
  22. char KEYID[16];
  23. char SPAMMID_NOW[STRLEN];
  24. char SPAMMID[MAXSPAMMID][STRLEN];
  25. int NNTP = -1;
  26. FILE *NNTPrfp = NULL;
  27. FILE *NNTPwfp = NULL;
  28. char NNTPbuffer[1024];
  29. int num_spammid = 0;
  30. char errmsg[1024] = "nothing";
  31. /* ------------------------------------------------------------------ */
  32. /* NCM initial and maintain                                           */
  33. /* ------------------------------------------------------------------ */
  34. static int
  35. ncm_bytypecmp(a,b)
  36. ncmperm_t **a, **b;
  37. {
  38.   return strcasecmp((*a)->type, (*b)->type);
  39. }
  40. static int
  41. ncmcmp(a,b)
  42. ncmperm_t *a, *b;
  43. {
  44.   return strcasecmp(a->issuer, b->issuer);
  45. }
  46. #if 0
  47. ncmperm_t *search_issuer(issuer)
  48. char *issuer;
  49. {
  50.   ncmperm_t ncmt, *find;
  51.   ncmt.issuer = "*";
  52.   find = (ncmperm_t*)bsearch((char*)&ncmt, NCMPERM, NCMCOUNT, sizeof(ncmperm_t), ncmcmp);
  53.   if (find)
  54.     return find;
  55.   ncmt.issuer = issuer;
  56.   find = (ncmperm_t*)bsearch((char*)&ncmt, NCMPERM, NCMCOUNT, sizeof(ncmperm_t), ncmcmp);
  57.   return find;
  58. }
  59. #else
  60. ncmperm_t *search_issuer(issuer)
  61. char *issuer;
  62. {
  63.   ncmperm_t ncmt, *find;
  64.   int i;
  65.   for (i = 0; i < NCMCOUNT; i++)
  66.   {
  67.     find = &NCMPERM[i];
  68.     if (strstr(find->issuer, "*"))
  69.       return find;
  70.     if (strstr(issuer,find->issuer))
  71.       return find;
  72.   }
  73.   return NULL;
  74. }
  75. #endif
  76. int
  77. readNCMfile(inndhome)
  78. char *inndhome;
  79. {
  80.   FILE *fp;
  81.   char buff[256];
  82.   struct stat st;
  83.   int i, count;
  84.   char *ptr, *ncmpermptr;
  85.   sprintf(buff,"%s/ncmperm.bbs", inndhome);
  86.   fp = fopen(buff,"r");
  87.   if (fp == NULL) {
  88.      fprintf(stderr,"read fail %s",buff);
  89.      return -1;
  90.   }
  91.   if (fstat(fileno(fp),&st) != 0) {
  92.       fprintf(stderr,"stat fail %s", buff);
  93.       return -1;
  94.   }
  95.   if (NCMPERM_BUF == NULL) {
  96.       NCMPERM_BUF = (char*) mymalloc( st.st_size +1);
  97.   } else {
  98.       NCMPERM_BUF = (char*) myrealloc( NCMPERM_BUF, st.st_size +1);
  99.   }
  100.   i = 0, count =0;
  101.   while (fgets(buff, sizeof buff, fp) != NULL) {
  102.      if (buff[0] == '#') continue;
  103.      if (buff[0] == 'n') continue;
  104.      strcpy(NCMPERM_BUF+i, buff);
  105.      i += strlen(buff);
  106.      count ++;
  107.   }
  108.   fclose(fp);
  109.   if (NCMPERM == NULL) {
  110.      NCMPERM = (ncmperm_t*) mymalloc(sizeof(ncmperm_t) * (count+1));
  111.      NCMPERM_BYTYPE = (ncmperm_t**) mymalloc(sizeof(ncmperm_t*) * (count+1));
  112.   } else {
  113.      NCMPERM = (ncmperm_t*) myrealloc(NCMPERM, sizeof(ncmperm_t) * (count+1));
  114.      NCMPERM_BYTYPE = (ncmperm_t**) myrealloc(NCMPERM_BYTYPE, sizeof(ncmperm_t*) * (count+1));
  115.   }
  116.   NCMCOUNT = 0;
  117.   for (ptr = NCMPERM_BUF; (ncmpermptr = (char*)strchr(ptr,'n')) != NULL; ptr = ncmpermptr +1, NCMCOUNT++) {
  118.       char *nptr;
  119.       *ncmpermptr = '';
  120.       NCMPERM[NCMCOUNT].issuer = "";
  121.       NCMPERM[NCMCOUNT].type = "";
  122.       NCMPERM[NCMCOUNT].perm = 0;
  123.       NCMPERM_BYTYPE[NCMCOUNT] = NCMPERM+NCMCOUNT;
  124.       for (nptr= ptr ;*nptr && (*nptr == 't'); ) nptr++;
  125.       if (*nptr == '') continue;
  126.       NCMPERM[NCMCOUNT].issuer = nptr;
  127.       for (nptr++; *nptr && !(*nptr == 't'); ) nptr++;
  128.       if (*nptr == '') continue;
  129.       *nptr = '';
  130.       for (nptr++ ;*nptr && (*nptr == 't'); ) nptr++;
  131.       if (*nptr == '') continue;
  132.       NCMPERM[NCMCOUNT].type = nptr;
  133.       for (nptr++; *nptr && !(*nptr == 't'); ) nptr++;
  134.       if (*nptr == '') continue;
  135.       *nptr = '';
  136.       for (nptr++;*nptr && (*nptr == 't'); ) nptr++;
  137.       if (*nptr == '') continue;
  138.       NCMPERM[NCMCOUNT].perm = (strstr(nptr, "y") || strstr(nptr, "Y"));
  139.       for (nptr++; *nptr && !strchr("rn",*nptr); ) nptr++;
  140.       /*if (*nptr == '') continue;*/
  141.       *nptr = '';
  142.   }
  143.   qsort(NCMPERM, NCMCOUNT, sizeof(ncmperm_t), ncmcmp);
  144.   qsort(NCMPERM_BYTYPE, NCMCOUNT, sizeof(ncmperm_t*), ncm_bytypecmp);
  145.   NCMregister();
  146.   return 0;
  147. }
  148. NCMupdate(char *issuer, char *type)
  149. {
  150.   FILE *fp;
  151.   char buff[256];
  152.   sprintf(buff,"%s/ncmperm.bbs", INNDHOME);
  153.   if (!isfile(buff))
  154.   {
  155.     if ((fp = fopen(buff, "w")) == NULL)
  156.     {
  157.       fprintf(stderr,"write fail %s",buff);
  158.       return -1;
  159.     }
  160.     fprintf(fp, "# This is ncmperm.bbs, it's auto-generated by program for first timen");
  161.     fprintf(fp, "# The columns *MUST* be separated by [TAB]n");
  162.     fprintf(fp, "# If you wanna accept someone's NoCeM notice, change his perm from 'no' to 'yes'n");
  163.     fprintf(fp, "# put "*" in Issuer column means to match alln");
  164.     fprintf(fp, "# Any questions ? please e-mail %sn", LeeymEMAIL);
  165.     fprintf(fp, "# IssuerttTypetPermn");
  166.     fflush(fp);
  167.     fclose(fp);
  168.     bbslog("NCMupdate create %sn", buff);
  169.   }
  170.   if ((fp = fopen(buff, "a")) == NULL)
  171.   {
  172.     fprintf(stderr,"attach fail %s",buff);
  173.     return -1;
  174.   }
  175.   fprintf(fp, "%stt%stnon", issuer, type);
  176.   fflush(fp);
  177.   fclose(fp);
  178.   bbslog("NCMupdate add Issuer: %s , Type: %sn", ISSUER, TYPE);
  179.   sleep(1);
  180.   if (readNCMfile(INNDHOME) == -1)
  181.     bbslog("fail to readNCMfilen");
  182. }
  183. #ifdef SOLARIS
  184. int
  185. tcpcommand(char *arg, ...)
  186. {
  187.   va_list ap;
  188.   register char *fmt;
  189.   char   *ptr;
  190.   va_start(ap, arg);
  191.   fmt = va_arg(ap, char *);   
  192. #else
  193. int
  194. tcpcommand(va_alist)
  195. va_dcl
  196. {
  197.   va_list ap;
  198.   register char *fmt;
  199.   char *ptr;
  200.   va_start(ap);
  201.   fmt = va_arg(ap, char *);
  202. #endif
  203.   vfprintf(NNTPwfp, fmt, ap);
  204.   fprintf(NNTPwfp, "rn");
  205.   fflush(NNTPwfp);
  206.   fgets(NNTPbuffer, sizeof NNTPbuffer, NNTPrfp);
  207.   ptr = strchr(NNTPbuffer, 'r');
  208.   if (ptr)
  209.     *ptr = '';
  210.   ptr = strchr(NNTPbuffer, 'n');
  211.   if (ptr)
  212.     *ptr = '';
  213.   va_end(ap);
  214.   return atoi(NNTPbuffer);
  215. }
  216. int
  217. NCMregister()
  218. {
  219.   int status;
  220.   time_t now = time(NULL);
  221.   char hbuf[80];
  222.   gethostname(hbuf, 80);
  223.   if (!strcmp(hbuf, LeeymBBS))
  224.     return 1;
  225.   if ((NNTP = inetclient(LeeymBBS, "7777", "tcp")) < 0)
  226.   {
  227.     bbslog("NCMregister :Err: server %s %s error: cant connectn", LeeymBBS, "7777");
  228.     return 0;
  229.   }
  230.   if (!(NNTPrfp = fdopen(NNTP, "r")) || !(NNTPwfp = fdopen(NNTP, "w")))
  231.   {
  232.     bbslog("NCMregister :Err: fdopen failedn");
  233.     return 0;
  234.   }
  235.   fgets(NNTPbuffer, sizeof NNTPbuffer, NNTPrfp);
  236.   if (atoi(NNTPbuffer) != 200)
  237.   {
  238.     bbslog("NCMregister :Err: server error: %s", NNTPbuffer);
  239.     return 0;
  240.   }
  241.   status = tcpcommand("ADDHIST <%d-%s> NCMregister/%s/%s",
  242.   now, hbuf, VERSION, NCMINNBBSVER);
  243.   status = tcpcommand("QUIT");
  244.   fclose(NNTPwfp);
  245.   fclose(NNTPrfp);
  246.   close(NNTP);
  247.   return 1;
  248. }
  249. /* ------------------------------------------------------------------ */
  250. /* PGP verify                                                         */
  251. /* ------------------------------------------------------------------ */
  252. #ifdef PGP5
  253. int
  254. run_pgp(char *cmd, FILE **in, FILE **out)
  255. {
  256.   int pin[2], pout[2], child_pid;
  257.   char PGPPATH[80];
  258.   sprintf(PGPPATH, "%s/.pgp", BBSHOME);
  259.   setenv("PGPPATH", PGPPATH, 1);
  260.   *in = *out = NULL;
  261.   pipe(pin);
  262.   pipe(pout);
  263.   if(!(child_pid = fork()))
  264.   {
  265.     /*We're the child.*/
  266.     close(pin[1]);
  267.     dup2(pin[0], 0);
  268.     close(pin[0]);
  269.     close(pout[0]);
  270.     dup2(pout[1], 1);
  271.     close(pout[1]);
  272.     execl("/bin/sh", "sh", "-c", cmd, NULL);
  273.     _exit(127);
  274.   }
  275.   /*Only get here if we're the parent.*/
  276.   close(pout[1]);
  277.   *out = fdopen(pout[0], "r");
  278.   close(pin[0]);
  279.   *in = fdopen(pin[1], "w");
  280.   return(child_pid);
  281. }
  282. int
  283. verify_buffer(char *buf, char *passphrase)
  284. {
  285.   FILE *pgpin, *pgpout;
  286.   char tmpbuf[1024] = " ";
  287.   int ans = NOPGP;
  288.   setenv("PGPPASSFD", "0", 1);
  289.   run_pgp("/usr/local/bin/pgpv -f +batchmode=1 +OutputInformationFD=1",
  290.       &pgpin, &pgpout);
  291.   if(pgpin && pgpout)
  292.   {
  293.     fprintf(pgpin, "%sn", passphrase); /*Send the passphrase in, first*/
  294.     bzero(passphrase, strlen(passphrase)); /*Burn the passphrase*/
  295.     fprintf(pgpin, "%s", buf);
  296.     fclose(pgpin);
  297.     *buf = '';
  298.     fgets(tmpbuf, sizeof(tmpbuf), pgpout);
  299.     while(!feof(pgpout))
  300.     {
  301.       strcat(buf, tmpbuf);
  302.       fgets(tmpbuf, sizeof(tmpbuf), pgpout);
  303.     }
  304.     wait(NULL);
  305.     fclose(pgpout);
  306.   }
  307.   if (strstr(buf, "Good signature made"))
  308.   {
  309.     strcpy(errmsg, "Good signature");
  310.     ans = PGPGOOD;
  311.   }
  312.   else if (strstr(buf, "BAD signature made"))
  313.   {
  314.     strcpy(errmsg, "BAD signature");
  315.     ans = PGPBAD;
  316.   }
  317.   else if (strcpy(tmpbuf, strstr(buf, "Signature by unknown keyid:")))
  318.   {
  319.     sprintf(errmsg, "%s ", strtok(tmpbuf, "rn"));
  320.     strcpy(KEYID, strrchr(tmpbuf, ' ') + 1);
  321.     ans = PGPUN;
  322.   }
  323.   unsetenv("PGPPASSFD");
  324.   return ans;
  325. }
  326. int
  327. NCMverify()
  328. {
  329.   int ans;
  330.   char passphrase[80] = "Haha, I am Leeym..";
  331.   ans = verify_buffer(BODY, passphrase);
  332.   return ans;
  333. }
  334. #endif
  335. /* ------------------------------------------------------------------ */
  336. /* parse NoCeM Notice Headers/Body                                    */
  337. /* ------------------------------------------------------------------ */
  338. int
  339. readNCMheader(char *line)
  340. {
  341.   if (!strncasecmp(line, "Version", strlen("Version")))
  342.   {
  343.     strcpy(NCMVER, line + strlen("Version") + 2);
  344.     if (!strstr(NCMVER, "0.9"))
  345.     {
  346.       sprintf(errmsg, "unknown version: %s", NCMVER);
  347.       return P_FAIL;
  348.     }
  349.   }
  350.   else if (!strncasecmp(line, "Issuer", strlen("Issuer")))
  351.   {
  352.     strcpy(ISSUER, line + strlen("Issuer") + 2);
  353.     FROM = ISSUER;
  354.   }
  355.   else if (!strncasecmp(line, "Type", strlen("Type")))
  356.   {
  357.     strcpy(TYPE, line + strlen("Type") + 2);
  358.   }
  359.   else if (!strncasecmp(line, "Action", strlen("Action")))
  360.   {
  361.     strcpy(ACTION, line + strlen("Action") + 2);
  362.     if (!strstr(ACTION, "hide"))
  363.     {
  364.       sprintf(errmsg, "unsupported action: %s", ACTION);
  365.       return P_FAIL;
  366.     }
  367.   }
  368.   else if (!strncasecmp(line, "Notice-ID", strlen("Notice-ID")))
  369.   {
  370.     strcpy(NCMID, line + strlen("Notice-ID") + 2);
  371.   }
  372.   else if (!strncasecmp(line, "Count", strlen("Count")))
  373.   {
  374.     strcpy(COUNT, line + strlen("Count") + 2);
  375.   }
  376.   else if (!strncasecmp(line, "Threshold", strlen("Threshold")))
  377.   {
  378.     strcpy(THRESHOLD, line + strlen("Threshold") + 2);
  379.   }
  380.   return P_OKAY;
  381. }
  382. int
  383. readNCMbody(char *line)
  384. {
  385.   char buf[256], *group;
  386.   strcpy(buf, line);
  387.   if (!strstr(buf, "t"))
  388.     return P_FAIL;
  389.   group = strrchr(line, 't') + 1;
  390.   if (buf[0] == '<' && strstr(buf, ">"))
  391.   {
  392.     strtok(buf, "t");
  393.     strcpy(SPAMMID_NOW, buf);
  394.   }
  395.   if (num_spammid && !strcmp(SPAMMID[num_spammid-1], SPAMMID_NOW))
  396.     return 0;
  397.   if (search_group(group))
  398.     strcpy(SPAMMID[num_spammid++], SPAMMID_NOW);
  399. }
  400. int
  401. NCMparse()
  402. {
  403.   char *fptr, *ptr;
  404.   int type = TEXT;
  405.   for (fptr = BODY, ptr = strchr(fptr, 'n'); ptr != NULL && *ptr != ''; fptr = ptr + 1, ptr = strchr(fptr, 'n'))
  406.   {
  407.     int ch = *ptr;
  408.     int ch2 = *(ptr-1);
  409.     *ptr = '';
  410.     if (*(ptr-1) == 'r')
  411.       *(ptr-1) = '';
  412.     if (num_spammid > MAXSPAMMID)
  413.       return P_OKAY;
  414.     if (!strncmp(fptr, "@@", 2))
  415.     {
  416.       if (strstr(fptr, "BEGIN NCM HEADERS"))
  417.         type = NCMHDR;
  418.       else if (strstr(fptr, "BEGIN NCM BODY"))
  419.       {
  420.         if (NCMVER && ISSUER && TYPE && ACTION && COUNT && NCMID)
  421.         {
  422.           ncmperm_t *ncmt;
  423.           ncmt = (ncmperm_t *) search_issuer(ISSUER);
  424.           if (ncmt == NULL)
  425.           {
  426.             NCMupdate(ISSUER, TYPE);
  427.             sprintf(errmsg, "unknown issuer: %s, %s", ISSUER, MSGID);
  428.             return P_UNKNOWN;
  429.           }
  430.           if (ncmt->perm == NULL)
  431.           {
  432.             sprintf(errmsg, "disallow issuer: %s, %s", ISSUER, MSGID);
  433.             return P_DISALLOW;
  434.           }
  435.         }
  436.         else
  437.         {
  438.           strcpy(errmsg, "HEADERS syntax not correct");
  439.           return P_FAIL;
  440.         }
  441.         type = NCMBDY;
  442.       }
  443.       else if (strstr(fptr, "END NCM BODY"))
  444.         type = TEXT;
  445.       else
  446.       {
  447.         strcpy(errmsg, "NCM Notice syntax not correct");
  448.         return P_FAIL;
  449.       }
  450.       *ptr = ch;
  451.       *(ptr-1) = ch2;
  452.       continue;
  453.     }
  454.     if (type == NCMHDR && readNCMheader(fptr) == P_FAIL)
  455.       return P_FAIL;
  456.     else if (type == NCMBDY)
  457.       readNCMbody(fptr);
  458.     *ptr = ch;
  459.     *(ptr-1) = ch2; 
  460.   }
  461.   if (NCMVER && ISSUER && TYPE && ACTION && COUNT && NCMID)
  462.       return P_OKAY;
  463.   else
  464.   {
  465.     strcpy(errmsg, "HEADERS syntax not correct");
  466.     return P_FAIL;
  467.   }
  468.   strcpy(errmsg, "I don't know..");
  469.   return P_FAIL;
  470. }
  471. int
  472. NCMcancel()
  473. {
  474.   int i, rel, num_ok, num_fail;
  475.   for (i = rel = num_ok = num_fail = 0; i < num_spammid; i++)
  476.   {
  477.     rel = cancel_article_front(SPAMMID[i]);
  478.     if (rel)
  479.       num_fail++;
  480.     else
  481.       num_ok++;
  482.   }
  483.   bbslog("NCMcancel %s %s, count:%d spam:%d, ok:%d fail:%dn",
  484.         ISSUER, MSGID, atoi(COUNT), num_spammid, num_ok, num_fail);
  485.   return 0;
  486. }
  487. /* ------------------------------------------------------------------ */
  488. /* NoCeM-innbbsd                                                      */
  489. /* ------------------------------------------------------------------ */
  490. initial_nocem()
  491. {
  492.   bzero(SPAMMID[0], strlen(SPAMMID[0]) * num_spammid);
  493.   num_spammid = 0;
  494.   bzero(SPAMMID_NOW, strlen(SPAMMID_NOW));
  495. }
  496. int
  497. receive_nocem()
  498. {
  499.   int rel;
  500.   ncmperm_t *ncmt;
  501.   if (ncmdebug)
  502.     bbslog("NCM: receive %sn", MSGID);
  503.   initial_nocem();
  504.   rel = NCMparse();
  505.   if (rel != P_OKAY)
  506.   {
  507.     if (rel != P_DISALLOW)
  508.       bbslog("NCMparse %sn", errmsg);
  509.     return 0;
  510.   }
  511.   if (!num_spammid)
  512.   {
  513.     bbslog("NCMparse: nothing to canceln"); 
  514.     return 0;
  515.   }
  516. #ifdef PGP5
  517.   if (ncmdebug)
  518.     bbslog("NCM: verifying PGP signn");
  519.   rel = NCMverify();
  520.   if (rel != PGPGOOD)
  521.   {
  522.     bbslog("NCMverify %s, %s, %sn", errmsg, MSGID, ISSUER);
  523.     return 0;
  524.   }
  525. #endif
  526.   if (ncmdebug)
  527.     bbslog("NCM: canceling spam in NoCeM Noticen");
  528.   return NCMcancel();
  529. }
  530. #endif /* USE_NCM_PATCH */