Ejemplo n.º 1
0
/**
 * configの説明を表示する
 *
 * @param out	出力先のストリーム
 */
static void
EnmaConfig_usage(FILE *out)
{
    assert(NULL != out);

    fprintf(out, "Options[with default]:\n");
    fprintf(out, "  -h\t: show this message\n");
    fprintf(out, "  -v\t: verbose mode\n");
    fprintf(out, "  -c filename\t: configuration file on startup\n");
    fprintf(out, "\n");
    for (const ConfigEntry *p = ConfigEntry_table; NULL != p->config_name; ++p) {
        fprintf(out, "  -o %s\t: %s [%s]\n", p->config_name, p->description,
                NNSTR(p->default_value));
    }
    fflush(out);
}
Ejemplo n.º 2
0
/**
 * @attention this function may rewrite yenmacfg
 */
bool
YenmaContext_buildPolicies(YenmaContext *self, YenmaConfig *yenmacfg)
{
    // Resolver
    DnsResolver_initializer *initializer = DnsResolver_lookupInitializer(yenmacfg->resolver_engine);
    if (NULL == initializer) {
        LogError("failed to load resolver module: resolver=%s",
                 PTROR(yenmacfg->resolver_engine, "any"));
        return false;
    }   // end if
    self->resolver_pool =
        ResolverPool_new(initializer, yenmacfg->resolver_conf, yenmacfg->resolver_pool_size,
                         (int) yenmacfg->resolver_timeout, (int) yenmacfg->resolver_retry_count);
    if (NULL == self->resolver_pool) {
        LogNoResource();
        return false;
    }   // end if

    // DMARC setup
    if (yenmacfg->dmarc_verify) {
        // enable SPF and DKIM
        if (!yenmacfg->spf_verify) {
            yenmacfg->spf_verify = true;
            LogNotice("SPF verification is turned on as a part of DMARC verification");
        }   // end if
        if (!yenmacfg->dkim_verify) {
            yenmacfg->dkim_verify = true;
            LogNotice("DKIM verification is turned on as a part of DMARC verification");
        }   // end if

        // load public suffix list
        if (NULL == yenmacfg->dmarc_public_suffix_list) {
            LogError("Public Suffix List must be specified for DMARC verification");
            return false;
        }   // end if
        if (DSTAT_OK !=
            PublicSuffix_build(yenmacfg->dmarc_public_suffix_list, &self->public_suffix)) {
            LogError("failed to load public suffix list: filename=%s",
                     yenmacfg->dmarc_public_suffix_list);
            return false;
        }   // end if

        // check SMTP reject actions
        self->dmarc_reject_action = YenmaConfig_lookupSmtpRejectActionByKeyword(yenmacfg->dmarc_reject_action);
        if (0 > self->dmarc_reject_action) {
            LogError("invalid SMTP action for DMARC reject: action=%s", yenmacfg->dmarc_reject_action);
            return false;
        } else if (SMFIS_REJECT == self->dmarc_reject_action && (notstartwith(yenmacfg->dmarc_reject_reply_code, '5') || notstartwith(yenmacfg->dmarc_reject_enhanced_status_code, '5'))) {
            LogError("invalid SMTP reply code or enhanced status code  for DMARC reject action: reply_code=%s, ehanced_status_code=%s", NNSTR(yenmacfg->dmarc_reject_reply_code), NNSTR(yenmacfg->dmarc_reject_enhanced_status_code));
            return false;
        } else if (SMFIS_TEMPFAIL == self->dmarc_reject_action && (notstartwith(yenmacfg->dmarc_reject_reply_code, '4') || notstartwith(yenmacfg->dmarc_reject_enhanced_status_code, '4'))) {
            LogError("invalid SMTP reply code or enhanced status code  for DMARC tempfail action: reply_code=%s, ehanced_status_code=%s", NNSTR(yenmacfg->dmarc_reject_reply_code), NNSTR(yenmacfg->dmarc_reject_enhanced_status_code));
            return false;
        }   // end if
    }   // end if

    if (yenmacfg->dkim_adsp_verify && !yenmacfg->dkim_verify) {
        yenmacfg->dkim_verify = true;
        LogNotice("DKIM verification is turned on as a part of DKIM-ADSP verification");
    }   // end if

    // building DkimVerificationPolicy
    if (yenmacfg->dkim_verify) {
        DkimStatus config_stat =
            YenmaConfig_buildDkimVerificationPolicy(yenmacfg, &self->dkim_vpolicy);
        if (DSTAT_OK != config_stat) {
            return false;
        }   // end if
    }   // end if

    // building SpfEvalPolicy for SPF (must be after determining authserv-id)
    if (yenmacfg->spf_verify) {
        self->spfevalpolicy = YenmaConfig_buildSpfEvalPolicy(yenmacfg);
        if (NULL == self->spfevalpolicy) {
            return false;
        }   // end if
    }   // end if

    // building SpfEvalPolicy for SIDF (must be after determining authserv-id)
    if (yenmacfg->sidf_verify) {
        self->sidfevalpolicy = YenmaConfig_buildSidfEvalPolicy(yenmacfg);
        if (NULL == self->sidfevalpolicy) {
            return false;
        }   // end if
    }   // end if

    if (NULL != yenmacfg->service_exclusion_blocks) {
        self->exclusion_block = YenmaConfig_buildExclusionBlock(yenmacfg->service_exclusion_blocks);
        if (NULL == self->exclusion_block) {
            return false;
        }   // end if
    }   // end if

    return true;
}   // end function: YenmaContext_buildPolicies
Ejemplo n.º 3
0
/**
 * @return DSTAT_OK for success, otherwise status code that indicates error.
 * @error DSTAT_INFO_ADSP_NOT_EXIST ADSP record have not found
 * @error DSTAT_PERMFAIL_MULTIPLE_ADSP_RECORD multiple ADSP records are found
 * @error DSTAT_TMPERR_DNS_ERROR_RESPONSE DNS lookup error (received error response)
 * @error DSTAT_SYSERR_DNS_LOOKUP_FAILURE DNS lookup error (failed to lookup itself)
 * @error DSTAT_SYSERR_IMPLERROR obvious implementation error
 * @error DSTAT_SYSERR_NORESOURCE memory allocation error
 */
