~ubuntu-branches/ubuntu/hoary/courier/hoary

« back to all changes in this revision

Viewing changes to courier/submit.C

  • Committer: Bazaar Package Importer
  • Author(s): Thom May
  • Date: 2004-11-29 12:09:34 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20041129120934-kkn0xj11j0n1n6lo
Tags: 0.47-3ubuntu1
* Nathaniel McCallum
 - debian/*.init: pretty initscripts
 - debian/control: version depends on lsb-base

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#include        "rfc2045/rfc2045charset.h"
13
13
#include        "rfc1035/rfc1035.h"
14
14
#include        "rfc1035/rfc1035mxlist.h"
 
15
#include        "rfc1035/spf.h"
15
16
#include        "numlib/numlib.h"
16
17
#include        "dbobj.h"
17
18
#include        "afx.h"
22
23
#include        <string.h>
23
24
#include        <stdlib.h>
24
25
#include        <ctype.h>
 
26
#include        <errno.h>
25
27
#include        <iostream>
26
28
#if     HAVE_LOCALE_H
27
29
#include        <locale.h>
39
41
 
40
42
#define TIMEOUT 1800
41
43
 
42
 
static const char rcsid[]="$Id: submit.C,v 1.40 2004/06/06 16:04:34 mrsam Exp $";
 
44
static const char rcsid[]="$Id: submit.C,v 1.46 2004/09/03 01:48:28 mrsam Exp $";
43
45
 
44
46
time_t  submit_time;
45
47
static const char *expnname=0;
362
364
        char    dsnformat;
363
365
        struct  rw_transport *module;
364
366
        int     flag;
 
367
        CString         helohost;
 
368
        CString         *receivedspfhelo;
 
369
        CString         *receivedspfmailfrom;
 
370
        int     mailfrom_passed_spf;
365
371
        } ;
366
372
 
367
373
static void mailfromerr(int msgnum, const char *errtext, struct rw_info *rwi)
461
467
        return (-1);
462
468
}
463
469
 
 
470
static const char *my_spf_lookup(const char *checkname,
 
471
                                 const char *mailfrom,
 
472
                                 const char *tcpremoteip,
 
473
                                 const char *helodomain,
 
474
                                 CString *hdrOut,
 
475
                                 char *errmsg_buf,
 
476
                                 size_t errmsg_buf_size)
 
477
{
 
478
        static const char * const keys[]={
 
479
                "sender",
 
480
                "remoteip",
 
481
                "remotehost",
 
482
                "helo",
 
483
                "receiver"};
 
484
        const char *values[5];
 
485
        char *q;
 
486
        char result=rfc1035_spf_lookup((values[0]=mailfrom),
 
487
                                       (values[1]=tcpremoteip),
 
488
                                       (values[2]=getenv("TCPREMOTEHOST")),
 
489
                                       (values[3]=helodomain),
 
490
                                       (values[4]=config_esmtphelo()),
 
491
                                       errmsg_buf,
 
492
                                       errmsg_buf_size);
 
493
 
 
494
 
 
495
        const char *str;
 
496
        size_t i;
 
497
 
 
498
        switch (result) {
 
499
        case SPF_NONE:
 
500
                str="none";
 
501
                break;
 
502
        case SPF_NEUTRAL:
 
503
                str="neutral";
 
504
                break;
 
505
        case SPF_PASS:
 
506
                str="pass";
 
507
                break;
 
508
        case SPF_FAIL:
 
509
                str="fail";
 
510
                break;
 
511
        case SPF_SOFTFAIL:
 
512
                str="softfail";
 
513
                break;
 
514
        case SPF_ERROR:
 
515
                str="error";
 
516
                break;
 
517
        default:
 
518
                str="unknown";
 
519
        }
 
520
 
 
521
        (*hdrOut)="Received-SPF: ";
 
522
 
 
523
        for (q=errmsg_buf; *q; q++)
 
524
                if (*q < ' ' || *q >= 127)
 
525
                        *q='?';
 
526
 
 
527
        (*hdrOut) += str;
 
528
        (*hdrOut) += " (";
 
529
        (*hdrOut) += errmsg_buf;
 
530
        (*hdrOut) += ")\n  SPF=";
 
531
        (*hdrOut) += checkname;
 
532
        (*hdrOut) += ";\n";
 
533
 
 
534
        for (i=0; i<sizeof(values)/sizeof(values[0]); i++)
 
535
        {
 
536
                char *v=strdup(values[i] ? values[i]:"");
 
537
 
 
538
                for (q=v; q && *q; q++)
 
539
                        if (*q < ' ' || *q >= 127)
 
540
                                *q='?';
 
541
                        else if (*q == ';')
 
542
                                *q=' ';
 
543
                (*hdrOut) += "  ";
 
544
                (*hdrOut) += keys[i];
 
545
                (*hdrOut) += "=";
 
546
                (*hdrOut) += v ? v:strerror(errno);
 
547
                (*hdrOut) += ";\n";
 
548
        }
 
549
        return str;
 
550
}
 
551
 
 
552
static CString get_spf_errmsg(const char *bofh_var,
 
553
                              const char *result,
 
554
                              const char *errmsg_txt,
 
555
                              const char *what)
 
556
{
 
557
        CString errmsg;
 
558
 
 
559
        if (!bofh_checkspf_status(bofh_var, "off", result))
 
560
        {
 
561
                const char *p=getenv("BOFHSPFNOVERBOSE");
 
562
 
 
563
                errmsg += bofh_checkspf("BOFHSPFHARDERROR",
 
564
                                        "fail,softfail", result)
 
565
                        ? "517":"417";
 
566
                errmsg += " SPF ";
 
567
                errmsg += result;
 
568
                errmsg += " ";
 
569
                errmsg += what;
 
570
                errmsg += ": ";
 
571
 
 
572
                if (p && atoi(p))
 
573
                        errmsg += "Rejected by the Sender Policy Framework.";
 
574
                else errmsg += errmsg_txt;
 
575
        }
 
576
        return errmsg;
 
577
}
 
578
 
464
579
static int getsender(struct rw_transport *module)
465
580
{
466
581
struct  mailfrominfo frominfo;
468
583
CString sender;
469
584
CString envid;
470
585
AliasSearch     asearch;
 
586
CString receivedspfhelo;
 
587
CString receivedspfmailfrom;
471
588
 
472
589
        frominfo.asptr= &asearch;
473
590
        frominfo.flag=1;
474
591
        frominfo.module=module;
475
592
        frominfo.dsnformat=0;
476
593
        frominfo.envid=0;
 
594
        frominfo.receivedspfhelo=NULL;
 
595
        frominfo.receivedspfmailfrom=NULL;
 
596
        frominfo.mailfrom_passed_spf=0;
477
597
 
478
598
        if (buf << cin) return (1);
479
599
 
503
623
                setmsgopts(frominfo, q);
504
624
 
505
625
        const char *tcpremoteip=getenv("TCPREMOTEIP");
 
626
        int bofhcheckhelo=(q=getenv("BOFHCHECKHELO")) == NULL ? 0:atoi(q);
506
627
 
507
 
        if ((q=getenv("BOFHCHECKHELO")) != 0 && atoi(q) &&
508
 
            strcmp(module->name, "esmtp") == 0 && receivedfrommta &&
509
 
            strncmp(receivedfrommta, "dns; ", 5) == 0 && tcpremoteip &&
510
 
            getenv("RELAYCLIENT") == NULL)
 
628
        if (strcmp(module->name, "esmtp") == 0 && receivedfrommta &&
 
629
            strncmp(receivedfrommta, "dns; ", 5) == 0 && tcpremoteip)
511
630
        {
512
631
                const char *s=receivedfrommta+5;
513
632
 
518
637
 
519
638
                memcpy(sbuf, receivedfrommta+5, s-receivedfrommta-5);
520
639
                sbuf[s-receivedfrommta-5]=0;
521
 
 
 
640
                frominfo.helohost=sbuf;
 
641
 
 
642
                q=getenv("BOFHSPFTRUSTME");
 
643
 
 
644
                if (q && atoi(q) && getenv("RELAYCLIENT"))
 
645
                {
 
646
                        putenv("BOFHSPFHELO=off");
 
647
                        putenv("BOFHSPFMAILFROM=off");
 
648
                        putenv("BOFHSPFFROM=off");
 
649
                }
 
650
        }
 
651
        else
 
652
        {
 
653
                bofhcheckhelo=0;
 
654
                putenv("BOFHSPFHELO=off");
 
655
                putenv("BOFHSPFMAILFROM=off");
 
656
                putenv("BOFHSPFFROM=off");
 
657
        }
 
658
 
 
659
        if (tcpremoteip && frominfo.helohost.GetLength())
 
660
        {
 
661
                const char *result;
 
662
                char errmsg[256];
 
663
 
 
664
                if (!bofh_checkspf("BOFHSPFHELO", "off", "off"))
 
665
 
 
666
                {
 
667
                        errmsg[0]=0;
 
668
                        if (ipcmp(tcpremoteip, frominfo.helohost) == 0)
 
669
                                result="pass";
 
670
                        /* Consider HELO=ip.address a PASS */
 
671
                        else
 
672
                        {
 
673
                                result=my_spf_lookup("HELO",
 
674
                                                     frominfo.helohost,
 
675
                                                     tcpremoteip,
 
676
                                                     frominfo.helohost,
 
677
                                                     &receivedspfhelo,
 
678
                                                     errmsg,
 
679
                                                     sizeof(errmsg));
 
680
 
 
681
                                if (strcmp(result, "pass") == 0)
 
682
                                        bofhcheckhelo=0;
 
683
 
 
684
                                CString errmsg_buf=
 
685
                                        get_spf_errmsg("BOFHSPFHELO", result,
 
686
                                                       errmsg,
 
687
                                                       frominfo.helohost);
 
688
 
 
689
                                if (errmsg_buf.GetLength() > 0)
 
690
                                {
 
691
                                        cout << errmsg_buf << endl;
 
692
                                        return 1;
 
693
                                }
 
694
                                frominfo.receivedspfhelo=
 
695
                                        &receivedspfhelo;
 
696
                        }
 
697
                }
 
698
 
 
699
                if (*p && !bofh_checkspf("BOFHSPFMAILFROM", "off", "off"))
 
700
 
 
701
                {
 
702
                        errmsg[0]=0;
 
703
 
 
704
                        result=my_spf_lookup("MAILFROM",
 
705
                                             p,
 
706
                                             tcpremoteip,
 
707
                                             frominfo.helohost,
 
708
                                             &receivedspfmailfrom,
 
709
                                             errmsg,
 
710
                                             sizeof(errmsg));
 
711
 
 
712
                        CString errmsg_buf=
 
713
                                get_spf_errmsg("BOFHSPFMAILFROM", result,
 
714
                                               errmsg, p);
 
715
 
 
716
                        if (errmsg_buf.GetLength() > 0)
 
717
                        {
 
718
                                cout << errmsg_buf << endl;
 
719
                                return 1;
 
720
                        }
 
721
                        frominfo.receivedspfmailfrom=
 
722
                                &receivedspfmailfrom;
 
723
                        if (strcmp(result, "pass") == 0)
 
724
                                frominfo.mailfrom_passed_spf=1;
 
725
                }
 