static DkimAdsp *
DkimAdsp_query(const DkimPolicyBase *policy, DnsResolver *resolver, const char *domain,
               DkimStatus *dstat)
{
    assert(NULL != resolver);
    assert(NULL != domain);

    // lookup ADSP record
    DnsTxtResponse *txt_rr = NULL;
    dns_stat_t txtquery_stat = DnsResolver_lookupTxt(resolver, domain, &txt_rr);
    switch (txtquery_stat) {
    case DNS_STAT_NOERROR:;
        // a TXT RR is found

        /*
         * [RFC5617] 4.3.
         * If the result of this query is a NOERROR response (rcode=0 in
         * [RFC1035]) with an answer that is a single record that is a valid
         * ADSP record, use that record, and the algorithm terminates.
         */
        if (0 == DnsTxtResponse_size(txt_rr)) {
            // no TXT records are found
            DnsTxtResponse_free(txt_rr);
            SETDEREF(dstat, DSTAT_INFO_ADSP_NOT_EXIST);
            break;
        } else if (1 < DnsTxtResponse_size(txt_rr)) {
            // multiple TXT records are found
            DnsTxtResponse_free(txt_rr);
            SETDEREF(dstat, DSTAT_PERMFAIL_MULTIPLE_ADSP_RECORD);
            break;
        }   // end if

        // only one TXT record is found, and now, try to parse as ADSP record
        DkimStatus build_stat;
        const char *txtrecord = DnsTxtResponse_data(txt_rr, 0);
        DkimAdsp *self = DkimAdsp_build(policy, txtrecord, &build_stat);
        if (NULL != self) {
            // parsed as a valid ADSP record
            DnsTxtResponse_free(txt_rr);
            SETDEREF(dstat, DSTAT_OK);
            return self;
        } else if (DSTAT_ISCRITERR(build_stat)) {
            // propagate system errors as-is
            DkimLogSysError
                (policy,
                 "System error has occurred while parsing ADSP record: domain=%s, err=%s, record=%s",
                 domain, DKIM_strerror(build_stat), NNSTR(txtrecord));
            SETDEREF(dstat, build_stat);
        } else if (DSTAT_ISPERMFAIL(build_stat)) {
            /*
             * treat syntax errors on ADSP record as DNS NODATA response
             *
             * [RFC5617] 4.1.
             * Records not in compliance with that syntax
             * or the syntax of individual tags described in Section 4.3 MUST be
             * ignored (considered equivalent to a NODATA result) for purposes of
             * ADSP, although they MAY cause the logging of warning messages via an
             * appropriate system logging mechanism.
             */
            DkimLogDebug(policy, "ADSP record candidate discarded: domain=%s, err=%s, record=%s",
                         domain, DKIM_strerror(build_stat), NNSTR(txtrecord));
            SETDEREF(dstat, DSTAT_INFO_ADSP_NOT_EXIST);
        } else {
            DkimLogNotice(policy, "DkimAdsp_build failed: domain=%s, err=%s, record=%s",
                          domain, DKIM_strerror(build_stat), NNSTR(txtrecord));
            SETDEREF(dstat, DSTAT_INFO_ADSP_NOT_EXIST);
        }   // end if

        // a TXT RR is not a valid ADSP record
        DnsTxtResponse_free(txt_rr);
        break;

    case DNS_STAT_NXDOMAIN:
    case DNS_STAT_NODATA:
        /*
         * no TXT (and ADSP) records are found
         *
         * [RFC5617] 4.3.
         * If the result of the query is NXDOMAIN or NOERROR with zero
         * records, there is no ADSP record.  If the result of the query
         * contains more than one record, or a record that is not a valid
         * ADSP record, the ADSP result is undefined.
         */
        DkimLogDebug(policy, "No ADSP record is found on DNS: domain=%s", domain);
        SETDEREF(dstat, DSTAT_INFO_ADSP_NOT_EXIST);
        break;

    case DNS_STAT_FORMERR:
    case DNS_STAT_SERVFAIL:
    case DNS_STAT_NOTIMPL:
    case DNS_STAT_REFUSED:
    case DNS_STAT_YXDOMAIN:
    case DNS_STAT_YXRRSET:
    case DNS_STAT_NXRRSET:
    case DNS_STAT_NOTAUTH:
    case DNS_STAT_NOTZONE:
    case DNS_STAT_RESERVED11:
    case DNS_STAT_RESERVED12:
    case DNS_STAT_RESERVED13:
    case DNS_STAT_RESERVED14:
    case DNS_STAT_RESERVED15:
        /*
         * [RFC5617] 4.3.
         * If a query results in a "SERVFAIL" error response (rcode=2 in
         * [RFC1035]), the algorithm terminates without returning a result;
         * possible actions include queuing the message or returning an SMTP
         * error indicating a temporary failure.
         */
        DkimLogInfo(policy, "DNS error on ADSP record look-up: domain=%s, type=txt, err=%s",
                    domain, DnsResolver_getErrorString(resolver));
        SETDEREF(dstat, DSTAT_TMPERR_DNS_ERROR_RESPONSE);
        break;

    case DNS_STAT_SYSTEM:
    case DNS_STAT_RESOLVER:
    case DNS_STAT_RESOLVER_INTERNAL:
        DkimLogSysError(policy, "error occurred during DNS lookup: domain=%s, type=txt, err=%s",
                        domain, DnsResolver_getErrorString(resolver));
        SETDEREF(dstat, DSTAT_SYSERR_DNS_LOOKUP_FAILURE);
        break;

    case DNS_STAT_NOMEMORY:
        DkimLogNoResource(policy);
        SETDEREF(dstat, DSTAT_SYSERR_NORESOURCE);
        break;

    case DNS_STAT_BADREQUEST:
    default:
        DkimLogImplError(policy,
                         "DnsResolver_lookupTxt returns unexpected value: value=0x%x, domain=%s, type=txt",
                         txtquery_stat, domain);
        SETDEREF(dstat, DSTAT_SYSERR_IMPLERROR);
        break;
    }   // end switch

    return NULL;
}   // end function: DkimAdsp_query