726
 
 
727
        }
 
728
 
 
729
        if (bofhcheckhelo &&
 
730
            getenv("RELAYCLIENT") == NULL)
 
731
        {
522
732
                /*
523
733
                ** If HELO/EHLO does not match the IP address, query the MX
524
734
                ** records.
526
736
                struct rfc1035_mxlist *mxlist, *mxp;
527
737
                int checked_a=0;
528
738
 
529
 
                if (ipcmp(sbuf, tcpremoteip)) switch (rfc1035_mxlist_create(&rfc1035_default_resolver,
530
 
                                                                            sbuf, &mxlist))
 
739
                if (ipcmp(frominfo.helohost, tcpremoteip)) switch (rfc1035_mxlist_create(&rfc1035_default_resolver,
 
740
                                                                                frominfo.helohost, &mxlist))
531
741
                {
532
742
                case RFC1035_MX_OK:
533
743
 
552
762
                        if (mxp)
553
763
                        {
554
764
                                rfc1035_mxlist_free(mxlist);
555
 
                                free(sbuf);
556
765
                                break;
557
766
                        }
558
767
                        rfc1035_mxlist_free(mxlist);
559
768
 
560
769
                        if (!checked_a) /* No need to recheck A records */
561
770
                        {
562
 
                                int rc=checka(sbuf);
 
771
                                int rc=checka(frominfo.helohost);
563
772
 
564
773
                                if (rc == 0)
565
774
                                {
566
 
                                        free(sbuf);
567
775
                                        break;
568
776
                                }
569
777
 
570
778
                                if (rc > 0) /* temp failure */
571
779
                                {
572
780
                                        cout << "417 DNS lookup on HELO "
573
 
                                             << sbuf
 
781
                                             << frominfo.helohost
574
782
                                             << " failed.  Try again later."
575
783
                                             << endl << flush;
576
 
                                        free(sbuf);
577
784
                                        return 1;
578
785
                                }
579
786
                        }
580
787
 
581
 
                        cout << "517 HELO " << sbuf
 
788
                        cout << "517 HELO " << frominfo.helohost
582
789
                             << " does not match " << tcpremoteip << endl;
583
 
                        free(sbuf);
584
790
                        return 1;
585
791
 
586
792
                case RFC1035_MX_HARDERR:
587
 
                        cout << "517 HELO " << sbuf << " does not exist." << endl;
 
793
                        cout << "517 HELO " << frominfo.helohost << " does not exist." << endl;
588
794
                        return 1;
589
795
                case RFC1035_MX_BADDNS:
590
 
                        cout << "517 RFC 1035 violation: recursive CNAME records for " << sbuf << "." << endl;
 
796
                        cout << "517 RFC 1035 violation: recursive CNAME records for " << frominfo.helohost << "." << endl;
591
797
                        return 1;
592
798
                default:
593
 
                        cout << "417 DNS lookup on HELO " << sbuf <<
 
799
                        cout << "417 DNS lookup on HELO " << frominfo.helohost <<
594
800
                                " failed.  Try again later." << endl << flush;
595
801
                        return 1;
596
802
                }
1067
1273
 
1068
1274
        // Read headers
1069
1275
 
 
1276
CString spf_from_address="";
1070
1277
CString header, headername, headernameorig;
1071
1278
CString line;
1072
1279
CString accumulated_errmsg;
1132
1339
                }
1133
1340
 
1134
1341
        my_rcptinfo.submitfile.Message(line);
 
1342
        if (mf->receivedspfhelo)
 
1343
                my_rcptinfo.submitfile.Message(*mf->receivedspfhelo);
 
1344
        if (mf->receivedspfmailfrom)
 
1345
                my_rcptinfo.submitfile.Message(*mf->receivedspfmailfrom);
1135
1346
 
1136
1347
unsigned        received_cnt=0;
1137
1348
 
1301
1512
                                free(new_header);
1302
1513
                                header += '\n';
1303
1514
                        }
 
1515
                        if (headername == "from" &&
 
1516
                            !bofh_checkspf("BOFHSPFFROM", "off", "off"))
 
1517
                        {
 
1518
                                struct rfc822t *t=
 
1519
                                        rfc822t_alloc_new(header,
 
1520
                                                          NULL, NULL);
 
1521
 
 
1522
                                if (!t)
 
1523
                                        clog_msg_errno();
 
1524
 
 
1525
                                struct rfc822a *a=rfc822a_alloc(t);
 
1526
                                if (!a)
 
1527
                                        clog_msg_errno();
 
1528
 
 
1529
                                if (a->naddrs > 0 && a->addrs[0].tokens)
 
1530
                                {
 
1531
                                        char *s=rfc822_getaddr(a, 0);
 
1532
 
 
1533
                                        if (!s)
 
1534
                                                clog_msg_errno();
 
1535
 
 
1536
                                        spf_from_address=s;
 
1537
                                        free(s);
 
1538
                                }
 
1539
                                rfc822a_free(a);
 
1540
                                rfc822t_free(t);
 
1541
 
 
1542
                                if (mf->mailfrom_passed_spf &&
 
1543
                                    bofh_checkspf("BOFHSPFFROM", "off",
 
1544
                                                  "mailfromok"))
 
1545
                                {
 
1546
                                        spf_from_address="";
 
1547
                                }
 
1548
 
 
1549
                        }
 
1550
 
1304
1551
                }
1305
1552
                else if (headername == "message-id")    has_msgid=1;
1306
1553
                else if (headername == "date")  has_date=1;
1307
1554
 
1308
1555
                // Quote Return-Path:'s at this point
1309
1556
 
1310
 
                if (headername == "return-path")
 
1557
                if (headername == "return-path" ||
 
1558
                    (headername == "received-spf" &&
 
1559
                     mf->helohost.GetLength() > 0))
1311
1560
                        headernameorig="Old-"+headernameorig;
1312
1561
 
1313
1562
                my_rcptinfo.submitfile.Message(headernameorig);
1320
1569
                accumulated_errmsg += "511 Headers specify no receipients.\n";
1321
1570
        }
1322
1571
 
 
1572
        if (headercnt > 0)
 
1573
        {
 
1574
                if (spf_from_address.GetLength() > 0)
 
1575
                {
 
1576
                        CString received_spf;
 
1577
                        char errmsg[256];
 
1578
 
 
1579
                        const char *result=my_spf_lookup("FROM",
 
1580
                                                         spf_from_address,
 
1581
                                                         getenv("TCPREMOTEIP"),
 
1582
                                                         mf->helohost,
 
1583
                                                         &received_spf,
 
1584
                                                         errmsg,
 
1585
                                                         sizeof(errmsg));
 
1586
 
 
1587
                        CString errmsg_buf=
 
1588
                                get_spf_errmsg("BOFHSPFFROM", result,
 
1589
                                               errmsg, spf_from_address);
 
1590
 
 
1591
                        if (errmsg_buf.GetLength() > 0)
 
1592
                        {
 
1593
                                while (cin.get() != EOF)
 
1594
                                        ;
 
1595
                                mf->flag=1;
 
1596
                                cout << errmsg_buf << endl;
 
1597
                                return;
 
1598
                        }
 
1599
                        my_rcptinfo.submitfile.Message(received_spf);
 
1600
                }
 
1601
        }
1323
1602
        if (accumulated_errmsg)
1324
1603
        {
1325
1604
        int     n=atoi(accumulated_errmsg);