Back to index

opendkim  2.6.4
opendkim.c
Go to the documentation of this file.
00001 /*
00002 **  Copyright (c) 2005-2009 Sendmail, Inc. and its suppliers.
00003 **     All rights reserved.
00004 **
00005 **  Copyright (c) 2009-2012, The OpenDKIM Project.  All rights reserved.
00006 **
00007 **  $Id: opendkim.c,v 1.230 2010/10/28 06:10:07 cm-msk Exp $
00008 */
00009 
00010 #ifndef lint
00011 static char opendkim_c_id[] = "@(#)$Id: opendkim.c,v 1.230 2010/10/28 06:10:07 cm-msk Exp $";
00012 #endif /* !lint */
00013 
00014 #include "build-config.h"
00015 
00016 #ifndef _POSIX_PTHREAD_SEMANTICS
00017 # define _POSIX_PTHREAD_SEMANTICS
00018 #endif /* ! _POSIX_PTHREAD_SEMANTICS */
00019 
00020 /* system includes */
00021 #include <sys/types.h>
00022 #include <sys/param.h>
00023 #include <sys/stat.h>
00024 #include <sys/socket.h>
00025 #include <sys/wait.h>
00026 #ifdef HAVE_ISO_LIMITS_ISO_H
00027 # include <iso/limits_iso.h>
00028 #endif /* HAVE_ISO_LIMITS_ISO_H */
00029 #ifdef HAVE_LIMITS_H
00030 # include <limits.h>
00031 #endif /* HAVE_LIMITS_H */
00032 #ifdef __linux__
00033 # include <sys/prctl.h>
00034 #endif /* __linux__ */
00035 #ifdef USE_LUA
00036 # include <netinet/in.h>
00037 # include <arpa/inet.h>
00038 #endif /* USE_LUA */
00039 #ifdef AF_INET6
00040 # include <arpa/inet.h>
00041 #endif /* AF_INET6 */
00042 #ifdef HAVE_STDBOOL_H
00043 # include <stdbool.h>
00044 #endif /* HAVE_STDBOOL_H */
00045 #include <stdlib.h>
00046 #include <stdio.h>
00047 #include <string.h>
00048 #include <syslog.h>
00049 #include <sysexits.h>
00050 #include <errno.h>
00051 #include <unistd.h>
00052 #include <pwd.h>
00053 #include <grp.h>
00054 #include <math.h>
00055 #include <assert.h>
00056 #include <ctype.h>
00057 #include <fcntl.h>
00058 #include <pthread.h>
00059 #include <netdb.h>
00060 #include <signal.h>
00061 #include <regex.h>
00062 
00063 #ifdef USE_GNUTLS
00064 # include <gnutls/gnutls.h>
00065 #else /* USE_GNUTLS */
00066 # include <openssl/sha.h>
00067 # include <openssl/err.h>
00068 #endif /* USE_GNUTLS */
00069 
00070 #ifdef HAVE_PATHS_H
00071 # include <paths.h>
00072 #endif /* HAVE_PATHS_H */
00073 #ifndef _PATH_DEVNULL
00074 # define _PATH_DEVNULL             "/dev/null"
00075 #endif /* ! _PATH_DEVNULL */
00076 
00077 /* libmilter includes */
00078 #include "libmilter/mfapi.h"
00079 
00080 #ifdef USE_LUA
00081 /* LUA includes */
00082 # include <lua.h>
00083 #endif /* USE_LUA */
00084 
00085 #ifdef _FFR_RBL
00086 /* librbl includes */
00087 # include <rbl.h>
00088 #endif /* _FFR_RBL */
00089 
00090 #ifdef _FFR_DKIM_REPUTATION
00091 /* libdkimrep includes */
00092 # include <dkim-rep.h>
00093 #endif /* _FFR_DKIM_REPUTATION */
00094 
00095 /* libopendkim includes */
00096 #include "dkim.h"
00097 #ifdef _FFR_VBR
00098 # include "vbr.h"
00099 #endif /* _FFR_VBR */
00100 #include "dkim-strl.h"
00101 
00102 #ifdef _FFR_REPUTATION
00103 /* reputation includes */
00104 # include <repute.h>
00105 #endif /* _FFR_REPUTATION */
00106 
00107 /* opendkim includes */
00108 #include "config.h"
00109 #ifdef _FFR_RATE_LIMIT
00110 # include "flowrate.h"
00111 #endif /* _FFR_RATE_LIMIT */
00112 #include "opendkim-db.h"
00113 #include "opendkim-config.h"
00114 #include "opendkim-crypto.h"
00115 #include "opendkim.h"
00116 #include "opendkim-ar.h"
00117 #include "opendkim-arf.h"
00118 #include "opendkim-dns.h"
00119 #ifdef USE_LUA
00120 # include "opendkim-lua.h"
00121 #endif /* USE_LUA */
00122 #include "util.h"
00123 #include "test.h"
00124 #ifdef _FFR_STATS
00125 # include "stats.h"
00126 #endif /* _FFR_STATS */
00127 #ifdef _FFR_REPUTATION
00128 # include "reputation.h"
00129 #endif /* _FFR_REPUTATION */
00130 
00131 /* macros */
00132 #define CMDLINEOPTS  "Ab:c:d:De:fF:k:lL:no:p:P:qQrs:S:t:T:u:vVWx:?"
00133 
00134 #ifndef MIN
00135 # define MIN(x,y)    ((x) < (y) ? (x) : (y))
00136 #endif /* ! MIN */
00137 
00138 #define       DKIMF_MILTER_ACCEPT  0
00139 #define       DKIMF_MILTER_REJECT  1
00140 #define       DKIMF_MILTER_TEMPFAIL       2
00141 #define       DKIMF_MILTER_DISCARD 3
00142 #define       DKIMF_MILTER_QUARANTINE     4
00143 
00144 /*
00145 **  ADDRLIST -- address list
00146 */
00147 
00148 struct addrlist
00149 {
00150        char *        a_addr;                     /* address */
00151        struct addrlist * a_next;          /* next record */
00152 };
00153 
00154 /*
00155 **  HANDLING -- message handling requests
00156 */
00157 
00158 struct handling
00159 {
00160        int           hndl_nosig;          /* no signature */
00161        int           hndl_badsig;         /* bad signature */
00162        int           hndl_nokey;          /* no key in DNS */
00163        int           hndl_dnserr;         /* DNS error */
00164        int           hndl_policyerr;             /* policy retrieval error */
00165        int           hndl_internal;              /* internal error */
00166 #ifdef _FFR_REPUTATION
00167        int           hndl_reperr;         /* reputation error */
00168 #endif /* _FFR_REPUTATION */
00169        int           hndl_security;              /* security concerns */
00170 };
00171 
00172 struct handling defaults =
00173 {
00174        DKIMF_MILTER_ACCEPT,               /* nosig */
00175        DKIMF_MILTER_ACCEPT,               /* badsig */
00176        DKIMF_MILTER_ACCEPT,               /* nokey */
00177        DKIMF_MILTER_TEMPFAIL,                    /* dnserr */
00178        DKIMF_MILTER_ACCEPT,               /* policyerr */
00179        DKIMF_MILTER_TEMPFAIL,                    /* internal */
00180 #ifdef _FFR_REPUTATION
00181        DKIMF_MILTER_ACCEPT,               /* reperror */
00182 #endif /* _FFR_REPUTATION */
00183        DKIMF_MILTER_TEMPFAIL                     /* security */
00184 };
00185 
00186 #ifdef _FFR_LUA_GLOBALS
00187 /*
00188 **  LUA_GLOBAL -- linked list of Lua globals
00189 */
00190 
00191 struct lua_global
00192 {
00193        int           lg_type;
00194        char *        lg_name;
00195        void *        lg_value;
00196        struct lua_global * lg_next;
00197 };
00198 #endif /* _FFR_LUA_GLOBALS */
00199 
00200 /*
00201 **  CONFIG -- configuration data
00202 */
00203 
00204 struct dkimf_config
00205 {
00206 #ifdef USE_LDAP
00207        _Bool         conf_softstart;             /* do LDAP soft starts */
00208 #endif /* USE_LDAP */
00209        _Bool         conf_weaksyntax;     /* do weaker syntax checking */
00210        _Bool         conf_noadsp;         /* suppress ADSP */
00211        _Bool         conf_logresults;     /* log all results */
00212        _Bool         conf_allsigs;        /* report on all signatures */
00213        _Bool         conf_dnsconnect;     /* request TCP mode from DNS */
00214        _Bool         conf_capture;        /* capture unknown errors */
00215        _Bool         conf_restrace;              /* resolver tracing? */
00216        _Bool         conf_acceptdk;              /* accept DK keys? */
00217        _Bool         conf_addxhdr;        /* add identifying header? */
00218        _Bool         conf_blen;           /* use "l=" when signing */
00219        _Bool         conf_ztags;          /* use "z=" when signing */
00220        _Bool         conf_alwaysaddar;    /* always add Auth-Results:? */
00221        _Bool         conf_reqreports;     /* request reports */
00222        _Bool         conf_sendreports;    /* signature failure reports */
00223        _Bool         conf_sendadspreports;       /* ADSP failure reports */
00224        _Bool         conf_adspnxdomain;   /* reject on ADSP NXDOMAIN? */
00225        _Bool         conf_reqhdrs;        /* required header checks */
00226        _Bool         conf_authservidwithjobid; /* use jobids in A-R headers */
00227        _Bool         conf_subdomains;     /* sign subdomains */
00228        _Bool         conf_remsigs;        /* remove current signatures? */
00229        _Bool         conf_remarall;              /* remove all matching ARs? */
00230        _Bool         conf_keepar;         /* keep our ARs? */
00231        _Bool         conf_dolog;          /* syslog interesting stuff? */
00232        _Bool         conf_dolog_success;  /* syslog successes too? */
00233        _Bool         conf_milterv2;              /* using milter v2? */
00234        _Bool         conf_fixcrlf;        /* fix bare CRs and LFs? */
00235        _Bool         conf_logwhy;         /* log mode decision logic */
00236        _Bool         conf_allowsha1only;  /* allow rsa-sha1 verifying */
00237        _Bool         conf_stricthdrs;     /* strict header checks */
00238        _Bool         conf_keeptmpfiles;   /* keep temporary files */
00239        _Bool         conf_multisig;              /* multiple signatures */
00240        _Bool         conf_enablecores;    /* enable coredumps */
00241        _Bool         conf_noheaderb;             /* suppress "header.b" */
00242        _Bool         conf_singleauthres;  /* single Auth-Results */
00243        _Bool         conf_safekeys;              /* check key permissions */
00244 #ifdef _FFR_RESIGN
00245        _Bool         conf_resignall;             /* resign unverified mail */
00246 #endif /* _FFR_RESIGN */
00247 #ifdef USE_LDAP
00248        _Bool         conf_ldap_usetls;    /* LDAP TLS */
00249 #endif /* USE_LDAP */
00250 #ifdef _FFR_VBR
00251        _Bool         conf_vbr_purge;             /* purge X-VBR-* fields */
00252        _Bool         conf_vbr_trustedonly;       /* trusted certifiers only */
00253 #endif /* _FFR_VBR */
00254 #ifdef _FFR_REPUTATION
00255        _Bool         conf_repverbose;     /* verbose reputation logs */
00256 #endif /* _FFR_REPUTATION */
00257        unsigned int  conf_mode;           /* operating mode */
00258        unsigned int  conf_refcnt;         /* reference count */
00259        unsigned int  conf_dnstimeout;     /* DNS timeout */
00260        unsigned int  conf_maxhdrsz;              /* max header bytes */
00261        unsigned int  conf_maxverify;             /* max sigs to verify */
00262 #ifdef _FFR_REPUTATION
00263        unsigned int  conf_repfactor;             /* reputation factor */
00264        unsigned int  conf_repminimum;     /* reputation minimum */
00265        unsigned int  conf_repcachettl;    /* reputation cache TTL */
00266 #endif /* _FFR_REPUTATION */
00267 #ifdef USE_UNBOUND
00268        unsigned int  conf_boguskey;              /* bogus key action */
00269        unsigned int  conf_insecurekey;    /* insecure key action */
00270        unsigned int  conf_boguspolicy;    /* bogus policy action */
00271        unsigned int  conf_insecurepolicy; /* insecure policy action */
00272 #endif /* USE_UNBOUND */
00273 #ifdef _FFR_RATE_LIMIT
00274        unsigned int  conf_flowdatattl;    /* flow data TTL */
00275        unsigned int  conf_flowfactor;     /* flow factor */
00276 #endif /* _FFR_RATE_LIMIT */
00277        int           conf_clockdrift;     /* tolerable clock drift */
00278        int           conf_sigmintype;     /* signature minimum type */
00279        int           conf_adspaction;     /* apply ADSP "discardable"? */
00280        size_t        conf_sigmin;         /* signature minimum */
00281        size_t        conf_keylen;         /* size of secret key */
00282 #ifdef USE_LUA
00283        size_t        conf_screenfuncsz;   /* screening function size */
00284        size_t        conf_setupfuncsz;    /* setup function size */
00285 # ifdef _FFR_STATS
00286        size_t        conf_statsfuncsz;    /* stats function size */
00287 # endif /* _FFR_STATS */
00288        size_t        conf_finalfuncsz;    /* final function size */
00289 #endif /* USE_LUA */
00290 #ifdef _FFR_DKIM_REPUTATION
00291        long          conf_repfail;        /* reputation "fail" limit */
00292        long          conf_reppass;        /* reputation "pass" limit */
00293        long          conf_repreject;             /* reputation "reject" limit */
00294 #endif /* _FFR_DKIM_REPUTATION */
00295        ssize_t              conf_signbytes;             /* bytes to sign */
00296        dkim_canon_t  conf_hdrcanon;              /* canon. method for headers */
00297        dkim_canon_t  conf_bodycanon;             /* canon. method for body */
00298        unsigned long conf_sigttl;         /* signature TTLs */
00299        dkim_alg_t    conf_signalg;        /* signing algorithm */
00300        struct config *      conf_data;           /* configuration data */
00301        char *        conf_authservid;     /* authserv-id */
00302        char *        conf_keyfile;        /* key file for single key */
00303        char *        conf_keytable;              /* key table */
00304        char *        conf_signtable;             /* signing table */
00305        char *        conf_peerfile;              /* peer file */
00306        char *        conf_internalfile;   /* internal hosts file */
00307        char *        conf_externalfile;   /* external hosts file */
00308        char *        conf_exemptfile;     /* exempt domains file */
00309        char *        conf_tmpdir;         /* temp directory */
00310        char *        conf_omitlist;              /* omit header list */
00311        char *        conf_domlist;        /* signing domain list */
00312        char *        conf_signalgstr;     /* signature algorithm string */
00313        char *        conf_modestr;        /* mode string */
00314        char *        conf_canonstr;              /* canonicalization(s) string */
00315        char *        conf_siglimit;              /* signing limits */
00316        char *        conf_chroot;         /* chroot(2) directory */
00317        char *        conf_selectcanonhdr; /* canon select header name */
00318        u_char *      conf_selector;              /* key selector */
00319 #ifdef _FFR_DEFAULT_SENDER
00320        char *        conf_defsender;             /* default sender address */
00321 #endif /* _FFR_DEFAULT_SENDER */
00322 #ifdef _FFR_RESIGN
00323        char *        conf_resign;         /* resign mail to */
00324 #endif /* _FFR_RESIGN */
00325 #ifdef _FFR_SENDER_MACRO
00326        char *        conf_sendermacro;    /* macro containing sender */
00327 #endif /* _FFR_SENDER_MACRO */
00328        char *        conf_testdnsdata;    /* test DNS data */
00329 #ifdef _FFR_IDENTITY_HEADER
00330        char *        conf_identityhdr;    /* identity header */
00331        _Bool         conf_rmidentityhdr;  /* remove identity header */
00332 #endif /* _FFR_IDENTITY_HEADER */
00333        char *        conf_diagdir;        /* diagnostics directory */
00334 #ifdef _FFR_STATS
00335        char *        conf_statspath;             /* path for stats file */
00336        char *        conf_reporthost;     /* reporter name */
00337        char *        conf_reportprefix;   /* stats data prefix */
00338 #endif /* _FFR_STATS */
00339 #ifdef _FFR_DKIM_REPUTATION
00340        char *        conf_reproot;        /* root of reputation queries */
00341 #endif /* _FFR_DKIM_REPUTATION */
00342        char *        conf_reportaddr;     /* report sender address */
00343        char *        conf_reportaddrbcc;  /* report repcipient address as bcc */
00344        char *        conf_mtacommand;     /* MTA command (reports) */
00345        char *        conf_localadsp_file; /* local ADSP file */
00346 #ifdef _FFR_REDIRECT
00347        char *        conf_redirect;              /* redirect failures to */
00348 #endif /* _FFR_REDIRECT */
00349 #ifdef USE_LDAP
00350        char *        conf_ldap_timeout;   /* LDAP timeout */
00351        char *        conf_ldap_kaidle;    /* LDAP keepalive idle */
00352        char *        conf_ldap_kaprobes;  /* LDAP keepalive probes */
00353        char *        conf_ldap_kainterval;       /* LDAP keepalive interval */
00354        char *        conf_ldap_binduser;  /* LDAP bind user */
00355        char *          conf_ldap_bindpw;  /* LDAP bind password */
00356        char *          conf_ldap_authmech;       /* LDAP auth mechanism */
00357 # ifdef USE_SASL
00358        char *        conf_ldap_authname;  /* LDAP auth name */
00359        char *        conf_ldap_authuser;  /* LDAP auth user */
00360        char *        conf_ldap_authrealm; /* LDAP auth realm */
00361 # endif /* USE_SASL */
00362 #endif /* USE_LDAP */
00363 #ifdef USE_LUA
00364        char *        conf_screenscript;   /* Lua script: screening */
00365        void *        conf_screenfunc;     /* Lua function: screening */
00366        char *        conf_setupscript;    /* Lua script: setup */
00367        void *        conf_setupfunc;             /* Lua function: setup */
00368 # ifdef _FFR_STATSEXT
00369        char *        conf_statsscript;    /* Lua script: stats */
00370        void *        conf_statsfunc;             /* Lua function: stats */
00371 # endif /* _FFR_STATSEXT */
00372        char *        conf_finalscript;    /* Lua script: final */
00373        void *        conf_finalfunc;             /* Lua function: final */
00374 #endif /* USE_LUA */
00375 #ifdef _FFR_REPLACE_RULES
00376        char *        conf_rephdrs;        /* replacement headers */
00377        struct replace * conf_replist;            /* replacement list */
00378        DKIMF_DB      conf_rephdrsdb;             /* replacement headers (DB) */
00379 #endif /* _FFR_REPLACE_RULES */
00380        dkim_sigkey_t conf_seckey;         /* secret key data */
00381 #ifdef USE_UNBOUND
00382        char *        conf_trustanchorpath;       /* unbound trust anchor file */
00383        char *        conf_unboundconfig;  /* unbound config file */
00384        char *        conf_resolvconf;     /* resolv.conf file */
00385        struct dkimf_unbound * conf_unbound;      /* libunbound handle */
00386 #endif /* USE_UNBOUND */
00387 #ifdef USE_ARLIB
00388        AR_LIB        conf_arlib;          /* libar handle */
00389 #endif /* USE_ARLIB */
00390 #ifdef _FFR_VBR
00391        char *        conf_vbr_deftype;    /* default VBR type */
00392        char *        conf_vbr_defcert;    /* default VBR certifiers */
00393        DKIMF_DB      conf_vbr_trusteddb;  /* trusted certifiers (DB) */
00394        u_char **     conf_vbr_trusted;    /* trusted certifiers */
00395 #endif /* _FFR_VBR */
00396        DKIMF_DB      conf_testdnsdb;             /* test TXT records */
00397        DKIMF_DB      conf_bldb;           /* l= recipients (DB) */
00398        DKIMF_DB      conf_domainsdb;             /* domains to sign (DB) */
00399        DKIMF_DB      conf_omithdrdb;             /* headers to omit (DB) */
00400        char **              conf_omithdrs;              /* headers to omit (array) */
00401        DKIMF_DB      conf_signhdrsdb;     /* headers to sign (DB) */
00402        char **              conf_signhdrs;              /* headers to sign (array) */
00403        DKIMF_DB      conf_alwayshdrsdb;   /* always incl. hdrs (DB) */
00404        char **              conf_alwayshdrs;     /* always incl. hdrs (array) */
00405        DKIMF_DB      conf_senderhdrsdb;   /* sender headers (DB) */
00406        char **              conf_senderhdrs;     /* sender headers (array) */
00407        DKIMF_DB      conf_mtasdb;         /* MTA ports to sign (DB) */
00408        char **              conf_mtas;           /* MTA ports to sign (array) */
00409        DKIMF_DB      conf_remardb;        /* A-R removal list (DB) */
00410        char **              conf_remar;          /* A-R removal list (array) */
00411        DKIMF_DB      conf_mbsdb;          /* must-be-signed hdrs (DB) */
00412        char **              conf_mbs;            /* must-be-signed (array) */
00413 #ifdef _FFR_OVERSIGN
00414        DKIMF_DB      conf_oversigndb;     /* fields to over-sign (DB) */
00415        char **              conf_oversignhdrs;   /*   "    "     "    (array) */
00416 #endif /* _FFR_OVERSIGN */
00417        DKIMF_DB      conf_dontsigntodb;   /* don't-sign-to addrs (DB) */
00418 #ifdef _FFR_ATPS
00419        DKIMF_DB      conf_atpsdb;         /* ATPS domains */
00420        char *        conf_atpshash;              /* ATPS hash algorithm */
00421 #endif /* _FFR_ATPS */
00422 #ifdef _FFR_ADSP_LISTS
00423        DKIMF_DB      conf_nodiscardto;    /* no discardable to (DB) */
00424 #endif /* _FFR_ADSP_LISTS */
00425        DKIMF_DB      conf_thirdpartydb;   /* trustsigsfrom DB */
00426        DKIMF_DB      conf_localadsp_db;   /* local ADSP DB */
00427        DKIMF_DB      conf_macrosdb;              /* macros/values (DB) */
00428        char **              conf_macros;         /* macros/values to check */
00429        regex_t **    conf_nosignpats;     /* do-not-sign patterns */
00430        DKIMF_DB      conf_peerdb;         /* DB of "peers" */
00431        DKIMF_DB      conf_internal;              /* DB of "internal" hosts */
00432        DKIMF_DB      conf_exignore;              /* "external ignore" host DB */
00433        DKIMF_DB      conf_exemptdb;              /* exempt domains DB */
00434        DKIMF_DB      conf_keytabledb;     /* key table DB */
00435        DKIMF_DB      conf_signtabledb;    /* signing table DB */
00436 #ifdef _FFR_STATS
00437        DKIMF_DB      conf_anondb;         /* anonymized domains DB */
00438 #endif /* _FFR_STATS */
00439 #ifdef _FFR_RESIGN
00440        DKIMF_DB      conf_resigndb;              /* resigning addresses */
00441 #endif /* _FFR_RESIGN */
00442 #ifdef _FFR_RATE_LIMIT
00443        DKIMF_DB      conf_ratelimitdb;    /* domain rate limits */
00444        DKIMF_DB      conf_flowdatadb;     /* domain flow data */
00445 #endif /* _FFR_RATE_LIMIT */
00446 #ifdef _FFR_REPUTATION
00447        char *        conf_repratios;             /* reputed ratios */
00448        DKIMF_DB      conf_repratiosdb;    /* reputed ratios DB */
00449        char *        conf_replimits;             /* reputed limits */
00450        DKIMF_DB      conf_replimitsdb;    /* reputed limits DB */
00451        char *        conf_replimitmods;   /* reputed limit modifiers */
00452        DKIMF_DB      conf_replimitmodsdb; /* reputed limit mods DB */
00453        char *        conf_replowtime;     /* reputed low timers */
00454        DKIMF_DB      conf_replowtimedb;   /* reputed low timers DB */
00455        DKIMF_REP     conf_rep;            /* reputation subsystem */
00456        char *        conf_repcache;              /* reputation cache DB */
00457        char *        conf_repdups;        /* reputation duplicates DB */
00458        char *        conf_repspamcheck;   /* reputation spam RE string */
00459        regex_t              conf_repspamre;             /* reputation spam RE */
00460 #endif /* _FFR_REPUTATION */
00461        DKIM_LIB *    conf_libopendkim;    /* DKIM library handle */
00462        struct handling      conf_handling;              /* message handling */
00463 };
00464 
00465 /*
00466 **  MSGCTX -- message context, containing transaction-specific data
00467 */
00468 
00469 typedef struct msgctx * msgctx;
00470 struct msgctx
00471 {
00472        _Bool         mctx_bldbdone;              /* BodyLengthDB applied? */
00473        _Bool         mctx_eom;            /* in EOM? (enables progress) */
00474        _Bool         mctx_addheader;             /* Authentication-Results: */
00475        _Bool         mctx_headeronly;     /* in EOM, only add headers */
00476        _Bool         mctx_ltag;           /* sign with l= tag? */
00477        _Bool         mctx_capture;        /* capture message? */
00478        _Bool         mctx_susp;           /* suspicious message? */
00479 #ifdef _FFR_RESIGN
00480        _Bool         mctx_resign;         /* arrange to re-sign */
00481 #endif /* _FFR_RESIGN */
00482 #ifdef _FFR_VBR
00483        _Bool         mctx_vbrpurge;              /* purge X-VBR-* headers */
00484 #endif /* _FFR_VBR */
00485 #ifdef _FFR_REPUTATION
00486        _Bool         mctx_spam;           /* is spam? */
00487 #endif /* _FFR_REPUTATION */
00488        dkim_policy_t mctx_pcode;          /* policy result code */
00489 #ifdef _FFR_ATPS
00490        int           mctx_atps;           /* ATPS */
00491 #endif /* _FFR_ATPS */
00492 #ifdef USE_LUA
00493        int           mctx_mresult;        /* SMFI status code */
00494 #endif /* USE_LUA */
00495        int           mctx_presult;        /* policy result */
00496        int           mctx_status;         /* status to report back */
00497        unsigned int  mctx_pflags;         /* policy flags */
00498        dkim_canon_t  mctx_hdrcanon;              /* header canonicalization */
00499        dkim_canon_t  mctx_bodycanon;             /* body canonicalization */
00500        dkim_alg_t    mctx_signalg;        /* signature algorithm */
00501 #ifdef USE_UNBOUND
00502        int           mctx_dnssec_key;     /* DNSSEC results for key */
00503        int           mctx_dnssec_policy;  /* DNSSEC results for policy */
00504 #endif /* USE_UNBOUND */
00505        int           mctx_queryalg;              /* query algorithm */
00506        int           mctx_hdrbytes;              /* header space allocated */
00507        struct dkimf_dstring * mctx_tmpstr;       /* temporary string */
00508        u_char *      mctx_jobid;          /* job ID */
00509        u_char *      mctx_laddr;          /* address triggering l= */
00510        DKIM *        mctx_dkimv;          /* verification handle */
00511 #ifdef _FFR_VBR
00512        VBR *         mctx_vbr;            /* VBR handle */
00513        char *        mctx_vbrinfo;        /* VBR-Info header field */
00514 #endif /* _FFR_VBR */
00515        struct Header *      mctx_hqhead;         /* header queue head */
00516        struct Header *      mctx_hqtail;         /* header queue tail */
00517        struct signreq * mctx_srhead;             /* signature request head */
00518        struct signreq * mctx_srtail;             /* signature request tail */
00519        struct addrlist * mctx_rcptlist;   /* recipient list */
00520        DKIM_PSTATE   * mctx_pstate;              /* policy state handle */
00521 #ifdef _FFR_STATSEXT
00522        struct statsext * mctx_statsext;   /* extension stats list */
00523 #endif /* _FFR_STATSEXT */
00524 #ifdef _FFR_LUA_GLOBALS
00525        struct lua_global * mctx_luaglobalh;      /* Lua global list */
00526        struct lua_global * mctx_luaglobalt;      /* Lua global list */
00527 #endif /* _FFR_LUA_GLOBALS */
00528 #ifdef _FFR_REPUTATION
00529        SHA_CTX              mctx_hash;           /* hash, for dup detection */
00530 #endif /* _FFR_REPUTATION */
00531        unsigned char mctx_envfrom[MAXADDRESS + 1];
00532                                           /* envelope sender */
00533        unsigned char mctx_domain[DKIM_MAXHOSTNAMELEN + 1];
00534                                           /* primary domain */
00535        unsigned char mctx_dkimar[DKIM_MAXHEADER + 1];
00536                                           /* DKIM Auth-Results content */
00537 };
00538 
00539 /*
00540 **  CONNCTX -- connection context, containing thread-specific data
00541 */
00542 
00543 typedef struct connctx * connctx;
00544 struct connctx
00545 {
00546        _Bool         cctx_milterv2;              /* milter v2 available */
00547        _Bool         cctx_noleadspc;             /* no leading spaces */
00548        char          cctx_host[DKIM_MAXHOSTNAMELEN + 1];
00549                                           /* hostname */
00550        struct sockaddr_storage     cctx_ip;      /* IP info */
00551        struct dkimf_config * cctx_config; /* configuration in use */
00552        struct msgctx *      cctx_msg;            /* message context */
00553 };
00554 
00555 /*
00556 **  LOOKUP -- lookup table
00557 */
00558 
00559 struct lookup
00560 {
00561        char *        str;
00562        int           code;
00563 };
00564 
00565 #define       HNDL_DEFAULT         0
00566 #define       HNDL_NOSIGNATURE     1
00567 #define       HNDL_BADSIGNATURE    2
00568 #define       HNDL_DNSERROR        3
00569 #define       HNDL_INTERNAL        4
00570 #define       HNDL_SECURITY        5
00571 #define       HNDL_NOKEY           6
00572 #define       HNDL_POLICYERROR     7
00573 #define       HNDL_REPERROR        8
00574 
00575 #define       DKIMF_MODE_SIGNER    0x01
00576 #define       DKIMF_MODE_VERIFIER  0x02
00577 #define       DKIMF_MODE_DEFAULT   (DKIMF_MODE_SIGNER|DKIMF_MODE_VERIFIER)
00578 
00579 #define       DKIMF_STATUS_GOOD    0
00580 #define       DKIMF_STATUS_BAD     1
00581 #define       DKIMF_STATUS_NOKEY   2
00582 #define       DKIMF_STATUS_REVOKED 3
00583 #define       DKIMF_STATUS_NOSIGNATURE 4
00584 #define       DKIMF_STATUS_BADFORMAT      5
00585 #define       DKIMF_STATUS_PARTIAL 6
00586 #define       DKIMF_STATUS_VERIFYERR      7
00587 #define       DKIMF_STATUS_UNKNOWN 8
00588 
00589 #define SIGMIN_BYTES        0
00590 #define SIGMIN_PERCENT             1
00591 #define SIGMIN_MAXADD              2
00592 
00593 #define       ADSPDENYSMTP         "550"
00594 #define       ADSPDENYESC          "5.7.1"
00595 #define       ADSPDENYTEXT         "rejected due to DKIM ADSP evaluation"
00596 
00597 #define       ADSPNXDOMAINSMTP     "550"
00598 #define       ADSPNXDOMAINESC             "5.7.1"
00599 #define       ADSPNXDOMAINTEXT     "sender domain does not exist"
00600 
00601 #ifdef _FFR_DKIM_REPUTATION
00602 # define REPDENYSMTP        "550"
00603 # define REPDENYESC         "5.7.1"
00604 # define REPDENYTXT         "rejected due to DKIM reputation evaluation"
00605 #endif /* _FFR_DKIM_REPUTATION */
00606 
00607 #ifdef _FFR_REPUTATION
00608 # define REPDENYSMTP        "450"
00609 # define REPDENYESC         "4.7.1"
00610 # define REPDENYTXT         "Message deferred for policy reasons"
00611 #endif /* _FFR_REPUTATION */
00612 
00613 #define       DELIMITER            "\001"
00614 
00615 struct lookup dkimf_adspactions[] =
00616 {
00617        { "continue",        SMFIS_CONTINUE },
00618        { "discard",         SMFIS_DISCARD },
00619        { "reject",          SMFIS_REJECT },
00620        { NULL,                     -1 },
00621 };
00622 
00623 struct lookup dkimf_params[] =
00624 {
00625        { "badsignature",    HNDL_BADSIGNATURE },
00626        { "default",         HNDL_DEFAULT },
00627        { "dnserror",        HNDL_DNSERROR },
00628        { "internal",        HNDL_INTERNAL },
00629        { "keynotfound",     HNDL_NOKEY },
00630        { "nosignature",     HNDL_NOSIGNATURE },
00631        { "policyerror",     HNDL_POLICYERROR },
00632 #ifdef _FFR_REPUTATION
00633        { "reputationerror", HNDL_REPERROR },
00634 #endif /* _FFR_REPUTATION */
00635        { "security",        HNDL_SECURITY },
00636        { NULL,                     -1 },
00637 };
00638 
00639 struct lookup dkimf_values[] =
00640 {
00641        { "a",               DKIMF_MILTER_ACCEPT },
00642        { "accept",          DKIMF_MILTER_ACCEPT },
00643        { "d",               DKIMF_MILTER_DISCARD },
00644        { "discard",         DKIMF_MILTER_DISCARD },
00645        { "q",               DKIMF_MILTER_QUARANTINE },
00646        { "quarantine",             DKIMF_MILTER_QUARANTINE },
00647        { "r",               DKIMF_MILTER_REJECT },
00648        { "reject",          DKIMF_MILTER_REJECT },
00649        { "t",               DKIMF_MILTER_TEMPFAIL },
00650        { "tempfail",        DKIMF_MILTER_TEMPFAIL },
00651        { NULL,                     -1 },
00652 };
00653 
00654 struct lookup dkimf_canon[] =
00655 {
00656        { "relaxed",         DKIM_CANON_RELAXED },
00657        { "simple",          DKIM_CANON_SIMPLE },
00658        { NULL,                     -1 },
00659 };
00660 
00661 struct lookup dkimf_policy[] =
00662 {
00663        { "unknown",         DKIM_POLICY_UNKNOWN },
00664        { "all",             DKIM_POLICY_ALL },
00665        { "discardable",     DKIM_POLICY_DISCARDABLE },
00666        { NULL,                     -1 },
00667 };
00668 
00669 struct lookup dkimf_sign[] =
00670 {
00671        { "rsa-sha1",        DKIM_SIGN_RSASHA1 },
00672        { "rsa-sha256",             DKIM_SIGN_RSASHA256 },
00673        { NULL,                     -1 },
00674 };
00675 
00676 struct lookup dkimf_atpshash[] =
00677 {
00678 #ifdef HAVE_SHA256
00679        { "sha256",          1 },
00680 #endif /* HAVE_SHA256 */
00681        { "sha1",            1 },
00682        { "none",            1 },
00683        { NULL,                     -1 },
00684 };
00685 
00686 struct lookup log_facilities[] =
00687 {
00688        { "auth",            LOG_AUTH },
00689        { "cron",            LOG_CRON },
00690        { "daemon",          LOG_DAEMON },
00691        { "kern",            LOG_KERN },
00692        { "lpr",             LOG_LPR },
00693        { "mail",            LOG_MAIL },
00694        { "news",            LOG_NEWS },
00695        { "security",        LOG_AUTH },       /* DEPRECATED */
00696        { "syslog",          LOG_SYSLOG },
00697        { "user",            LOG_USER },
00698        { "uucp",            LOG_UUCP },
00699        { "local0",          LOG_LOCAL0 },
00700        { "local1",          LOG_LOCAL1 },
00701        { "local2",          LOG_LOCAL2 },
00702        { "local3",          LOG_LOCAL3 },
00703        { "local4",          LOG_LOCAL4 },
00704        { "local5",          LOG_LOCAL5 },
00705        { "local6",          LOG_LOCAL6 },
00706        { "local7",          LOG_LOCAL7 },
00707        { NULL,                     -1 }
00708 };
00709 
00710 #ifdef USE_UNBOUND
00711 struct lookup dkimf_dnssec[] =
00712 {
00713        { "unknown",         DKIM_DNSSEC_UNKNOWN },
00714        { "bogus",           DKIM_DNSSEC_BOGUS },
00715        { "insecure",        DKIM_DNSSEC_INSECURE },
00716        { "secure",          DKIM_DNSSEC_SECURE },
00717        { NULL,                     -1 },
00718 };
00719 
00720 #define       DKIMF_KEYACTIONS_NONE       0
00721 #define       DKIMF_KEYACTIONS_NEUTRAL 1
00722 #define       DKIMF_KEYACTIONS_FAIL       2
00723 
00724 struct lookup dkimf_keyactions[] =
00725 {
00726        { "none",            DKIMF_KEYACTIONS_NONE },
00727        { "neutral",         DKIMF_KEYACTIONS_NEUTRAL },
00728        { "fail",            DKIMF_KEYACTIONS_FAIL },
00729        { NULL,                     -1 },
00730 };
00731 
00732 #define       DKIM_POLICYACTIONS_IGNORE   0
00733 #define DKIM_POLICYACTIONS_APPLY   1
00734 
00735 struct lookup dkimf_policyactions[] =
00736 {
00737        { "ignore",          DKIM_POLICYACTIONS_IGNORE },
00738        { "apply",           DKIM_POLICYACTIONS_APPLY },
00739        { NULL,                     -1 },
00740 };
00741 #endif /* USE_UNBOUND */
00742 
00743 /* PROTOTYPES */
00744 #ifdef LEAK_TRACKING
00745 void dkimf_debug_free __P((void *, char *, int));
00746 void *dkim_debug_malloc __P((size_t, char *, int));
00747 void *dkim_debug_realloc __P((void *, size_t, char *, int));
00748 
00749 # define free(x)     dkimf_debug_free((x), __FILE__, __LINE__)
00750 # define malloc(x)   dkimf_debug_malloc((x), __FILE__, __LINE__)
00751 # define realloc(x,y)       dkimf_debug_realloc((x), (y), __FILE__, __LINE__)
00752 #endif /* LEAK_TRACKING */
00753 
00754 sfsistat mlfi_abort __P((SMFICTX *));
00755 sfsistat mlfi_body __P((SMFICTX *, u_char *, size_t));
00756 sfsistat mlfi_close __P((SMFICTX *));
00757 sfsistat mlfi_connect __P((SMFICTX *, char *, _SOCK_ADDR *));
00758 sfsistat mlfi_envfrom __P((SMFICTX *, char **));
00759 sfsistat mlfi_envrcpt __P((SMFICTX *, char **));
00760 sfsistat mlfi_eoh __P((SMFICTX *));
00761 sfsistat mlfi_eom __P((SMFICTX *));
00762 sfsistat mlfi_header __P((SMFICTX *, char *, char *));
00763 sfsistat mlfi_negotiate __P((SMFICTX *, unsigned long, unsigned long,
00764                                         unsigned long, unsigned long,
00765                                         unsigned long *, unsigned long *,
00766                                         unsigned long *, unsigned long *));
00767 
00768 static int dkimf_add_signrequest __P((struct msgctx *, DKIMF_DB,
00769                                       char *, char *, ssize_t));
00770 sfsistat dkimf_addheader __P((SMFICTX *, char *, char *));
00771 sfsistat dkimf_addrcpt __P((SMFICTX *, char *));
00772 sfsistat dkimf_chgheader __P((SMFICTX *, char *, int, char *));
00773 static void dkimf_cleanup __P((SMFICTX *));
00774 static void dkimf_config_reload __P((void));
00775 sfsistat dkimf_delrcpt __P((SMFICTX *, char *));
00776 static Header dkimf_findheader __P((msgctx, char *, int));
00777 void *dkimf_getpriv __P((SMFICTX *));
00778 char * dkimf_getsymval __P((SMFICTX *, char *));
00779 sfsistat dkimf_insheader __P((SMFICTX *, int, char *, char *));
00780 static void dkimf_policyreport __P((connctx, struct dkimf_config *, char *));
00781 sfsistat dkimf_quarantine __P((SMFICTX *, char *));
00782 void dkimf_sendprogress __P((const void *));
00783 sfsistat dkimf_setpriv __P((SMFICTX *, void *));
00784 sfsistat dkimf_setreply __P((SMFICTX *, char *, char *, char *));
00785 static void dkimf_sigreport __P((connctx, struct dkimf_config *, char *));
00786 
00787 /* GLOBALS */
00788 _Bool dolog;                              /* logging? (exported) */
00789 _Bool reload;                             /* reload requested */
00790 _Bool no_i_whine;                         /* noted ${i} is undefined */
00791 _Bool quarantine;                         /* quarantine failures? */
00792 _Bool testmode;                                  /* test mode */
00793 #ifdef QUERY_CACHE
00794 _Bool querycache;                         /* local query cache */
00795 #endif /* QUERY_CACHE */
00796 _Bool die;                                /* global "die" flag */
00797 int diesig;                               /* signal to distribute */
00798 int thread_count;                         /* thread count */
00799 #ifdef QUERY_CACHE
00800 time_t cache_lastlog;                            /* last cache stats logged */
00801 #endif /* QUERY_CACHE */
00802 char *progname;                                  /* program name */
00803 char *sock;                               /* listening socket */
00804 char *conffile;                                  /* configuration file */
00805 struct dkimf_config *curconf;                    /* current configuration */
00806 #ifdef POPAUTH
00807 DKIMF_DB popdb;                                  /* POP auth DB */
00808 #endif /* POPAUTH */
00809 char reportcmd[BUFRSZ + 1];               /* reporting command */
00810 char reportaddr[MAXADDRESS + 1];          /* reporting address */
00811 char myhostname[DKIM_MAXHOSTNAMELEN + 1]; /* hostname */
00812 pthread_mutex_t conf_lock;                /* config lock */
00813 
00814 /* Other useful definitions */
00815 #define CRLF                "\r\n"        /* CRLF */
00816 
00817 /* MACROS */
00818 #define       JOBID(x)      ((x) == NULL ? JOBIDUNKNOWN : (char *) (x))
00819 #define       TRYFREE(x)    do { \
00820                             if ((x) != NULL) \
00821                             { \
00822                                    free(x); \
00823                                    (x) = NULL; \
00824                             } \
00825                      } while (0)
00826 #define       DKIMF_EOHMACROS      "i {daemon_name} {auth_type}"
00827 
00828 
00829 
00830 /*
00831 **  ==================================================================
00832 **  BEGIN private section
00833 */
00834 
00835 #ifndef HAVE_SMFI_INSHEADER
00836 /*
00837 **  SMFI_INSHEADER -- stub for smfi_insheader() which didn't exist before
00838 **                    sendmail 8.13.0
00839 **
00840 **  Parameters:
00841 **     ctx -- milter context
00842 **     idx -- insertion index
00843 **     hname -- header name
00844 **     hvalue -- header value
00845 **
00846 **  Return value:
00847 **     An sfsistat.
00848 */
00849 
00850 sfsistat 
00851 smfi_insheader(SMFICTX *ctx, int idx, char *hname, char *hvalue)
00852 {
00853        assert(ctx != NULL);
00854        assert(hname != NULL);
00855        assert(hvalue != NULL);
00856 
00857        return smfi_addheader(ctx, hname, hvalue);
00858 }
00859 #endif /* ! HAVE_SMFI_INSHEADER */
00860 
00861 /*
00862 **  DKIMF_GETPRIV -- wrapper for smfi_getpriv()
00863 **
00864 **  Parameters:
00865 **     ctx -- milter (or test) context
00866 **
00867 **  Return value:
00868 **     The stored private pointer, or NULL.
00869 */
00870 
00871 void *
00872 dkimf_getpriv(SMFICTX *ctx)
00873 {
00874        assert(ctx != NULL);
00875 
00876        if (testmode)
00877               return dkimf_test_getpriv((void *) ctx);
00878        else
00879               return smfi_getpriv(ctx);
00880 }
00881 
00882 /*
00883 **  DKIMF_SETPRIV -- wrapper for smfi_setpriv()
00884 **
00885 **  Parameters:
00886 **     ctx -- milter (or test) context
00887 **
00888 **  Return value:
00889 **     An sfsistat.
00890 */
00891 
00892 sfsistat
00893 dkimf_setpriv(SMFICTX *ctx, void *ptr)
00894 {
00895        assert(ctx != NULL);
00896 
00897        if (testmode)
00898               return dkimf_test_setpriv((void *) ctx, ptr);
00899        else
00900               return smfi_setpriv(ctx, ptr);
00901 }
00902 
00903 /*
00904 **  DKIMF_INSHEADER -- wrapper for smfi_insheader()
00905 **
00906 **  Parameters:
00907 **     ctx -- milter (or test) context
00908 **     idx -- index at which to insert
00909 **     hname -- header name
00910 **     hvalue -- header value
00911 **
00912 **  Return value:
00913 **     An sfsistat.
00914 */
00915 
00916 sfsistat
00917 dkimf_insheader(SMFICTX *ctx, int idx, char *hname, char *hvalue)
00918 {
00919        assert(ctx != NULL);
00920        assert(hname != NULL);
00921        assert(hvalue != NULL);
00922 
00923        if (testmode)
00924               return dkimf_test_insheader(ctx, idx, hname, hvalue);
00925        else
00926 #ifdef HAVE_SMFI_INSHEADER
00927               return smfi_insheader(ctx, idx, hname, hvalue);
00928 #else /* HAVE_SMFI_INSHEADER */
00929               return smfi_addheader(ctx, hname, hvalue);
00930 #endif /* HAVE_SMFI_INSHEADER */
00931 }
00932 
00933 /*
00934 **  DKIMF_CHGHEADER -- wrapper for smfi_chgheader()
00935 **
00936 **  Parameters:
00937 **     ctx -- milter (or test) context
00938 **     hname -- header name
00939 **     idx -- index of header to be changed
00940 **     hvalue -- header value
00941 **
00942 **  Return value:
00943 **     An sfsistat.
00944 */
00945 
00946 sfsistat
00947 dkimf_chgheader(SMFICTX *ctx, char *hname, int idx, char *hvalue)
00948 {
00949        assert(ctx != NULL);
00950        assert(hname != NULL);
00951 
00952        if (testmode)
00953               return dkimf_test_chgheader(ctx, hname, idx, hvalue);
00954        else
00955               return smfi_chgheader(ctx, hname, idx, hvalue);
00956 }
00957 
00958 /*
00959 **  DKIMF_QUARANTINE -- wrapper for smfi_quarantine()
00960 **
00961 **  Parameters:
00962 **     ctx -- milter (or test) context
00963 **     reason -- quarantine reason
00964 **
00965 **  Return value:
00966 **     An sfsistat.
00967 */
00968 
00969 sfsistat
00970 dkimf_quarantine(SMFICTX *ctx, char *reason)
00971 {
00972        assert(ctx != NULL);
00973 
00974        if (testmode)
00975               return dkimf_test_quarantine(ctx, reason);
00976 #ifdef SMFIF_QUARANTINE
00977        else
00978               return smfi_quarantine(ctx, reason);
00979 #endif /* SMFIF_QUARANTINE */
00980 }
00981 
00982 /*
00983 **  DKIMF_ADDHEADER -- wrapper for smfi_addheader()
00984 **
00985 **  Parameters:
00986 **     ctx -- milter (or test) context
00987 **     hname -- header name
00988 **     hvalue -- header value
00989 **
00990 **  Return value:
00991 **     An sfsistat.
00992 */
00993 
00994 sfsistat
00995 dkimf_addheader(SMFICTX *ctx, char *hname, char *hvalue)
00996 {
00997        assert(ctx != NULL);
00998        assert(hname != NULL);
00999        assert(hvalue != NULL);
01000 
01001        if (testmode)
01002               return dkimf_test_addheader(ctx, hname, hvalue);
01003        else
01004               return smfi_addheader(ctx, hname, hvalue);
01005 }
01006 
01007 /*
01008 **  DKIMF_ADDRCPT -- wrapper for smfi_addrcpt()
01009 **
01010 **  Parameters:
01011 **     ctx -- milter (or test) context
01012 **     addr -- address to add
01013 **
01014 **  Return value:
01015 **     An sfsistat.
01016 */
01017 
01018 sfsistat
01019 dkimf_addrcpt(SMFICTX *ctx, char *addr)
01020 {
01021        assert(ctx != NULL);
01022        assert(addr != NULL);
01023 
01024        if (testmode)
01025               return dkimf_test_addrcpt(ctx, addr);
01026        else
01027               return smfi_addrcpt(ctx, addr);
01028 }
01029 
01030 /*
01031 **  DKIMF_DELRCPT -- wrapper for smfi_delrcpt()
01032 **
01033 **  Parameters:
01034 **     ctx -- milter (or test) context
01035 **     addr -- address to delete
01036 **
01037 **  Return value:
01038 **     An sfsistat.
01039 */
01040 
01041 sfsistat
01042 dkimf_delrcpt(SMFICTX *ctx, char *addr)
01043 {
01044        assert(ctx != NULL);
01045        assert(addr != NULL);
01046 
01047        if (testmode)
01048               return dkimf_test_delrcpt(ctx, addr);
01049        else
01050               return smfi_delrcpt(ctx, addr);
01051 }
01052 
01053 /*
01054 **  DKIMF_SETREPLY -- wrapper for smfi_setreply()
01055 **
01056 **  Parameters:
01057 **     ctx -- milter (or test) context
01058 **     rcode -- SMTP reply code
01059 **     xcode -- SMTP enhanced status code
01060 **     replytxt -- reply text
01061 **
01062 **  Return value:
01063 **     An sfsistat.
01064 */
01065 
01066 sfsistat
01067 dkimf_setreply(SMFICTX *ctx, char *rcode, char *xcode, char *replytxt)
01068 {
01069        assert(ctx != NULL);
01070 
01071        if (testmode)
01072               return dkimf_test_setreply(ctx, rcode, xcode, replytxt);
01073        else
01074               return smfi_setreply(ctx, rcode, xcode, replytxt);
01075 }
01076 
01077 /*
01078 **  DKIMF_GETSYMVAL -- wrapper for smfi_getsymval()
01079 **
01080 **  Parameters:
01081 **     ctx -- milter (or test) context
01082 **     sym -- symbol to retrieve
01083 **
01084 **  Return value:
01085 **     Pointer to the value of the requested MTA symbol.
01086 */
01087 
01088 char *
01089 dkimf_getsymval(SMFICTX *ctx, char *sym)
01090 {
01091        assert(ctx != NULL);
01092        assert(sym != NULL);
01093 
01094        if (testmode)
01095               return dkimf_test_getsymval(ctx, sym);
01096        else
01097               return smfi_getsymval(ctx, sym);
01098 }
01099 
01100 #ifdef USE_LUA
01101 /*
01102 **  LUA ACCESSOR FUNCTIONS
01103 **
01104 **  These are the C sides of the utility functions that will be made available
01105 **  to users via Lua to write their own policy scripts.
01106 **
01107 **  NAMES:
01108 **     Should all start "dkimf_xs_" (for DKIM filter accessors)
01109 **
01110 **  PARAMETERS:
01111 **     Should all accept nothing more than a single Lua state handle.
01112 **     Lua accessor and utility functions are used to pull parameters off
01113 **     the stack.
01114 **
01115 **  RETURN VALUES:
01116 **     Should all return the number of things they want to return via
01117 **     the Lua stack.  Generally accessors return one thing, and utility
01118 **     functions either return a result or a Lua "nil", which means
01119 **     at least one thing is always returned.
01120 **
01121 **  STACK:
01122 **     All functions should first evaluate the stack to see that it's what
01123 **     they expect in terms of number and types of elements.  The first
01124 **     stack item should always be expected to be a "light user data"
01125 **     (handle pointer) to a (SMFICTX).  If there are no errors,
01126 **     collect all the values and pop them.  The context pointer may come in
01127 **     NULL, in which case the script is being called during configuration
01128 **     verification; if so, return an appropriate dummy value from your
01129 **     function, if applicable, such as the name of the function or 0 or
01130 **     something matching what the script would expect back from
01131 **     the function such that the rest of the test will complete.
01132 */
01133 
01134 # ifdef _FFR_LUA_GLOBALS
01135 /*
01136 **  DKIMF_IMPORT_GLOBALS -- add globals to a Lua state
01137 **
01138 **  Parameters:
01139 **     ctx -- filter context
01140 **     l -- Lua state
01141 **
01142 **  Return value:
01143 **     None.
01144 */
01145 
01146 void
01147 dkimf_import_globals(void *p, lua_State *l)
01148 {
01149        SMFICTX *ctx;
01150        struct connctx *cc;
01151        struct msgctx *mctx;
01152        struct lua_global *lg;
01153 
01154        if (p == NULL)
01155               return;
01156 
01157        ctx = (SMFICTX *) p;
01158        cc = (struct connctx *) dkimf_getpriv(ctx);
01159        mctx = cc->cctx_msg;
01160 
01161        lg = mctx->mctx_luaglobalh;
01162        while (lg != NULL)
01163        {
01164               switch (lg->lg_type)
01165               {
01166                 case LUA_TNIL:
01167                      lua_pushnil(l);
01168                      lua_setglobal(l, lg->lg_name);
01169                      break;
01170 
01171                 case LUA_TNUMBER:
01172                 {
01173                      lua_Number x;
01174 
01175                      memcpy(&x, lg->lg_value, sizeof x);
01176                      lua_pushnumber(l, x);
01177                      lua_setglobal(l, lg->lg_name);
01178                      break;
01179                 }
01180 
01181                 case LUA_TBOOLEAN:
01182                      lua_pushboolean(l, (long) lg->lg_value);
01183                      lua_setglobal(l, lg->lg_name);
01184                      break;
01185 
01186                 case LUA_TSTRING:
01187                      lua_pushstring(l, (char *) lg->lg_value);
01188                      lua_setglobal(l, lg->lg_name);
01189                      break;
01190 
01191                 default:
01192                      assert(0);
01193               }
01194 
01195               lg = lg->lg_next;
01196        }
01197 }
01198 
01199 /*
01200 **  DKIMF_XS_EXPORT -- export a global for use in later scripts
01201 **
01202 **  Parameters:
01203 **     l -- Lua state
01204 **
01205 **  Return value:
01206 **     Number of stack items pushed.
01207 */
01208 
01209 int
01210 dkimf_xs_export(lua_State *l)
01211 {
01212        int c;
01213        int top;
01214        int type;
01215        struct lua_global *lg;
01216        SMFICTX *ctx;
01217        struct connctx *cc;
01218        struct msgctx *msg;
01219 
01220        top = lua_gettop(l);
01221 
01222        if (top < 3 || top % 2 != 1)
01223        {
01224               lua_pushstring(l,
01225                              "odkim.export(): incorrect argument count");
01226               lua_error(l);
01227        }
01228 
01229        for (c = 2; c < top; c += 2)
01230        {
01231               if (!lua_isstring(l, c) ||
01232                   (!lua_isnil(l, c + 1) &&
01233                    !lua_isstring(l, c + 1) &&
01234                    !lua_isnumber(l, c + 1) &&
01235                    !lua_isboolean(l, c + 1)))
01236               {
01237                      lua_pushstring(l,
01238                                     "odkim.export(): incorrect argument type");
01239                      lua_error(l);
01240               }
01241        }
01242 
01243        ctx = (SMFICTX *) lua_touserdata(l, 1);
01244        if (ctx == NULL)
01245        {
01246               lua_pop(l, top);
01247               return 0;
01248        }
01249        cc = (struct connctx *) dkimf_getpriv(ctx);
01250        msg = cc->cctx_msg;
01251 
01252        for (c = 2; c < top; c += 2)
01253        {
01254               type = lua_type(l, c + 1);
01255 
01256               if (type != LUA_TNIL &&
01257                   type != LUA_TNUMBER &&
01258                   type != LUA_TBOOLEAN &&
01259                   type != LUA_TSTRING)
01260                      continue;
01261 
01262               lg = (struct lua_global *) malloc(sizeof *lg);
01263               if (lg != NULL)
01264               {
01265                      lg->lg_name = strdup(lua_tostring(l, c));
01266                      if (lg->lg_name == NULL)
01267                      {
01268                             free(lg);
01269                             continue;
01270                      }
01271 
01272                      lg->lg_type = type;
01273 
01274                      lg->lg_next = NULL;
01275 
01276                      if (msg->mctx_luaglobalh == NULL)
01277                             msg->mctx_luaglobalh = lg;
01278                      else
01279                             msg->mctx_luaglobalt->lg_next = lg;
01280 
01281                      msg->mctx_luaglobalt = lg;
01282 
01283                      switch (lg->lg_type)
01284                      {
01285                        case LUA_TNIL:
01286                             lg->lg_value = NULL;
01287                             break;
01288 
01289                        case LUA_TNUMBER:
01290                             lg->lg_value = malloc(sizeof(lua_Number));
01291                             if (lg->lg_value != NULL)
01292                             {
01293                                    lua_Number x;
01294 
01295                                    x = lua_tonumber(l, c + 1);
01296                                    memcpy(lg->lg_value, &x, sizeof x);
01297                             }
01298                             break;
01299 
01300                        case LUA_TBOOLEAN:
01301                             if (lua_toboolean(l, c + 1))
01302                                    lg->lg_value = (void *) 1;
01303                             else
01304                                    lg->lg_value = (void *) 0;
01305                             break;
01306 
01307                        case LUA_TSTRING:
01308                             lg->lg_value = strdup(lua_tostring(l, c + 1));
01309                             break;
01310                      }
01311               }
01312        }
01313 
01314        lua_pop(l, top);
01315 
01316        return 0;
01317 }
01318 # endif /* _FFR_LUA_GLOBALS */
01319 
01320 # ifdef _FFR_RBL
01321 /*
01322 **  DKIMF_XS_RBLCHECK -- do an RBL query
01323 **
01324 **  Parameters:
01325 **     l -- Lua state
01326 **
01327 **  Return value:
01328 **     Number of stack items pushed.
01329 */
01330 
01331 int
01332 dkimf_xs_rblcheck(lua_State *l)
01333 {
01334        _Bool found = FALSE;
01335        RBL_STAT status;
01336        uint32_t res;
01337        double timeout = -1.;
01338        double i;
01339        const char *query;
01340        const char *qroot = NULL;
01341        void *qh;
01342        RBL *rbl;
01343        SMFICTX *ctx;
01344        struct connctx *cc = NULL;
01345        struct timeval to;
01346 
01347        if (lua_gettop(l) < 3 || lua_gettop(l) > 4)
01348        {
01349               lua_pushstring(l,
01350                              "odkim.rbl_check(): incorrect argument count");
01351               lua_error(l);
01352        }
01353        else if (!lua_isuserdata(l, 1) ||
01354                 !lua_isstring(l, 2) ||
01355                 !lua_isstring(l, 3) ||
01356                 (lua_gettop(l) == 4 && !lua_isnumber(l, 4)))
01357        {
01358               lua_pushstring(l,
01359                              "odkim.rbl_check(): incorrect argument type");
01360               lua_error(l);
01361        }
01362 
01363        ctx = (SMFICTX *) lua_touserdata(l, 1);
01364        if (ctx != NULL)
01365               cc = (struct connctx *) dkimf_getpriv(ctx);
01366        query = lua_tostring(l, 2);
01367        qroot = lua_tostring(l, 3);
01368        if (lua_gettop(l) == 4)
01369               timeout = lua_tonumber(l, 4);
01370        lua_pop(l, lua_gettop(l));
01371 
01372 #  ifdef USE_ARLIB
01373        if (cc == NULL || cc->cctx_config->conf_arlib == NULL)
01374               return 0;
01375 #  endif /* USE_ARLIB */
01376 
01377 #  ifdef USE_UNBOUND
01378        if (cc == NULL || cc->cctx_config->conf_unbound == NULL)
01379               return 0;
01380 #  endif /* USE_UNBOUND */
01381 
01382        rbl = rbl_init(NULL, NULL, NULL);
01383        if (rbl == NULL)
01384        {
01385               lua_pushstring(l,
01386                              "odkim.rbl_check(): can't create RBL handle");
01387               lua_error(l);
01388        }
01389 
01390 #  ifdef USE_ARLIB
01391        dkimf_rbl_arlib_setup(rbl, cc->cctx_config->conf_arlib);
01392 #  endif /* USE_ARLIB */
01393 
01394 #  ifdef USE_UNBOUND
01395        dkimf_rbl_unbound_setup(rbl, cc->cctx_config->conf_unbound);
01396 #  endif /* USE_UNBOUND */
01397 
01398        rbl_setdomain(rbl, (u_char *) qroot);
01399 
01400        status = rbl_query_start(rbl, (u_char *) query, &qh);
01401        if (status != RBL_STAT_OK)
01402        {
01403               rbl_close(rbl);
01404               lua_pushstring(l,
01405                              "odkim.rbl_check(): RBL query failed");
01406               lua_error(l);
01407        }
01408 
01409        to.tv_usec = modf(timeout, &i);
01410        to.tv_sec = (u_int) i;
01411 
01412        status = rbl_query_check(rbl, qh, timeout == -1. ? NULL : &to, &res);
01413 
01414        if (status != RBL_STAT_NOTFOUND &&
01415            status != RBL_STAT_NOREPLY &&
01416            status != RBL_STAT_FOUND)
01417               lua_pushstring(l, rbl_geterror(rbl));
01418        else if (status == RBL_STAT_FOUND)
01419               found = TRUE;
01420 
01421        rbl_close(rbl);
01422 
01423        if (status != RBL_STAT_NOTFOUND &&
01424            status != RBL_STAT_NOREPLY &&
01425            status != RBL_STAT_FOUND)
01426        {
01427               return 1;
01428        }
01429        else if (found)
01430        {
01431               lua_pushnumber(l, res >> 24);
01432               lua_pushnumber(l, (res >> 16) & 0xff);
01433               lua_pushnumber(l, (res >> 8) & 0xff);
01434               lua_pushnumber(l, res & 0xff);
01435               return 4;
01436        }
01437        else
01438        {
01439               return 0;
01440        }
01441 }
01442 # endif /* _FFR_RBL */
01443 
01444 /*
01445 **  DKIMF_XS_XTAG -- add an extension tag
01446 **
01447 **  Parameters:
01448 **     l -- Lua state
01449 **
01450 **  Return value:
01451 **     Number of stack items pushed.
01452 */
01453 
01454 int
01455 dkimf_xs_xtag(lua_State *l)
01456 {
01457        SMFICTX *ctx;
01458        const char *tag = NULL;
01459        const char *value = NULL;
01460 
01461        if (lua_gettop(l) != 3)
01462        {
01463               lua_pushstring(l,
01464                              "odkim.xtag(): incorrect argument count");
01465               lua_error(l);
01466        }
01467        else if (!lua_isuserdata(l, 1) ||
01468                 !lua_isstring(l, 2) ||
01469                 !lua_isstring(l, 3))
01470        {
01471               lua_pushstring(l,
01472                              "odkim.xtag(): incorrect argument type");
01473               lua_error(l);
01474        }
01475 
01476        ctx = (SMFICTX *) lua_touserdata(l, 1);
01477        tag = lua_tostring(l, 2);
01478        value = lua_tostring(l, 3);
01479        lua_pop(l, 3);
01480 
01481        if (ctx != NULL)
01482        {
01483               int n = 0;
01484               int status;
01485               struct connctx *cc;
01486               struct msgctx *dfc;
01487               struct signreq *sr;
01488 
01489               cc = (struct connctx *) dkimf_getpriv(ctx);
01490               dfc = cc->cctx_msg;
01491 
01492               for (sr = dfc->mctx_srhead; sr != NULL; sr = sr->srq_next)
01493               {
01494                      status = dkim_add_xtag(sr->srq_dkim, tag, value);
01495                      if (status != DKIM_STAT_OK)
01496                      {
01497                             lua_pushnumber(l, -1);
01498                             return 1;
01499                      }
01500 
01501                      n++;
01502               }
01503 
01504               lua_pushnumber(l, n);
01505               return 1;
01506        }
01507        else
01508        {
01509               lua_pushnumber(l, 0);
01510               return 1;
01511        }
01512 }
01513 
01514 /*
01515 **  DKIMF_XS_PARSEFIELD -- parse an address field into its components
01516 **
01517 **  Parameters:
01518 **     l -- Lua state
01519 **
01520 **  Return value:
01521 **     Number of stack items pushed.
01522 */
01523 
01524 int
01525 dkimf_xs_parsefield(lua_State *l)
01526 {
01527        unsigned char *user = NULL;
01528        unsigned char *domain = NULL;
01529        unsigned char field[DKIM_MAXHEADER + 1];
01530 
01531        if (lua_gettop(l) != 1)
01532        {
01533               lua_pushstring(l,
01534                              "odkim.parse_field(): incorrect argument count");
01535               lua_error(l);
01536        }
01537        else if (!lua_isstring(l, 1))
01538        {
01539               lua_pushstring(l,
01540                              "odkim.parse_field(): incorrect argument type");
01541               lua_error(l);
01542        }
01543 
01544        dkim_strlcpy(field, lua_tostring(l, 1), sizeof field);
01545        lua_pop(l, 1);
01546 
01547        if (field == NULL)
01548        {
01549               lua_pushnil(l);
01550               return 1;
01551        }
01552        else if (dkim_mail_parse(field, &user, &domain) != 0 ||
01553                 user == NULL || domain == NULL)
01554        {
01555               lua_pushnil(l);
01556               return 1;
01557        }
01558        else
01559        {
01560               lua_pushstring(l, user);
01561               lua_pushstring(l, domain);
01562               return 2;
01563        }
01564 }
01565 
01566 /*
01567 **  DKIMF_XS_LOG -- log a string
01568 **
01569 **  Parameters:
01570 **     l -- Lua state
01571 **
01572 **  Return value:
01573 **     Number of stack items pushed.
01574 */
01575 
01576 int
01577 dkimf_xs_log(lua_State *l)
01578 {
01579        SMFICTX *ctx;
01580        const char *logstring;
01581 
01582        if (lua_gettop(l) != 2)
01583        {
01584               lua_pushstring(l, "odkim.log(): incorrect argument count");
01585               lua_error(l);
01586        }
01587        else if (!lua_islightuserdata(l, 1) ||
01588                 !lua_isstring(l, 2))
01589        {
01590               lua_pushstring(l, "odkim.log(): incorrect argument type");
01591               lua_error(l);
01592        }
01593 
01594        ctx = (SMFICTX *) lua_touserdata(l, 1);
01595        logstring = lua_tostring(l, 2);
01596        lua_pop(l, 2);
01597 
01598        if (ctx != NULL)
01599        {
01600               struct connctx *cc;
01601 
01602               cc = (struct connctx *) dkimf_getpriv(ctx);
01603               if (cc->cctx_config->conf_dolog)
01604                      syslog(LOG_INFO, "%s", logstring);
01605        }
01606 
01607        lua_pushnil(l);
01608 
01609        return 1;
01610 }
01611 
01612 /*
01613 **  DKIMF_XS_FROMDOMAIN -- retrieve From: domain
01614 **
01615 **  Parameters:
01616 **     l -- Lua state
01617 **
01618 **  Return value:
01619 **     Number of stack items pushed.
01620 */
01621 
01622 int
01623 dkimf_xs_fromdomain(lua_State *l)
01624 {
01625        SMFICTX *ctx;
01626        struct connctx *cc;
01627        struct msgctx *dfc;
01628 
01629        assert(l != NULL);
01630 
01631        if (lua_gettop(l) != 1)
01632        {
01633               lua_pushstring(l,
01634                              "odkim.get_fromdomain(): incorrect argument count");
01635               lua_error(l);
01636        }
01637        else if (!lua_islightuserdata(l, 1))
01638        {
01639               lua_pushstring(l,
01640                              "odkim.get_fromdomain(): incorrect argument type");
01641               lua_error(l);
01642        }
01643 
01644        ctx = (SMFICTX *) lua_touserdata(l, 1);
01645        lua_pop(l, 1);
01646 
01647        if (ctx == NULL)
01648        {
01649               lua_pushstring(l, "dkimf_xs_fromdomain");
01650        }
01651        else
01652        {
01653               cc = (struct connctx *) dkimf_getpriv(ctx);
01654               dfc = cc->cctx_msg;
01655               lua_pushstring(l, (char *) dfc->mctx_domain);
01656        }
01657 
01658        return 1;
01659 }
01660 
01661 /*
01662 **  DKIMF_XS_CLIENTHOST -- retrieve client hostname
01663 **
01664 **  Parameters:
01665 **     l -- Lua state
01666 **
01667 **  Return value:
01668 **     Number of stack items pushed.
01669 */
01670 
01671 int
01672 dkimf_xs_clienthost(lua_State *l)
01673 {
01674        SMFICTX *ctx;
01675        struct connctx *cc;
01676 
01677        assert(l != NULL);
01678 
01679        if (lua_gettop(l) != 1)
01680        {
01681               lua_pushstring(l,
01682                              "odkim.get_clienthost(): incorrect argument count");
01683               lua_error(l);
01684        }
01685        else if (!lua_islightuserdata(l, 1))
01686        {
01687               lua_pushstring(l,
01688                              "odkim.get_clienthost(): incorrect argument type");
01689               lua_error(l);
01690        }
01691 
01692        ctx = (SMFICTX *) lua_touserdata(l, 1);
01693        lua_pop(l, 1);
01694 
01695        if (ctx == NULL)
01696        {
01697               lua_pushstring(l, "dkimf_xs_clienthost");
01698        }
01699        else
01700        {
01701               cc = (struct connctx *) dkimf_getpriv(ctx);
01702 
01703               lua_pushstring(l, cc->cctx_host);
01704        }
01705 
01706        return 1;
01707 }
01708 
01709 /*
01710 **  DKIMF_XS_CLIENTIP -- retrieve client IP address
01711 **
01712 **  Parameters:
01713 **     l -- Lua state
01714 **
01715 **  Return value:
01716 **     Number of stack items pushed.
01717 */
01718 
01719 int
01720 dkimf_xs_clientip(lua_State *l)
01721 {
01722        SMFICTX *ctx;
01723        struct connctx *cc;
01724 
01725        assert(l != NULL);
01726 
01727        if (lua_gettop(l) != 1)
01728        {
01729               lua_pushstring(l,
01730                              "odkim.get_clientip(): incorrect argument count");
01731               lua_error(l);
01732        }
01733        else if (!lua_islightuserdata(l, 1))
01734        {
01735               lua_pushstring(l,
01736                              "odkim.get_clientip(): incorrect argument type");
01737               lua_error(l);
01738        }
01739 
01740        ctx = (SMFICTX *) lua_touserdata(l, 1);
01741        lua_pop(l, 1);
01742 
01743        if (ctx == NULL)
01744        {
01745               lua_pushstring(l, "dkimf_xs_clientip");
01746        }
01747        else
01748        {
01749               char ipbuf[BUFRSZ + 1];
01750 
01751               memset(ipbuf, '\0', sizeof ipbuf);
01752 
01753               cc = (struct connctx *) dkimf_getpriv(ctx);
01754 
01755 #ifdef AF_INET6
01756               if (cc->cctx_ip.ss_family == AF_INET6)
01757               {
01758                      struct sockaddr_in6 *sa;
01759 
01760                      sa = (struct sockaddr_in6 *) &cc->cctx_ip;
01761 
01762                      if (inet_ntop(AF_INET6, &sa->sin6_addr,
01763                                    ipbuf, sizeof ipbuf) == NULL)
01764                      {
01765                             lua_pushnil(l);
01766                      }
01767                      else
01768                      {
01769                             lua_pushstring(l, ipbuf);
01770                      }
01771               }
01772               else
01773 #endif /* AF_INET6 */
01774 #ifdef AF_INET
01775               if (cc->cctx_ip.ss_family == AF_INET)
01776               {
01777                      struct sockaddr_in *sa;
01778 
01779                      sa = (struct sockaddr_in *) &cc->cctx_ip;
01780 
01781                      if (inet_ntop(AF_INET, &sa->sin_addr,
01782                                    ipbuf, sizeof ipbuf) == NULL)
01783                      {
01784                             lua_pushnil(l);
01785                      }
01786                      else
01787                      {
01788                             lua_pushstring(l, ipbuf);
01789                      }
01790               }
01791               else
01792 #endif /* AF_INET */
01793               {
01794                      lua_pushnil(l);
01795               }
01796        }
01797 
01798        return 1;
01799 }
01800 
01801 #ifdef _FFR_REPUTATION
01802 /*
01803 **  DKIMF_XS_SPAM -- tag message as spam
01804 **
01805 **  Parameters:
01806 **     l -- Lua state
01807 **
01808 **  Return value:
01809 **     Number of stack items pushed.
01810 */
01811 
01812 int
01813 dkimf_xs_spam(lua_State *l)
01814 {
01815        SMFICTX *ctx;
01816        const char *keyname = NULL;
01817        const char *ident = NULL;
01818        struct connctx *cc;
01819        struct msgctx *dfc;
01820        struct dkimf_config *conf;
01821 
01822        assert(l != NULL);
01823 
01824        if (lua_gettop(l) != 1)
01825        {
01826               lua_pushstring(l, "odkim.spam(): incorrect argument count");
01827               lua_error(l);
01828        }
01829        else if (!lua_islightuserdata(l, 1))
01830        {
01831               lua_pushstring(l, "odkim.spam(): incorrect argument type");
01832               lua_error(l);
01833        }
01834 
01835        ctx = (SMFICTX *) lua_touserdata(l, 1);
01836        if (ctx != NULL)
01837        {
01838               cc = (struct connctx *) dkimf_getpriv(ctx);
01839               dfc = cc->cctx_msg;
01840 
01841               dfc->mctx_spam = TRUE;
01842        }
01843 
01844        lua_pop(l, 1);
01845 
01846        return 0;
01847 }
01848 #endif /* _FFR_REPUTATION */
01849 
01850 /*
01851 **  DKIMF_XS_REQUESTSIG -- request a signature
01852 **
01853 **  Parameters:
01854 **     l -- Lua state
01855 **
01856 **  Return value:
01857 **     Number of stack items pushed.
01858 */
01859 
01860 int
01861 dkimf_xs_requestsig(lua_State *l)
01862 {
01863        int top;
01864        ssize_t signlen = (ssize_t) -1;
01865        SMFICTX *ctx;
01866        const char *keyname = NULL;
01867        const char *ident = NULL;
01868        struct connctx *cc;
01869        struct msgctx *dfc;
01870        struct dkimf_config *conf;
01871 
01872        assert(l != NULL);
01873 
01874        top = lua_gettop(l);
01875 
01876        if (top == 0 && top > 4)
01877        {
01878               lua_pushstring(l, "odkim.sign(): incorrect argument count");
01879               lua_error(l);
01880        }
01881        else if (!lua_islightuserdata(l, 1) ||
01882                 (top > 1 && !lua_isstring(l, 2)) ||
01883                 (top > 2 && !lua_isstring(l, 3) && !lua_isnumber(l, 3)) ||
01884                 (top > 3 && !lua_isstring(l, 4) && !lua_isnumber(l, 4)))
01885        {
01886               lua_pushstring(l, "odkim.sign(): incorrect argument type");
01887               lua_error(l);
01888        }
01889 
01890        ctx = (SMFICTX *) lua_touserdata(l, 1);
01891        if (ctx != NULL)
01892        {
01893               int c;
01894 
01895               cc = (struct connctx *) dkimf_getpriv(ctx);
01896               dfc = cc->cctx_msg;
01897               conf = cc->cctx_config;
01898 
01899               for (c = 2; c <= top; c++)
01900               {
01901                      if (c == 2)
01902                      {
01903                             keyname = lua_tostring(l, 2);
01904                      }
01905                      else if (lua_type(l, c) == LUA_TNUMBER)
01906                      {
01907                             if (signlen != (ssize_t) -1)
01908                             {
01909                                    lua_pushstring(l,
01910                                                   "odkim.sign(): incorrect argument type");
01911                                    lua_error(l);
01912                             }
01913                             signlen = (ssize_t) lua_tonumber(l, c);
01914                      }
01915                      else
01916                      {
01917                             if (ident != NULL)
01918                             {
01919                                    lua_pushstring(l,
01920                                                   "odkim.sign(): incorrect argument type");
01921                                    lua_error(l);
01922                             }
01923                             ident = lua_tostring(l, c);
01924                      }
01925               }
01926        }
01927 
01928        lua_pop(l, top);
01929 
01930        if (ident != NULL && ident[0] == '\0')
01931               ident = NULL;
01932 
01933        if (ctx == NULL)
01934        {
01935               lua_pushnumber(l, 0);
01936 
01937               return 1;
01938        }
01939 
01940        if (conf->conf_keytabledb == NULL && keyname != NULL)
01941        {
01942               lua_pushstring(l, "odkim.sign(): request requires KeyTable");
01943               lua_error(l);
01944        }
01945 
01946        /* try to get the key */
01947        if (keyname != NULL)
01948        {
01949               switch (dkimf_add_signrequest(dfc, conf->conf_keytabledb,
01950                                             (char *) keyname,
01951                                             (char *) ident,
01952                                             signlen))
01953               {
01954                 case 3:
01955                      if (conf->conf_dolog)
01956                      {
01957                             syslog(LOG_ERR,
01958                                    "key '%s' could not be applied",
01959                                    keyname);
01960                      }
01961                      lua_pushnumber(l, 0);
01962                      return 1;
01963 
01964                 case 2:
01965                      if (conf->conf_dolog)
01966                      {
01967                             syslog(LOG_ERR, "key '%s' could not be loaded",
01968                                    keyname);
01969                      }
01970                      lua_pushnumber(l, 0);
01971                      return 1;
01972 
01973                 case 1:
01974                      if (conf->conf_dolog)
01975                             syslog(LOG_ERR, "key '%s' not found", keyname);
01976                      lua_pushnumber(l, 0);
01977                      return 1;
01978 
01979                 case -1:
01980                      if (conf->conf_dolog)
01981                      {
01982                             syslog(LOG_ERR, "error requesting key '%s'",
01983                                    keyname);
01984                      }
01985                      lua_pushnumber(l, 0);
01986                      return 1;
01987               }
01988        }
01989        else if (dkimf_add_signrequest(dfc, NULL, NULL, (char *) ident,
01990                                       (ssize_t) -1) != 0)
01991        {
01992               if (conf->conf_dolog)
01993                      syslog(LOG_ERR, "failed to load/apply default key");
01994 
01995               lua_pushnumber(l, 0);
01996 
01997               return 1;
01998        }
01999 
02000        dfc->mctx_signalg = conf->conf_signalg;
02001 
02002        lua_pushnumber(l, 1);
02003 
02004        return 1;
02005 }
02006 
02007 /*
02008 **  DKIMF_XS_REPLACEHEADER -- replace a header field's value
02009 **
02010 **  Parameters:
02011 **     l -- Lua state
02012 **
02013 **  Return value:
02014 **     Number of stack items pushed.
02015 */
02016 
02017 int
02018 dkimf_xs_replaceheader(lua_State *l)
02019 {
02020        int idx;
02021        const char *hdrname;
02022        const char *newval;
02023        SMFICTX *ctx;
02024        struct connctx *cc;
02025        struct msgctx *dfc;
02026        struct dkimf_config *conf;
02027        Header hdr;
02028 
02029        assert(l != NULL);
02030 
02031        if (lua_gettop(l) != 4)
02032        {
02033               lua_pushstring(l,
02034                              "odkim.replace_header(): incorrect argument count");
02035               lua_error(l);
02036        }
02037        else if (!lua_islightuserdata(l, 1) ||
02038                 !lua_isstring(l, 2) ||
02039                 !lua_isnumber(l, 3) ||
02040                 !lua_isstring(l, 4))
02041        {
02042               lua_pushstring(l,
02043                              "odkim.replace_header(): incorrect argument type");
02044               lua_error(l);
02045        }
02046 
02047        ctx = (SMFICTX *) lua_touserdata(l, 1);
02048        hdrname = lua_tostring(l, 2);
02049        idx = (int) lua_tonumber(l, 3);
02050        newval = lua_tostring(l, 4);
02051 
02052        if (ctx != NULL)
02053        {
02054               cc = (struct connctx *) dkimf_getpriv(ctx);
02055               dfc = cc->cctx_msg;
02056               conf = cc->cctx_config;
02057        }
02058 
02059        lua_pop(l, 3);
02060 
02061        if (ctx == NULL)
02062        {
02063               if (idx == 0)
02064                      lua_pushstring(l, "dkimf_xs_replaceheader");
02065               else
02066                      lua_pushnil(l);
02067               return 1;
02068        }
02069 
02070        hdr = dkimf_findheader(dfc, (char *) hdrname, idx);
02071        if (hdr == NULL)
02072        {
02073               lua_pushnil(l);
02074               return 1;
02075        }
02076        else
02077        {
02078               char *tmp;
02079 
02080               if (ctx != NULL && cc->cctx_noleadspc)
02081               {
02082                      size_t len;
02083 
02084                      len = strlen(newval);
02085                      tmp = malloc(len + 2);
02086                      if (tmp == NULL)
02087                      {
02088                             lua_pushnil(l);
02089                             return 1;
02090                      }
02091 
02092                      tmp[0] = ' ';
02093                      memcpy(&tmp[1], newval, len + 1);
02094               }
02095               else
02096               {
02097                      tmp = strdup(newval);
02098                      if (tmp == NULL)
02099                      {
02100                             lua_pushnil(l);
02101                             return 1;
02102                      }
02103               }
02104 
02105               free(hdr->hdr_val);
02106               hdr->hdr_val = tmp;
02107 
02108               return 0;
02109        }
02110 }
02111 
02112 /*
02113 **  DKIMF_XS_GETENVFROM -- request envelope sender
02114 **
02115 **  Parameters:
02116 **     l -- Lua state
02117 **
02118 **  Return value:
02119 **     Number of stack items pushed.
02120 */
02121 
02122 int
02123 dkimf_xs_getenvfrom(lua_State *l)
02124 {
02125        int idx;
02126        const char *hdrname;
02127        SMFICTX *ctx;
02128        struct connctx *cc;
02129        struct msgctx *dfc;
02130        struct dkimf_config *conf;
02131        Header hdr;
02132 
02133        assert(l != NULL);
02134 
02135        if (lua_gettop(l) != 1)
02136        {
02137               lua_pushstring(l,
02138                              "odkim.get_envfrom(): incorrect argument count");
02139               lua_error(l);
02140        }
02141        else if (!lua_islightuserdata(l, 1))
02142        {
02143               lua_pushstring(l,
02144                              "odkim.get_envfrom(): incorrect argument type");
02145               lua_error(l);
02146        }
02147 
02148        ctx = (SMFICTX *) lua_touserdata(l, 1);
02149 
02150        if (ctx != NULL)
02151        {
02152               cc = (struct connctx *) dkimf_getpriv(ctx);
02153               dfc = cc->cctx_msg;
02154        }
02155 
02156        lua_pop(l, 1);
02157 
02158        if (ctx == NULL)
02159               lua_pushstring(l, "dkimf_xs_getenvfrom");
02160        else
02161               lua_pushstring(l, dfc->mctx_envfrom);
02162        return 1;
02163 }
02164 
02165 /*
02166 **  DKIMF_XS_GETHEADER -- request a header value
02167 **
02168 **  Parameters:
02169 **     l -- Lua state
02170 **
02171 **  Return value:
02172 **     Number of stack items pushed.
02173 */
02174 
02175 int
02176 dkimf_xs_getheader(lua_State *l)
02177 {
02178        int idx;
02179        const char *hdrname;
02180        SMFICTX *ctx;
02181        struct connctx *cc;
02182        struct msgctx *dfc;
02183        struct dkimf_config *conf;
02184        Header hdr;
02185 
02186        assert(l != NULL);
02187 
02188        if (lua_gettop(l) != 3)
02189        {
02190               lua_pushstring(l,
02191                              "odkim.get_header(): incorrect argument count");
02192               lua_error(l);
02193        }
02194        else if (!lua_islightuserdata(l, 1) ||
02195                 !lua_isstring(l, 2) || !lua_isnumber(l, 3))
02196        {
02197               lua_pushstring(l,
02198                              "odkim.get_header(): incorrect argument type");
02199               lua_error(l);
02200        }
02201 
02202        ctx = (SMFICTX *) lua_touserdata(l, 1);
02203        hdrname = lua_tostring(l, 2);
02204        idx = (int) lua_tonumber(l, 3);
02205 
02206        if (ctx != NULL)
02207        {
02208               cc = (struct connctx *) dkimf_getpriv(ctx);
02209               dfc = cc->cctx_msg;
02210               conf = cc->cctx_config;
02211        }
02212 
02213        lua_pop(l, 3);
02214 
02215        if (ctx == NULL)
02216        {
02217               if (idx == 0)
02218                      lua_pushstring(l, "dkimf_xs_getheader");
02219               else
02220                      lua_pushnil(l);
02221               return 1;
02222        }
02223 
02224        hdr = dkimf_findheader(dfc, (char *) hdrname, idx);
02225        if (hdr == NULL)
02226        {
02227               lua_pushnil(l);
02228               return 1;
02229        }
02230        else
02231        {
02232               lua_pushstring(l, hdr->hdr_val);
02233               return 1;
02234        }
02235 }
02236 
02237 /*
02238 **  DKIMF_XS_POPAUTH -- see if the client's IP address is in the POPAUTH
02239 **                      database
02240 **
02241 **  Parameters:
02242 **     l -- Lua state
02243 **
02244 **  Return value:
02245 **     Number of stack items pushed.
02246 */
02247 
02248 int
02249 dkimf_xs_popauth(lua_State *l)
02250 {
02251        SMFICTX *ctx;
02252        struct connctx *cc;
02253 
02254        assert(l != NULL);
02255 
02256        if (lua_gettop(l) != 1)
02257        {
02258               lua_pushstring(l,
02259                              "odkim.check_popauth(): incorrect argument count");
02260               lua_error(l);
02261        }
02262        else if (!lua_islightuserdata(l, 1))
02263        {
02264               lua_pushstring(l,
02265                              "odkim.check_popauth(): incorrect argument type");
02266               lua_error(l);
02267        }
02268 
02269        ctx = (SMFICTX *) lua_touserdata(l, 1);
02270        lua_pop(l, 1);
02271 
02272        if (ctx == NULL)
02273        {
02274               lua_pushnumber(l, 0);
02275 
02276               return 1;
02277        }
02278 
02279        cc = (struct connctx *) dkimf_getpriv(ctx);
02280 
02281 #ifdef POPAUTH
02282        if (popdb == NULL)
02283        {
02284               lua_pushnil(l);
02285               return 1;
02286        }
02287        else
02288        {
02289               _Bool popauth;
02290 
02291               popauth = dkimf_checkpopauth(popdb, &cc->cctx_ip);
02292 
02293               lua_pushnumber(l, popauth ? 1 : 0);
02294               return 1;
02295        }
02296 #else /* POPAUTH */
02297        lua_pushnil(l);
02298        return 1;
02299 #endif /* POPAUTH */
02300 }
02301 
02302 /*
02303 **  DKIMF_XS_INTERNALIP -- see if the client's IP address is "internal"
02304 **
02305 **  Parameters:
02306 **     l -- Lua state
02307 **
02308 **  Return value:
02309 **     Number of stack items pushed.
02310 */
02311 
02312 int
02313 dkimf_xs_internalip(lua_State *l)
02314 {
02315        SMFICTX *ctx;
02316        struct connctx *cc;
02317        struct dkimf_config *conf;
02318 
02319        assert(l != NULL);
02320 
02321        if (lua_gettop(l) != 1)
02322        {
02323               lua_pushstring(l,
02324                              "odkim.internal_ip(): incorrect argument count");
02325               lua_error(l);
02326        }
02327        else if (!lua_islightuserdata(l, 1))
02328        {
02329               lua_pushstring(l,
02330                              "odkim.internal_ip(): incorrect argument type");
02331               lua_error(l);
02332        }
02333 
02334        ctx = (SMFICTX *) lua_touserdata(l, 1);
02335        lua_pop(l, 1);
02336 
02337        if (ctx == NULL)
02338        {
02339               lua_pushnumber(l, 1);
02340 
02341               return 1;
02342        }
02343 
02344        cc = (struct connctx *) dkimf_getpriv(ctx);
02345        conf = cc->cctx_config;
02346 
02347        if (conf->conf_internal == NULL)
02348        {
02349               lua_pushnumber(l, 0);
02350        }
02351        else
02352        {
02353               _Bool internal;
02354 
02355               internal = dkimf_checkhost(conf->conf_internal, cc->cctx_host);
02356               internal = internal || dkimf_checkip(conf->conf_internal,
02357                                                    (struct sockaddr *) &cc->cctx_ip);
02358 
02359               lua_pushnumber(l, internal ? 1 : 0);
02360        }
02361 
02362        return 1;
02363 }
02364 
02365 /*
02366 **  DKIMF_XS_DBOPEN -- open a DB handle
02367 **
02368 **  Parameters:
02369 **     l -- Lua state
02370 **
02371 **  Return value:
02372 **     Number of stack items pushed.
02373 */
02374 
02375 int
02376 dkimf_xs_dbopen(lua_State *l)
02377 {
02378        unsigned int flags = DKIMF_DB_FLAG_READONLY;
02379        int status;
02380        DKIMF_DB db;
02381        char *name;
02382        char *err = NULL;
02383        struct dkimf_lua_gc *gc;
02384 
02385        assert(l != NULL);
02386 
02387        if (lua_gettop(l) != 1 && lua_gettop(l) != 2)
02388        {
02389               lua_pushstring(l,
02390                              "odkim.db_open(): incorrect argument count");
02391               lua_error(l);
02392        }
02393        else if (!lua_isstring(l, 1) ||
02394                 (lua_gettop(l) == 2 && !lua_isboolean(l, 2)))
02395        {
02396               lua_pushstring(l,
02397                              "odkim.db_open(): incorrect argument type");
02398               lua_error(l);
02399        }
02400 
02401        name = (char *)lua_tostring(l, 1);
02402        if (lua_gettop(l) == 2 && lua_toboolean(l, 2))
02403               flags |= DKIMF_DB_FLAG_ICASE;
02404        lua_pop(l, lua_gettop(l));
02405 
02406        status = dkimf_db_open(&db, name, flags, NULL, &err);
02407 
02408        if (status != 0)
02409        {
02410               if (err != NULL)
02411               {
02412                      lua_pushfstring(l, "%s: odkim.db_open(): %s", name,
02413                                      err);
02414               }
02415               else
02416               {
02417                      lua_pushfstring(l, "%s: odkim.db_open() failed", name);
02418               }
02419               lua_error(l);
02420        }
02421 
02422        lua_getglobal(l, DKIMF_GC);
02423        gc = (struct dkimf_lua_gc *) lua_touserdata(l, 1);
02424        lua_pop(l, 1);
02425        dkimf_lua_gc_add(gc, db, DKIMF_LUA_GC_DB);
02426 
02427        lua_pushlightuserdata(l, db);
02428 
02429        return 1;
02430 }
02431 
02432 /*
02433 **  DKIMF_XS_DBCLOSE -- close a DB handle
02434 **
02435 **  Parameters:
02436 **     l -- Lua state
02437 **
02438 **  Return value:
02439 **     Number of stack items pushed.
02440 */
02441 
02442 int
02443 dkimf_xs_dbclose(lua_State *l)
02444 {
02445        DKIMF_DB db;
02446        struct dkimf_lua_gc *gc;
02447 
02448        assert(l != NULL);
02449 
02450        if (lua_gettop(l) != 1)
02451        {
02452               lua_pushstring(l,
02453                              "odkim.db_close(): incorrect argument count");
02454               lua_error(l);
02455        }
02456        else if (!lua_islightuserdata(l, 1))
02457        {
02458               lua_pushstring(l,
02459                              "odkim.db_close(): incorrect argument type");
02460               lua_error(l);
02461        }
02462 
02463        db = (DKIMF_DB) lua_touserdata(l, 1);
02464 
02465        lua_pop(l, 1);
02466 
02467        if (db == NULL)
02468        {
02469               lua_pushnumber(l, 0);
02470               return 1;
02471        }
02472 
02473        (void) dkimf_db_close(db);
02474 
02475        lua_getglobal(l, DKIMF_GC);
02476        gc = (struct dkimf_lua_gc *) lua_touserdata(l, 1);
02477        lua_pop(l, 1);
02478        dkimf_lua_gc_remove(gc, (void *) db);
02479 
02480        lua_pushnumber(l, 1);
02481 
02482        return 1;
02483 }
02484 
02485 /*
02486 **  DKIMF_XS_DBHANDLE -- retrieve a DB handle
02487 **
02488 **  Parameters:
02489 **     l -- Lua state
02490 **
02491 **  Return value:
02492 **     Number of stack items pushed.
02493 */
02494 
02495 int
02496 dkimf_xs_dbhandle(lua_State *l)
02497 {
02498        int code;
02499        SMFICTX *ctx;
02500        struct connctx *cc;
02501        struct dkimf_config *conf;
02502 
02503        assert(l != NULL);
02504 
02505        if (lua_gettop(l) != 2)
02506        {
02507               lua_pushstring(l,
02508                              "odkim.get_dbhandle(): incorrect argument count");
02509               lua_error(l);
02510        }
02511        else if (!lua_islightuserdata(l, 1) || !lua_isnumber(l, 2))
02512        {
02513               lua_pushstring(l,
02514                              "odkim.get_dbhandle(): incorrect argument type");
02515               lua_error(l);
02516        }
02517 
02518        ctx = (SMFICTX *) lua_touserdata(l, 1);
02519 
02520        if (ctx == NULL)
02521        {
02522               lua_pop(l, 2);
02523               lua_pushnil(l);
02524               return 1;
02525        }
02526 
02527        cc = (struct connctx *) dkimf_getpriv(ctx);
02528        conf = cc->cctx_config;
02529 
02530        code = (int) lua_tonumber(l, 1);
02531        lua_pop(l, 2);
02532 
02533        switch (code)
02534        {
02535          case DB_DOMAINS:
02536               if (conf->conf_domainsdb == NULL)
02537                      lua_pushnil(l);
02538               else
02539                      lua_pushlightuserdata(l, conf->conf_domainsdb);
02540               break;
02541 
02542          case DB_THIRDPARTY:
02543               if (conf->conf_thirdpartydb == NULL)
02544                      lua_pushnil(l);
02545               else
02546                      lua_pushlightuserdata(l, conf->conf_thirdpartydb);
02547               break;
02548 
02549          case DB_DONTSIGNTO:
02550               if (conf->conf_dontsigntodb == NULL)
02551                      lua_pushnil(l);
02552               else
02553                      lua_pushlightuserdata(l, conf->conf_dontsigntodb);
02554               break;
02555 
02556          case DB_MTAS:
02557               if (conf->conf_mtasdb == NULL)
02558                      lua_pushnil(l);
02559               else
02560                      lua_pushlightuserdata(l, conf->conf_mtasdb);
02561               break;
02562 
02563          case DB_MACROS:
02564               if (conf->conf_macrosdb == NULL)
02565                      lua_pushnil(l);
02566               else
02567                      lua_pushlightuserdata(l, conf->conf_macrosdb);
02568               break;
02569 
02570          case DB_LOCALADSP:
02571               if (conf->conf_localadsp_db == NULL)
02572                      lua_pushnil(l);
02573               else
02574                      lua_pushlightuserdata(l, conf->conf_localadsp_db);
02575               break;
02576 
02577          case DB_SIGNINGTABLE:
02578               if (conf->conf_signtabledb == NULL)
02579                      lua_pushnil(l);
02580               else
02581                      lua_pushlightuserdata(l, conf->conf_signtabledb);
02582               break;
02583          default:
02584               lua_pushnil(l);
02585               break;
02586        }
02587 
02588        return 1;
02589 }
02590 
02591 /*
02592 **  DKIMF_XS_RCPTCOUNT -- retrieve recipient count
02593 **
02594 **  Parameters:
02595 **     l -- Lua state
02596 **
02597 **  Return value:
02598 **     Number of stack items pushed.
02599 */
02600 
02601 int
02602 dkimf_xs_rcptcount(lua_State *l)
02603 {
02604        int rcnt;
02605        SMFICTX *ctx;
02606        struct connctx *cc;
02607        struct dkimf_config *conf;
02608        struct msgctx *dfc;
02609        struct addrlist *addr;
02610 
02611        assert(l != NULL);
02612 
02613        if (lua_gettop(l) != 1)
02614        {
02615               lua_pushstring(l,
02616                              "odkim.rcpt_count(): incorrect argument count");
02617               lua_error(l);
02618        }
02619        else if (!lua_islightuserdata(l, 1))
02620        {
02621               lua_pushstring(l,
02622                              "odkim.rcpt_count(): incorrect argument type");
02623               lua_error(l);
02624        }
02625 
02626        ctx = (SMFICTX *) lua_touserdata(l, 1);
02627        lua_pop(l, 1);
02628 
02629        if (ctx == NULL)
02630        {
02631               lua_pushnumber(l, 1);
02632               return 1;
02633        }
02634 
02635        cc = (struct connctx *) dkimf_getpriv(ctx);
02636        conf = cc->cctx_config;
02637        dfc = cc->cctx_msg;
02638 
02639        rcnt = 0;
02640        
02641        for (addr = dfc->mctx_rcptlist; addr != NULL; addr = addr->a_next)
02642               rcnt++;
02643 
02644        lua_pushnumber(l, rcnt);
02645 
02646        return 1;
02647 }
02648 
02649 /*
02650 **  DKIMF_XS_RCPT -- retrieve an envelope recipient
02651 **
02652 **  Parameters:
02653 **     l -- Lua state
02654 **
02655 **  Return value:
02656 **     Number of stack items pushed.
02657 */
02658 
02659 int
02660 dkimf_xs_rcpt(lua_State *l)
02661 {
02662        int rcnt;
02663        SMFICTX *ctx;
02664        struct connctx *cc;
02665        struct msgctx *dfc;
02666        struct addrlist *addr;
02667 
02668        assert(l != NULL);
02669 
02670        if (lua_gettop(l) != 2)
02671        {
02672               lua_pushstring(l,
02673                              "odkim.get_rcpt(): incorrect argument count");
02674               lua_error(l);
02675        }
02676        else if (!lua_islightuserdata(l, 1) || !lua_isnumber(l, 2))
02677        {
02678               lua_pushstring(l,
02679                              "odkim.get_rcpt(): incorrect argument type");
02680               lua_error(l);
02681        }
02682 
02683        ctx = (SMFICTX *) lua_touserdata(l, 1);
02684        rcnt = (int) lua_tonumber(l, 1);
02685        lua_pop(l, 2);
02686 
02687        if (ctx == NULL)
02688        {
02689               lua_pushstring(l, "dkimf_xs_rcpt");
02690               return 1;
02691        }
02692        
02693        cc = (struct connctx *) dkimf_getpriv(ctx);
02694        dfc = cc->cctx_msg;
02695 
02696        for (addr = dfc->mctx_rcptlist;
02697             addr != NULL && rcnt >= 0;
02698             addr = addr->a_next)
02699               rcnt--;
02700 
02701        if (addr == NULL)
02702               lua_pushnil(l);
02703        else
02704               lua_pushstring(l, addr->a_addr);
02705 
02706        return 1;
02707 }
02708 
02709 /*
02710 **  DKIMF_XS_RCPTARRAY -- retrieve all recipients into a Lua array
02711 **
02712 **  Parameters:
02713 **     l -- Lua state
02714 **
02715 **  Return value:
02716 **     Number of stack items pushed.
02717 */
02718 
02719 int
02720 dkimf_xs_rcptarray(lua_State *l)
02721 {
02722        SMFICTX *ctx;
02723        struct connctx *cc;
02724        struct msgctx *dfc;
02725 
02726        assert(l != NULL);
02727 
02728        if (lua_gettop(l) != 1)
02729        {
02730               lua_pushstring(l,
02731                              "odkim.get_rcptarray(): incorrect argument count");
02732               lua_error(l);
02733        }
02734        else if (!lua_islightuserdata(l, 1))
02735        {
02736               lua_pushstring(l,
02737                              "odkim.get_rcptarray(): incorrect argument type");
02738               lua_error(l);
02739        }
02740 
02741        ctx = (SMFICTX *) lua_touserdata(l, 1);
02742        lua_pop(l, 1);
02743 
02744        lua_newtable(l);
02745 
02746        if (ctx == NULL)
02747        {
02748               lua_pushnumber(l, 1);
02749               lua_pushstring(l, "dkimf_xs_rcptarray");
02750               lua_settable(l, -3);
02751        }
02752        else
02753        {
02754               int idx;
02755               struct addrlist *addr;
02756 
02757               cc = (struct connctx *) dkimf_getpriv(ctx);
02758               dfc = cc->cctx_msg;
02759 
02760               for (addr = dfc->mctx_rcptlist, idx = 1;
02761                    addr != NULL;
02762                    addr = addr->a_next, idx++)
02763               {
02764                      lua_pushnumber(l, idx);
02765                      lua_pushstring(l, addr->a_addr);
02766                      lua_settable(l, -3);
02767               }
02768        }
02769 
02770        return 1;
02771 }
02772 
02773 /*
02774 **  DKIMF_XS_DBQUERY -- check for a record in a database
02775 **
02776 **  Parameters:
02777 **     l -- Lua state
02778 **
02779 **  Return value:
02780 **     Number of stack items pushed.
02781 */
02782 
02783 int
02784 dkimf_xs_dbquery(lua_State *l)
02785 {
02786        int status;
02787        _Bool exists;
02788        DKIMF_DB db;
02789        const char *str;
02790 
02791        assert(l != NULL);
02792 
02793        if (lua_gettop(l) != 2)
02794        {
02795               lua_pushstring(l,
02796                              "odkim.db_check(): incorrect argument count");
02797               lua_error(l);
02798        }
02799        else if (!lua_islightuserdata(l, 1) ||
02800                 !lua_isstring(l, 2))
02801        {
02802               lua_pushstring(l,
02803                              "odkim.db_check(): incorrect argument type");
02804               lua_error(l);
02805        }
02806 
02807        db = (DKIMF_DB) lua_touserdata(l, 1);
02808        str = lua_tostring(l, 2);
02809        lua_pop(l, 2);
02810 
02811        if (db == NULL || str == NULL)
02812        {
02813               lua_pushnil(l);
02814               return 1;
02815        }
02816 
02817        exists = FALSE;
02818        status = dkimf_db_get(db, (char *) str, 0, NULL, 0, &exists);
02819        if (status == 0)
02820               lua_pushnumber(l, exists ? 1 : 0);
02821        else
02822               lua_pushnil(l);
02823 
02824        return 1;
02825 }
02826 
02827 /*
02828 **  DKIMF_XS_SETPARTIAL -- request l= tags
02829 **
02830 **  Parameters:
02831 **     l -- Lua state
02832 **
02833 **  Return value:
02834 **     Number of stack items pushed.
02835 */
02836 
02837 int
02838 dkimf_xs_setpartial(lua_State *l)
02839 {
02840        SMFICTX *ctx;
02841 
02842        assert(l != NULL);
02843 
02844        if (lua_gettop(l) != 1)
02845        {
02846               lua_pushstring(l,
02847                              "odkim.use_ltag(): incorrect argument count");
02848               lua_error(l);
02849        }
02850        else if (!lua_islightuserdata(l, 1))
02851        {
02852               lua_pushstring(l,
02853                              "odkim.use_ltag(): incorrect argument type");
02854               lua_error(l);
02855        }
02856 
02857        ctx = (SMFICTX *) lua_touserdata(l, 1);
02858        lua_pop(l, 1);
02859 
02860        if (ctx != NULL)
02861        {
02862               struct connctx *cc;
02863               struct msgctx *dfc;
02864 
02865               cc = (struct connctx *) dkimf_getpriv(ctx);
02866               dfc = cc->cctx_msg;
02867               dfc->mctx_ltag = TRUE;
02868        }
02869 
02870        lua_pushnil(l);
02871 
02872        return 1;
02873 }
02874 
02875 /*
02876 **  DKIMF_XS_VERIFY -- set up verification
02877 **
02878 **  Parameters:
02879 **     l -- Lua state
02880 **
02881 **  Return value:
02882 **     Number of stack items pushed.
02883 */
02884 
02885 int
02886 dkimf_xs_verify(lua_State *l)
02887 {
02888        SMFICTX *ctx;
02889        struct connctx *cc;
02890        struct msgctx *dfc;
02891        struct dkimf_config *conf;
02892 
02893        assert(l != NULL);
02894 
02895        if (lua_gettop(l) != 1)
02896        {
02897               lua_pushstring(l,
02898                              "odkim.verify(): incorrect argument count");
02899               lua_error(l);
02900        }
02901        else if (!lua_islightuserdata(l, 1))
02902        {
02903               lua_pushstring(l,
02904                              "odkim.verify(): incorrect argument type");
02905               lua_error(l);
02906        }
02907 
02908        ctx = (SMFICTX *) lua_touserdata(l, 1);
02909        lua_pop(l, 1);
02910 
02911        if (ctx != NULL)
02912        {
02913               cc = (struct connctx *) dkimf_getpriv(ctx);
02914               dfc = cc->cctx_msg;
02915               conf = cc->cctx_config;
02916 
02917               if (dfc->mctx_dkimv == NULL)
02918               {
02919                      DKIM_STAT status;
02920 
02921                      dfc->mctx_dkimv = dkim_verify(conf->conf_libopendkim,
02922                                                    dfc->mctx_jobid, NULL,
02923                                                    &status);
02924 
02925                      if (dfc->mctx_dkimv == NULL)
02926                      {
02927                             lua_pushstring(l, dkim_getresultstr(status));
02928                             return 1;
02929                      }
02930               }
02931        }
02932 
02933        lua_pushnil(l);
02934        return 1;
02935 }
02936 
02937 /*
02938 **  DKIMF_XS_GETSIGARRAY -- get signature handle array
02939 **
02940 **  Parameters:
02941 **     l -- Lua state
02942 **
02943 **  Return value:
02944 **     Number of stack items pushed.
02945 */
02946 
02947 int
02948 dkimf_xs_getsigarray(lua_State *l)
02949 {
02950        SMFICTX *ctx;
02951 
02952        assert(l != NULL);
02953 
02954        if (lua_gettop(l) != 1)
02955        {
02956               lua_pushstring(l,
02957                              "odkim.get_sigarray(): incorrect argument count");
02958               lua_error(l);
02959        }
02960        else if (!lua_islightuserdata(l, 1))
02961        {
02962               lua_pushstring(l,
02963                              "odkim.get_sigarray(): incorrect argument type");
02964               lua_error(l);
02965        }
02966 
02967        ctx = (SMFICTX *) lua_touserdata(l, 1);
02968        lua_pop(l, 1);
02969 
02970        if (ctx != NULL)
02971        {
02972               struct connctx *cc;
02973               struct msgctx *dfc;
02974 
02975               cc = (struct connctx *) dkimf_getpriv(ctx);
02976               dfc = cc->cctx_msg;
02977 
02978               if (dfc->mctx_dkimv == NULL)
02979               {
02980                      lua_pushnumber(l, 0);
02981               }
02982               else
02983               {
02984                      int nsigs;
02985                      DKIM_STAT status;
02986                      DKIM_SIGINFO **sigs;
02987 
02988                      status = dkim_getsiglist(dfc->mctx_dkimv,
02989                                               &sigs, &nsigs);
02990                      if (status != DKIM_STAT_OK)
02991                      {
02992                             lua_pushnil(l);
02993                      }
02994                      else
02995                      {
02996                             int c;
02997 
02998                             lua_newtable(l);
02999 
03000                             for (c = 0; c < nsigs; c++)
03001                             {
03002                                    lua_pushnumber(l, c + 1);
03003                                    lua_pushlightuserdata(l, sigs[c]);
03004                                    lua_settable(l, -3);
03005                             }
03006                      }
03007               }
03008        }
03009        else
03010        {
03011               lua_pushnil(l);
03012        }
03013        
03014        return 1;
03015 }
03016 
03017 /*
03018 **  DKIMF_XS_GETSIGCOUNT -- get signature count
03019 **
03020 **  Parameters:
03021 **     l -- Lua state
03022 **
03023 **  Return value:
03024 **     Number of stack items pushed.
03025 */
03026 
03027 int
03028 dkimf_xs_getsigcount(lua_State *l)
03029 {
03030        SMFICTX *ctx;
03031        struct connctx *cc;
03032        struct msgctx *dfc;
03033 
03034        assert(l != NULL);
03035 
03036        if (lua_gettop(l) != 1)
03037        {
03038               lua_pushstring(l,
03039                              "odkim.get_sigcount(): incorrect argument count");
03040               lua_error(l);
03041        }
03042        else if (!lua_islightuserdata(l, 1))
03043        {
03044               lua_pushstring(l,
03045                              "odkim.get_sigcount(): incorrect argument type");
03046               lua_error(l);
03047        }
03048 
03049        ctx = (SMFICTX *) lua_touserdata(l, 1);
03050        lua_pop(l, 1);
03051 
03052        if (ctx != NULL)
03053        {
03054               cc = (struct connctx *) dkimf_getpriv(ctx);
03055               dfc = cc->cctx_msg;
03056 
03057               if (dfc->mctx_dkimv == NULL)
03058               {
03059                      lua_pushnumber(l, 0);
03060               }
03061               else
03062               {
03063                      DKIM_STAT status;
03064                      int nsigs;
03065                      DKIM_SIGINFO **sigs;
03066 
03067                      status = dkim_getsiglist(dfc->mctx_dkimv,
03068                                               &sigs, &nsigs);
03069                      if (status != DKIM_STAT_OK)
03070                             lua_pushnil(l);
03071                      else
03072                             lua_pushnumber(l, nsigs);
03073               }
03074        }
03075        else
03076        {
03077               lua_pushnumber(l, 1);
03078        }
03079        
03080        return 1;
03081 }
03082 
03083 /*
03084 **  DKIMF_XS_GETSIGHANDLE -- get signature handle
03085 **
03086 **  Parameters:
03087 **     l -- Lua state
03088 **
03089 **  Return value:
03090 **     Number of stack items pushed.
03091 */
03092 
03093 int
03094 dkimf_xs_getsighandle(lua_State *l)
03095 {
03096        int idx;
03097        int nsigs;
03098        DKIM_STAT status;
03099        SMFICTX *ctx;
03100        DKIM_SIGINFO **sigs;
03101        struct connctx *cc;
03102        struct msgctx *dfc;
03103 
03104        assert(l != NULL);
03105 
03106        if (lua_gettop(l) != 2)
03107        {
03108               lua_pushstring(l,
03109                              "odkim.get_sighandle(): incorrect argument count");
03110               lua_error(l);
03111        }
03112        else if (!lua_islightuserdata(l, 1) ||
03113                 !lua_isnumber(l, 2))
03114        {
03115               lua_pushstring(l,
03116                              "odkim.get_sighandle(): incorrect argument type");
03117               lua_error(l);
03118        }
03119 
03120        ctx = (SMFICTX *) lua_touserdata(l, 1);
03121        idx = (int) lua_tonumber(l, 2);
03122        lua_pop(l, 2);
03123 
03124        if (ctx == NULL)
03125        {
03126               lua_pushlightuserdata(l, NULL);
03127               return 1;
03128        }
03129 
03130        cc = (struct connctx *) dkimf_getpriv(ctx);
03131        dfc = cc->cctx_msg;
03132 
03133        if (dfc->mctx_dkimv == NULL)
03134        {
03135               lua_pushnil(l);
03136               return 1;
03137        }
03138 
03139        status = dkim_getsiglist(dfc->mctx_dkimv, &sigs, &nsigs);
03140        if (status != DKIM_STAT_OK)
03141        {
03142               lua_pushnil(l);
03143               return 1;
03144        }
03145 
03146        if (idx < 0 || idx >= nsigs)
03147        {
03148               lua_pushstring(l, "odkim.get_sighandle(): invalid request");
03149               lua_error(l);
03150        }
03151 
03152        lua_pushlightuserdata(l, sigs[idx]);
03153 
03154        return 1;
03155 }
03156 
03157 /*
03158 **  DKIMF_XS_GETSIGDOMAIN -- get signature's signing domain ("d=")
03159 **
03160 **  Parameters:
03161 **     l -- Lua state
03162 **
03163 **  Return value:
03164 **     Number of stack items pushed.
03165 */
03166 
03167 int
03168 dkimf_xs_getsigdomain(lua_State *l)
03169 {
03170        DKIM_SIGINFO *sig;
03171 
03172        assert(l != NULL);
03173 
03174        if (lua_gettop(l) != 1)
03175        {
03176               lua_pushstring(l,
03177                              "odkim.sig_getdomain(): incorrect argument count");
03178               lua_error(l);
03179        }
03180        else if (!lua_islightuserdata(l, 1))
03181        {
03182               lua_pushstring(l,
03183                              "odkim.sig_getdomain(): incorrect argument type");
03184               lua_error(l);
03185        }
03186 
03187        sig = (DKIM_SIGINFO *) lua_touserdata(l, 1);
03188        lua_pop(l, 1);
03189 
03190        if (sig == NULL)
03191               lua_pushlightuserdata(l, NULL);
03192        else
03193               lua_pushstring(l, (char *) dkim_sig_getdomain(sig));
03194 
03195        return 1;
03196 }
03197 
03198 /*
03199 **  DKIMF_XS_SIGIGNORE -- ignore a signature and its result
03200 **
03201 **  Parameters:
03202 **     l -- Lua state
03203 **
03204 **  Return value:
03205 **     Number of stack items pushed.
03206 */
03207 
03208 int
03209 dkimf_xs_sigignore(lua_State *l)
03210 {
03211        DKIM_SIGINFO *sig;
03212 
03213        assert(l != NULL);
03214 
03215        if (lua_gettop(l) != 1)
03216        {
03217               lua_pushstring(l,
03218                              "odkim.sig_getdomain(): incorrect argument count");
03219               lua_error(l);
03220        }
03221        else if (!lua_islightuserdata(l, 1))
03222        {
03223               lua_pushstring(l,
03224                              "odkim.sig_getdomain(): incorrect argument type");
03225               lua_error(l);
03226        }
03227 
03228        sig = (DKIM_SIGINFO *) lua_touserdata(l, 1);
03229        lua_pop(l, 1);
03230 
03231        if (sig != NULL)
03232               dkim_sig_ignore(sig);
03233 
03234        lua_pushnil(l);
03235 
03236        return 1;
03237 }
03238 
03239 /*
03240 **  DKIMF_XS_GETSIGIDENTITY -- get signature's signing identity ("i=")
03241 **
03242 **  Parameters:
03243 **     l -- Lua state
03244 **
03245 **  Return value:
03246 **     Number of stack items pushed.
03247 */
03248 
03249 int
03250 dkimf_xs_getsigidentity(lua_State *l)
03251 {
03252        DKIM_STAT status;
03253        DKIM_SIGINFO *sig;
03254        u_char addr[MAXADDRESS + 1];
03255 
03256        assert(l != NULL);
03257 
03258        if (lua_gettop(l) != 1)
03259        {
03260               lua_pushstring(l,
03261                              "odkim.sig_getidentity(): incorrect argument count");
03262               lua_error(l);
03263        }
03264        else if (!lua_islightuserdata(l, 1))
03265        {
03266               lua_pushstring(l,
03267                              "odkim.sig_getidentity(): incorrect argument type");
03268               lua_error(l);
03269        }
03270 
03271        sig = (DKIM_SIGINFO *) lua_touserdata(l, 1);
03272        lua_pop(l, 1);
03273 
03274        if (sig == NULL)
03275        {
03276               lua_pushstring(l, "dkimf_xs_getsigidentity");
03277               return 1;
03278        }
03279 
03280        memset(addr, '\0', sizeof addr);
03281        status = dkim_sig_getidentity(NULL, sig, addr, sizeof addr - 1);
03282        if (status != DKIM_STAT_OK)
03283               lua_pushnil(l);
03284        else
03285               lua_pushstring(l, (char *) addr);
03286 
03287        return 1;
03288 }
03289 
03290 /*
03291 **  DKIMF_XS_GETSYMVAL -- get MTA symbol
03292 **
03293 **  Parameters:
03294 **     l -- Lua state
03295 **
03296 **  Return value:
03297 **     Number of stack items pushed.
03298 */
03299 
03300 int
03301 dkimf_xs_getsymval(lua_State *l)
03302 {
03303        char *name;
03304        char *sym;
03305        SMFICTX *ctx;
03306 
03307        assert(l != NULL);
03308 
03309        if (lua_gettop(l) != 2)
03310        {
03311               lua_pushstring(l,
03312                              "odkim.get_mtasymbol(): incorrect argument count");
03313               lua_error(l);
03314        }
03315        else if (!lua_islightuserdata(l, 1) ||
03316                 !lua_isstring(l, 2))
03317        {
03318               lua_pushstring(l,
03319                              "odkim.get_mtasymbol(): incorrect argument type");
03320               lua_error(l);
03321        }
03322 
03323        ctx = (SMFICTX *) lua_touserdata(l, 1);
03324        name = (char *) lua_tostring(l, 2);
03325        lua_pop(l, 2);
03326 
03327        if (ctx == NULL)
03328        {
03329               lua_pushstring(l, "dkimf_xs_getmtasymbol");
03330        }
03331        else
03332        {
03333               sym = dkimf_getsymval(ctx, name);
03334               if (sym == NULL)
03335                      lua_pushnil(l);
03336               else
03337                      lua_pushstring(l, sym);
03338        }
03339 
03340        return 1;
03341 }
03342 
03343 /*
03344 **  DKIMF_XS_SIGRESULT -- get signature's result code
03345 **
03346 **  Parameters:
03347 **     l -- Lua state
03348 **
03349 **  Return value:
03350 **     Number of stack items pushed.
03351 */
03352 
03353 int
03354 dkimf_xs_sigresult(lua_State *l)
03355 {
03356        DKIM_SIGINFO *sig;
03357 
03358        assert(l != NULL);
03359 
03360        if (lua_gettop(l) != 1)
03361        {
03362               lua_pushstring(l,
03363                              "odkim.sig_result(): incorrect argument count");
03364               lua_error(l);
03365        }
03366        else if (!lua_islightuserdata(l, 1))
03367        {
03368               lua_pushstring(l,
03369                              "odkim.sig_result(): incorrect argument type");
03370               lua_error(l);
03371        }
03372 
03373        sig = (DKIM_SIGINFO *) lua_touserdata(l, 1);
03374        lua_pop(l, 1);
03375 
03376        if (sig == NULL)
03377               lua_pushnumber(l, 0);
03378        else
03379               lua_pushnumber(l, dkim_sig_geterror(sig));
03380 
03381        return 1;
03382 }
03383 
03384 /*
03385 **  DKIMF_XS_SIGBHRESULT -- get signature's body hash result code
03386 **
03387 **  Parameters:
03388 **     l -- Lua state
03389 **
03390 **  Return value:
03391 **     Number of stack items pushed.
03392 */
03393 
03394 int
03395 dkimf_xs_sigbhresult(lua_State *l)
03396 {
03397        DKIM_SIGINFO *sig;
03398 
03399        assert(l != NULL);
03400 
03401        if (lua_gettop(l) != 1)
03402        {
03403               lua_pushstring(l,
03404                              "odkim.sig_bhresult(): incorrect argument count");
03405               lua_error(l);
03406        }
03407        else if (!lua_islightuserdata(l, 1))
03408        {
03409               lua_pushstring(l,
03410                              "odkim.sig_bhresult(): incorrect argument type");
03411               lua_error(l);
03412        }
03413 
03414        sig = (DKIM_SIGINFO *) lua_touserdata(l, 1);
03415        lua_pop(l, 1);
03416 
03417        if (sig == NULL)
03418               lua_pushnumber(l, 0);
03419        else
03420               lua_pushnumber(l, dkim_sig_getbh(sig));
03421 
03422        return 1;
03423 }
03424 
03425 /*
03426 **  DKIMF_XS_BODYLENGTH -- return total body length
03427 **
03428 **  Parameters:
03429 **     l -- Lua state
03430 **
03431 **  Return value:
03432 **     Number of stack items pushed.
03433 */
03434 
03435 int
03436 dkimf_xs_bodylength(lua_State *l)
03437 {
03438        ssize_t body;
03439        DKIM_STAT status;
03440        SMFICTX *ctx;
03441        DKIM_SIGINFO *sig;
03442        struct connctx *cc;
03443 
03444        assert(l != NULL);
03445 
03446        if (lua_gettop(l) != 2)
03447        {
03448               lua_pushstring(l,
03449                              "odkim.sig_bodylength(): incorrect argument count");
03450               lua_error(l);
03451        }
03452        else if (!lua_islightuserdata(l, 1) ||
03453                 !lua_islightuserdata(l, 2))
03454        {
03455               lua_pushstring(l,
03456                              "odkim.sig_bodylength(): incorrect argument type");
03457               lua_error(l);
03458        }
03459 
03460        ctx = (SMFICTX *) lua_touserdata(l, 1);
03461        sig = (DKIM_SIGINFO *) lua_touserdata(l, 2);
03462        lua_pop(l, 2);
03463 
03464        if (ctx == NULL)
03465        {
03466               lua_pushnumber(l, 100);
03467               return 1;
03468        }
03469 
03470        cc = (struct connctx *) dkimf_getpriv(ctx);
03471        if (cc->cctx_msg == NULL || cc->cctx_msg->mctx_dkimv == NULL)
03472        {
03473               lua_pushnil(l);
03474               return 1;
03475        }
03476 
03477        status = dkim_sig_getcanonlen(cc->cctx_msg->mctx_dkimv, sig, &body,
03478                                      NULL, NULL);
03479        if (status != DKIM_STAT_OK)
03480               lua_pushnil(l);
03481        else
03482               lua_pushnumber(l, body);
03483 
03484        return 1;
03485 }
03486 
03487 /*
03488 **  DKIMF_XS_CANONLENGTH -- return length canonicalized by a signature
03489 **
03490 **  Parameters:
03491 **     l -- Lua state
03492 **
03493 **  Return value:
03494 **     Number of stack items pushed.
03495 */
03496 
03497 int
03498 dkimf_xs_canonlength(lua_State *l)
03499 {
03500        ssize_t cl;
03501        DKIM_STAT status;
03502        SMFICTX *ctx;
03503        DKIM_SIGINFO *sig;
03504        struct connctx *cc;
03505 
03506        assert(l != NULL);
03507 
03508        if (lua_gettop(l) != 2)
03509        {
03510               lua_pushstring(l,
03511                              "odkim.sig_canonlength(): incorrect argument count");
03512               lua_error(l);
03513        }
03514        else if (!lua_islightuserdata(l, 1) ||
03515                 !lua_islightuserdata(l, 2))
03516        {
03517               lua_pushstring(l,
03518                              "odkim.sig_canonlength(): incorrect argument type");
03519               lua_error(l);
03520        }
03521 
03522        ctx = (SMFICTX *) lua_touserdata(l, 1);
03523        sig = (DKIM_SIGINFO *) lua_touserdata(l, 2);
03524        lua_pop(l, 2);
03525 
03526        if (ctx == NULL)
03527        {
03528               lua_pushnumber(l, 100);
03529               return 1;
03530        }
03531 
03532        cc = (struct connctx *) dkimf_getpriv(ctx);
03533        if (cc->cctx_msg == NULL || cc->cctx_msg->mctx_dkimv == NULL)
03534        {
03535               lua_pushnil(l);
03536               return 1;
03537        }
03538 
03539        status = dkim_sig_getcanonlen(cc->cctx_msg->mctx_dkimv, sig, NULL,
03540                                      &cl, NULL);
03541        if (status != DKIM_STAT_OK)
03542               lua_pushnil(l);
03543        else
03544               lua_pushnumber(l, cl);
03545 
03546        return 1;
03547 }
03548 
03549 /*
03550 **  DKIMF_XS_ADDHEADER -- add a header field
03551 **
03552 **  Parameters:
03553 **     l -- Lua state
03554 **
03555 **  Return value:
03556 **     Number of stack items pushed.
03557 */
03558 
03559 int
03560 dkimf_xs_addheader(lua_State *l)
03561 {
03562        char *name;
03563        char *value;
03564        SMFICTX *ctx;
03565 
03566        assert(l != NULL);
03567 
03568        if (lua_gettop(l) != 3)
03569        {
03570               lua_pushstring(l,
03571                              "odkim.add_header(): incorrect argument count");
03572               lua_error(l);
03573        }
03574        else if (!lua_islightuserdata(l, 1) ||
03575                 !lua_isstring(l, 2) ||
03576                 !lua_isstring(l, 3))
03577        {
03578               lua_pushstring(l,
03579                              "odkim.add_header(): incorrect argument type");
03580               lua_error(l);
03581        }
03582 
03583        ctx = (SMFICTX *) lua_touserdata(l, 1);
03584        name = (char *) lua_tostring(l, 2);
03585        value = (char *) lua_tostring(l, 3);
03586        lua_pop(l, 3);
03587 
03588        if (ctx == NULL)
03589               lua_pushnil(l);
03590        else if (dkimf_insheader(ctx, 1, name, value) == MI_SUCCESS)
03591               lua_pushnumber(l, 1);
03592        else
03593               lua_pushnil(l);
03594 
03595        return 1;
03596 }
03597 
03598 /*
03599 **  DKIMF_XS_DELHEADER -- delete a header field
03600 **
03601 **  Parameters:
03602 **     l -- Lua state
03603 **
03604 **  Return value:
03605 **     Number of stack items pushed.
03606 */
03607 
03608 int
03609 dkimf_xs_delheader(lua_State *l)
03610 {
03611        int idx;
03612        char *name;
03613        SMFICTX *ctx;
03614 
03615        assert(l != NULL);
03616 
03617        if (lua_gettop(l) != 3)
03618        {
03619               lua_pushstring(l,
03620                              "odkim.del_header(): incorrect argument count");
03621               lua_error(l);
03622        }
03623        else if (!lua_islightuserdata(l, 1) ||
03624                 !lua_isstring(l, 2) ||
03625                 !lua_isnumber(l, 3))
03626        {
03627               lua_pushstring(l,
03628                              "odkim.del_header(): incorrect argument type");
03629               lua_error(l);
03630        }
03631 
03632        ctx = (SMFICTX *) lua_touserdata(l, 1);
03633        name = (char *) lua_tostring(l, 2);
03634        idx = lua_tonumber(l, 3);
03635        lua_pop(l, 3);
03636 
03637        if (ctx == NULL)
03638               lua_pushnil(l);
03639        else if (dkimf_chgheader(ctx, name, 1, NULL) == MI_SUCCESS)
03640               lua_pushnumber(l, 1);
03641        else
03642               lua_pushnil(l);
03643 
03644        return 1;
03645 }
03646 
03647 /*
03648 **  DKIMF_XS_ADDRCPT -- add a recipient
03649 **
03650 **  Parameters:
03651 **     l -- Lua state
03652 **
03653 **  Return value:
03654 **     Number of stack items pushed.
03655 */
03656 
03657 int
03658 dkimf_xs_addrcpt(lua_State *l)
03659 {
03660        char *addr;
03661        SMFICTX *ctx;
03662 
03663        assert(l != NULL);
03664 
03665        if (lua_gettop(l) != 2)
03666        {
03667               lua_pushstring(l,
03668                              "odkim.add_rcpt(): incorrect argument count");
03669               lua_error(l);
03670        }
03671        else if (!lua_islightuserdata(l, 1) ||
03672                 !lua_isstring(l, 2))
03673        {
03674               lua_pushstring(l, "odkim.add_rcpt(): incorrect argument type");
03675               lua_error(l);
03676        }
03677 
03678        ctx = (SMFICTX *) lua_touserdata(l, 1);
03679        addr = (char *) lua_tostring(l, 2);
03680        lua_pop(l, 2);
03681 
03682        if (ctx == NULL)
03683               lua_pushnumber(l, 1);
03684        else if (dkimf_addrcpt(ctx, addr) == MI_SUCCESS)
03685               lua_pushnumber(l, 1);
03686        else
03687               lua_pushnil(l);
03688 
03689        return 1;
03690 }
03691 
03692 /*
03693 **  DKIMF_XS_DELRCPT -- delete a recipient
03694 **
03695 **  Parameters:
03696 **     l -- Lua state
03697 **
03698 **  Return value:
03699 **     Number of stack items pushed.
03700 */
03701 
03702 int
03703 dkimf_xs_delrcpt(lua_State *l)
03704 {
03705        char *addr;
03706        struct addrlist *a;
03707        SMFICTX *ctx;
03708        struct connctx *cc;
03709        struct msgctx *dfc;
03710        struct dkimf_config *conf;
03711 
03712        assert(l != NULL);
03713 
03714        if (lua_gettop(l) != 2)
03715        {
03716               lua_pushstring(l,
03717                              "odkim.delete_rcpt(): incorrect argument count");
03718               lua_error(l);
03719        }
03720        else if (!lua_islightuserdata(l, 1) ||
03721                 !lua_isstring(l, 2))
03722        {
03723               lua_pushstring(l,
03724                              "odkim.delete_rcpt(): incorrect argument type");
03725               lua_error(l);
03726        }
03727 
03728        ctx = (SMFICTX *) lua_touserdata(l, 1);
03729        addr = (char *) lua_tostring(l, 2);
03730        lua_pop(l, 2);
03731 
03732        if (ctx == NULL)
03733        {
03734               lua_pushnumber(l, 1);
03735               return 1;
03736        }
03737 
03738        cc = (struct connctx *) dkimf_getpriv(ctx);
03739        conf = cc->cctx_config;
03740        dfc = cc->cctx_msg;
03741 
03742        /* see if this is a known recipient */
03743        for (a = dfc->mctx_rcptlist; a != NULL; a = a->a_next)
03744        {
03745               if (strcasecmp(a->a_addr, addr) == 0)
03746                      break;
03747        }
03748 
03749        /* if not found, report error */
03750        if (a == NULL)
03751        {
03752               lua_pushnil(l);
03753               return 1;
03754        }
03755 
03756        /* delete and replace with a header field */
03757        if (dkimf_delrcpt(ctx, a->a_addr) != MI_SUCCESS)
03758        {
03759               if (conf->conf_dolog)
03760               {
03761                      syslog(LOG_ERR, "%s: smfi_delrcpt() failed",
03762                             dfc->mctx_jobid);
03763               }
03764        }
03765        else
03766        {
03767               char header[MAXADDRESS + 8];
03768 
03769               snprintf(header, sizeof header, "rfc822;%s", a->a_addr);
03770               if (dkimf_addheader(ctx, ORCPTHEADER, header) != MI_SUCCESS)
03771               {
03772                      if (conf->conf_dolog)
03773                      {
03774                             syslog(LOG_ERR, "%s: smfi_addheader() failed",
03775                                    dfc->mctx_jobid);
03776                      }
03777               }
03778        }
03779 
03780        lua_pushnumber(l, 1);
03781 
03782        return 1;
03783 }
03784 
03785 /*
03786 **  DKIMF_XS_RESIGN -- set up for re-signing
03787 **
03788 **  Parameters:
03789 **     l -- Lua state
03790 **
03791 **  Return value:
03792 **     Number of stack items pushed.
03793 */
03794 
03795 int
03796 dkimf_xs_resign(lua_State *l)
03797 {
03798        SMFICTX *ctx;
03799        struct connctx *cc;
03800        struct msgctx *dfc;
03801 
03802        assert(l != NULL);
03803 
03804        if (lua_gettop(l) != 1)
03805        {
03806               lua_pushstring(l, "odkim.resign(): incorrect argument count");
03807               lua_error(l);
03808        }
03809        else if (!lua_islightuserdata(l, 1))
03810        {
03811               lua_pushstring(l, "odkim.resign(): incorrect argument type");
03812               lua_error(l);
03813        }
03814 
03815        ctx = (SMFICTX *) lua_touserdata(l, 1);
03816        lua_pop(l, 1);
03817 
03818        if (ctx == NULL)
03819        {
03820               lua_pushnumber(l, 1);
03821               return 1;
03822        }
03823 
03824        cc = (struct connctx *) dkimf_getpriv(ctx);
03825        dfc = cc->cctx_msg;
03826 
03827 # ifdef _FFR_RESIGN
03828        dfc->mctx_resign = TRUE;
03829 
03830        lua_pushnumber(l, 1);
03831 # else /* _FFR_RESIGN */
03832        lua_pushnil(l);
03833 # endif /* _FFR_RESIGN */
03834 
03835        return 1;
03836 }
03837 
03838 /*
03839 **  DKIMF_XS_GETPOLICY -- retrieve sender policy
03840 **
03841 **  Parameters:
03842 **     l -- Lua state
03843 **
03844 **  Return value:
03845 **     Number of stack items pushed.
03846 */
03847 
03848 int
03849 dkimf_xs_getpolicy(lua_State *l)
03850 {
03851        SMFICTX *ctx;
03852        struct connctx *cc;
03853        struct msgctx *dfc;
03854 
03855        assert(l != NULL);
03856 
03857        if (lua_gettop(l) != 1)
03858        {
03859               lua_pushstring(l, "odkim.get_policy(): incorrect argument count");
03860               lua_error(l);
03861        }
03862        else if (!lua_islightuserdata(l, 1))
03863        {
03864               lua_pushstring(l, "odkim.get_policy(): incorrect argument type");
03865               lua_error(l);
03866        }
03867 
03868        ctx = (SMFICTX *) lua_touserdata(l, 1);
03869        lua_pop(l, 1);
03870 
03871        if (ctx == NULL)
03872        {
03873               lua_pushlightuserdata(l, NULL);
03874               return 1;
03875        }
03876 
03877        cc = (struct connctx *) dkimf_getpriv(ctx);
03878        dfc = cc->cctx_msg;
03879 
03880        if (dfc->mctx_presult == DKIM_PRESULT_NONE ||
03881            dfc->mctx_pcode == DKIM_POLICY_NONE)
03882               lua_pushnumber(l, DKIMF_POLICY_NONE);
03883        else if (dfc->mctx_presult == DKIM_PRESULT_NXDOMAIN)
03884               lua_pushnumber(l, DKIMF_POLICY_NXDOMAIN);
03885        else if (dfc->mctx_pcode == DKIM_POLICY_UNKNOWN)
03886               lua_pushnumber(l, DKIMF_POLICY_UNKNOWN);
03887        else if (dfc->mctx_pcode == DKIM_POLICY_ALL)
03888               lua_pushnumber(l, DKIMF_POLICY_ALL);
03889        else if (dfc->mctx_pcode == DKIM_POLICY_DISCARDABLE)
03890               lua_pushnumber(l, DKIMF_POLICY_DISCARDABLE);
03891        else
03892               lua_pushnil(l);
03893 
03894        return 1;
03895 }
03896 
03897 /*
03898 **  DKIMF_XS_SETREPLY -- set SMTP reply text
03899 **
03900 **  Parameters:
03901 **     l -- Lua state
03902 **
03903 **  Return value:
03904 **     Number of stack items pushed.
03905 */
03906 
03907 int
03908 dkimf_xs_setreply(lua_State *l)
03909 {
03910        SMFICTX *ctx;
03911        char *rcode = NULL;
03912        char *xcode = NULL;
03913        char *message = NULL;
03914 
03915        assert(l != NULL);
03916 
03917        if (lua_gettop(l) != 4)
03918        {
03919               lua_pushstring(l,
03920                              "odkim.set_reply(): incorrect argument count");
03921               lua_error(l);
03922        }
03923        else if (!lua_islightuserdata(l, 1) ||
03924                 !lua_isstring(l, 2) ||
03925                 !lua_isstring(l, 3) ||
03926                 !lua_isstring(l, 4))
03927        {
03928               lua_pushstring(l,
03929                              "odkim.set_reply(): incorrect argument type");
03930               lua_error(l);
03931        }
03932 
03933        ctx = (SMFICTX *) lua_touserdata(l, 1);
03934        rcode = (char *) lua_tostring(l, 2);
03935        xcode = (char *) lua_tostring(l, 3);
03936        message = (char *) lua_tostring(l, 4);
03937        lua_pop(l, 4);
03938 
03939        if (ctx == NULL)
03940        {
03941               lua_pushnumber(l, 1);
03942               return 1;
03943        }
03944 
03945        if (strlen(xcode) == 0)
03946               xcode = NULL;
03947 
03948        if (dkimf_setreply(ctx, rcode, xcode, message) == MI_FAILURE)
03949               lua_pushnil(l);
03950        else
03951               lua_pushnumber(l, 1);
03952 
03953        return 1;
03954 }
03955 
03956 /*
03957 **  DKIMF_XS_QUARANTINE -- request quarantine
03958 **
03959 **  Parameters:
03960 **     l -- Lua state
03961 **
03962 **  Return value:
03963 **     Number of stack items pushed.
03964 */
03965 
03966 int
03967 dkimf_xs_quarantine(lua_State *l)
03968 {
03969        SMFICTX *ctx;
03970        char *message = NULL;
03971 
03972        assert(l != NULL);
03973 
03974        if (lua_gettop(l) != 2)
03975        {
03976               lua_pushstring(l,
03977                              "odkim.quarantine(): incorrect argument count");
03978               lua_error(l);
03979        }
03980        else if (!lua_islightuserdata(l, 1) ||
03981                 !lua_isstring(l, 2))
03982        {
03983               lua_pushstring(l,
03984                              "odkim.quarantine(): incorrect argument type");
03985               lua_error(l);
03986        }
03987 
03988        ctx = (SMFICTX *) lua_touserdata(l, 1);
03989        message = (char *) lua_tostring(l, 2);
03990        lua_pop(l, 2);
03991 
03992        if (ctx == NULL)
03993               lua_pushnumber(l, 1);
03994        else if (dkimf_quarantine(ctx, message) == MI_FAILURE)
03995               lua_pushnil(l);
03996        else
03997               lua_pushnumber(l, 1);
03998 
03999        return 1;
04000 }
04001 
04002 /*
04003 **  DKIMF_XS_SETRESULT -- set milter result
04004 **
04005 **  Parameters:
04006 **     l -- Lua state
04007 **
04008 **  Return value:
04009 **     Number of stack items pushed.
04010 */
04011 
04012 int
04013 dkimf_xs_setresult(lua_State *l)
04014 {
04015        SMFICTX *ctx;
04016        int mresult;
04017 
04018        assert(l != NULL);
04019 
04020        if (lua_gettop(l) != 2)
04021        {
04022               lua_pushstring(l,
04023                              "odkim.set_result(): incorrect argument count");
04024               lua_error(l);
04025        }
04026        else if (!lua_islightuserdata(l, 1) ||
04027                 !lua_isnumber(l, 2))
04028        {
04029               lua_pushstring(l,
04030                              "odkim.set_result(): incorrect argument type");
04031               lua_error(l);
04032        }
04033 
04034        ctx = (SMFICTX *) lua_touserdata(l, 1);
04035        mresult = (int) lua_tonumber(l, 2);
04036        lua_pop(l, 2);
04037 
04038        if (ctx == NULL)
04039        {
04040               lua_pushnumber(l, 1);
04041        }
04042        else if (mresult == SMFIS_TEMPFAIL ||
04043                 mresult == SMFIS_ACCEPT ||
04044                 mresult == SMFIS_DISCARD ||
04045                 mresult == SMFIS_REJECT)
04046        {
04047               struct msgctx *dfc;
04048               struct connctx *cc;
04049 
04050               cc = (struct connctx *) dkimf_getpriv(ctx);
04051               dfc = cc->cctx_msg;
04052 
04053               dfc->mctx_mresult = mresult;
04054               lua_pushnumber(l, 1);
04055        }
04056        else
04057        {
04058               lua_pushnil(l);
04059        }
04060 
04061        return 1;
04062 }
04063 
04064 /*
04065 **  DKIMF_XS_GETREPUTATION -- perform reputation query
04066 **
04067 **  Parameters:
04068 **     l -- Lua state
04069 **
04070 **  Return value:
04071 **     Number of stack items pushed.
04072 */
04073 
04074 int
04075 dkimf_xs_getreputation(lua_State *l)
04076 {
04077        DKIM_STAT status;
04078        int rep;
04079        SMFICTX *ctx;
04080        char *qroot;
04081        DKIM_SIGINFO *sig;
04082        struct connctx *cc;
04083        struct dkimf_config *conf;
04084        struct msgctx *dfc;
04085 
04086        assert(l != NULL);
04087 
04088        if (lua_gettop(l) != 3)
04089        {
04090               lua_pushstring(l,
04091                              "odkim.get_reputation(): incorrect argument count");
04092               lua_error(l);
04093        }
04094        else if (!lua_islightuserdata(l, 1) ||
04095                 !lua_islightuserdata(l, 2) ||
04096                 !lua_isstring(l, 3))
04097        {
04098               lua_pushstring(l,
04099                              "odkim.get_reputation(): incorrect argument type");
04100               lua_error(l);
04101        }
04102 
04103        ctx = (SMFICTX *) lua_touserdata(l, 1);
04104        sig = (DKIM_SIGINFO *) lua_touserdata(l, 2);
04105        qroot = (char *) lua_tostring(l, 3);
04106        lua_pop(l, 3);
04107 
04108        if (ctx == NULL)
04109        {
04110               lua_pushnumber(l, 50);
04111               return 1;
04112        }
04113 
04114        cc = (struct connctx *) dkimf_getpriv(ctx);
04115        dfc = cc->cctx_msg;
04116        conf = cc->cctx_config;
04117 
04118        if (dfc->mctx_dkimv == NULL)
04119        {
04120               lua_pushnil(l);
04121        }
04122        else
04123        {
04124 # ifdef _FFR_DKIM_REPUTATION
04125               DKIM_REP dr;
04126 
04127               dr = dkim_rep_init(NULL, NULL, NULL);
04128               if (dr != NULL)
04129               {
04130                      void *qh;
04131 
04132 #  ifdef USE_ARLIB
04133                      dkimf_rep_arlib_setup(dr, conf->conf_arlib);
04134 #  endif /* USE_ARLIB */
04135 #  ifdef USE_UNBOUND
04136                      dkimf_rep_unbound_setup(dr, conf->conf_unbound);
04137 #  endif /* USE_UNBOUND */
04138 
04139                      if (strlen(qroot) != 0)
04140                             dkim_rep_setdomain(dr, qroot);
04141 
04142                      status = dkim_rep_query_start(dr,
04143                                                    dkim_getuser(dfc->mctx_dkimv),
04144                                                    dkim_getdomain(dfc->mctx_dkimv),
04145                                                    dkim_sig_getdomain(sig),
04146                                                    &qh);
04147                      if (status == DKIM_REP_STAT_OK && qh != NULL)
04148                      {
04149                             int rep = 0;
04150                             struct timeval timeout;
04151 
04152                             timeout.tv_sec = conf->conf_dnstimeout;
04153                             timeout.tv_usec = 0;
04154 
04155                             status = dkim_rep_query_check(dr, qh,
04156                                                           &timeout, &rep);
04157                             if (status == DKIM_REP_STAT_FOUND)
04158                                    lua_pushnumber(l, rep);
04159                             else
04160                                    lua_pushnil(l);
04161                      }
04162                      else
04163                      {
04164                             lua_pushnil(l);
04165                      }
04166 
04167                      dkim_rep_close(dr);
04168               }
04169 
04170               lua_pushnil(l);
04171 # else /* _FFR_DKIM_REPUTATION */
04172               lua_pushnil(l);
04173 # endif /* _FFR_DKIM_REPUTATION */
04174        }
04175 
04176        return 1;
04177 }
04178 
04179 # ifdef _FFR_STATSEXT
04180 /*
04181 **  DKIMF_XS_STATSEXT -- record extended statistics
04182 **
04183 **  Parameters:
04184 **     l -- Lua state
04185 **
04186 **  Return value:
04187 **     Number of stack items pushed.
04188 */
04189 
04190 int
04191 dkimf_xs_statsext(lua_State *l)
04192 {
04193        char *name;
04194        char *value;
04195        SMFICTX *ctx;
04196 
04197        assert(l != NULL);
04198 
04199        if (lua_gettop(l) != 3)
04200        {
04201               lua_pushstring(l,
04202                              "odkim.stats(): incorrect argument count");
04203               lua_error(l);
04204        }
04205        else if (!lua_islightuserdata(l, 1) ||
04206                 !lua_isstring(l, 2) ||
04207                 !lua_isstring(l, 3))
04208        {
04209               lua_pushstring(l,
04210                              "odkim.stats(): incorrect argument type");
04211               lua_error(l);
04212        }
04213 
04214        ctx = (SMFICTX *) lua_touserdata(l, 1);
04215        name = (char *) lua_tostring(l, 2);
04216        value = (char *) lua_tostring(l, 3);
04217        lua_pop(l, 3);
04218 
04219        if (ctx != NULL)
04220        {
04221               struct statsext *se;
04222               struct connctx *cc;
04223               struct msgctx *dfc;
04224 
04225               cc = (struct connctx *) dkimf_getpriv(ctx);
04226               dfc = cc->cctx_msg;
04227 
04228               se = (struct statsext *) malloc(sizeof(struct statsext));
04229               if (se == NULL)
04230               {
04231                      lua_pushfstring(l, "odkim.stats(): malloc(): %s",
04232                                      strerror(errno));
04233                      lua_error(l);
04234               }
04235 
04236               se->se_next = dfc->mctx_statsext;
04237               dfc->mctx_statsext = se;
04238 
04239               strlcpy(se->se_name, name, sizeof se->se_name);
04240               strlcpy(se->se_value, value, sizeof se->se_value);
04241        }
04242 
04243        lua_pushnil(l);
04244 
04245        return 1;
04246 }
04247 # endif /* _FFR_STATSEXT */
04248 #endif /* USE_LUA */
04249 
04250 #ifdef _FFR_VBR
04251 /*
04252 **  DKIMF_VALID_VBR -- determine whether or not VBR should be verified
04253 **
04254 **  Parameters:
04255 **     dfc -- filter context
04256 **
04257 **  Return value:
04258 **     TRUE iff the message should have its VBR data checked
04259 */
04260 
04261 static _Bool
04262 dkimf_valid_vbr(struct msgctx *dfc)
04263 {
04264        _Bool ret;
04265        int c = 0;
04266        char *p;
04267        char *q;
04268        char *last = NULL;
04269        Header hdr;
04270        char mc[DKIM_MAXHEADER + 1];
04271        char tmp[DKIM_MAXHEADER + 1];
04272 
04273        assert(dfc != NULL);
04274 
04275        memset(mc, '\0', sizeof mc);
04276 
04277        for (c = 0; c == 0 || ret; c++)
04278        {
04279               hdr = dkimf_findheader(dfc, VBR_INFOHEADER, c);
04280 
04281               if (hdr == NULL)
04282                      break;
04283 
04284               if (c == 0)
04285                      ret = TRUE;
04286 
04287               strlcpy(tmp, hdr->hdr_val, sizeof tmp);
04288 
04289               for (p = strtok_r(tmp, ";", &last);
04290                    p != NULL;
04291                    p = strtok_r(NULL, ";", &last))
04292               {
04293                      q = strchr(p, '=');
04294                      if (q == NULL)
04295                             continue;
04296                      *q = '\0';
04297 
04298                      dkimf_trimspaces(p);
04299                      dkimf_trimspaces(q + 1);
04300 
04301                      if (strcasecmp(p, "mc") == 0)
04302                      {
04303                             if (mc[0] == '\0')
04304                                    strlcpy(mc, q + 1, sizeof mc);
04305                             else if (strcasecmp(q + 1, mc) != 0)
04306                                    ret = FALSE;
04307 
04308                             break;
04309                      }
04310               }
04311        }
04312 
04313        if (mc[0] == '\0')
04314               ret = FALSE;
04315 
04316        return ret;
04317 }
04318 #endif /* _FFR_VBR */
04319 
04320 /*
04321 **  DKIMF_ADD_AR_FIELDS -- add Authentication-Results header fields
04322 **
04323 **  Parameters:
04324 **     dfc -- filter context
04325 **     conf -- configuration handle
04326 **     ctx -- milter context
04327 **
04328 **  Return value:
04329 **     None.
04330 */
04331 
04332 static void
04333 dkimf_add_ar_fields(struct msgctx *dfc, struct dkimf_config *conf,
04334                     SMFICTX *ctx)
04335 {
04336        assert(dfc != NULL);
04337        assert(conf != NULL);
04338        assert(ctx != NULL);
04339 
04340        if (dkimf_insheader(ctx, 1, AUTHRESULTSHDR,
04341                            (char *) dfc->mctx_dkimar) == MI_FAILURE)
04342        {
04343               if (conf->conf_dolog)
04344               {
04345                      syslog(LOG_ERR, "%s: %s header add failed",
04346                             dfc->mctx_jobid, AUTHRESULTSHDR);
04347               }
04348        }
04349 }
04350 
04351 /*
04352 **  DKIMF_DB_ERROR -- syslog errors related to db retrieval
04353 **
04354 **  Parameters:
04355 **     db -- the db
04356 **      key -- what was looked up
04357 **
04358 **  Return value:
04359 **     None.
04360 */
04361 
04362 static void
04363 dkimf_db_error(DKIMF_DB db, const char *key)
04364 {
04365        char errbuf[BUFRSZ];
04366 
04367        assert(db != NULL);
04368        assert(key != NULL);
04369 
04370        (void) dkimf_db_strerror(db, errbuf, sizeof errbuf);
04371 
04372        syslog(LOG_ERR, "error looking up \"%s\" in database: %s",
04373               key, errbuf);
04374 }
04375 
04376 
04377 /*
04378 **  DKIMF_INIT_SYSLOG -- initialize syslog()
04379 **
04380 **  Parameters:
04381 **     facility -- name of the syslog facility to use when logging;
04382 **                 can be NULL to request the default
04383 **
04384 **  Return value:
04385 **     None.
04386 */
04387 
04388 static void
04389 dkimf_init_syslog(char *facility)
04390 {
04391 #ifdef LOG_MAIL
04392        int code;
04393        struct lookup *p = NULL;
04394 
04395        closelog();
04396 
04397        code = LOG_MAIL;
04398        if (facility != NULL)
04399        {
04400               for (p = log_facilities; p != NULL; p++)
04401               {
04402                      if (strcasecmp(p->str, facility) == 0)
04403                      {
04404                             code = p->code;
04405                             break;
04406                      }
04407               }
04408        }
04409 
04410        openlog(progname, LOG_PID, code);
04411 #else /* LOG_MAIL */
04412        closelog();
04413 
04414        openlog(progname, LOG_PID);
04415 #endif /* LOG_MAIL */
04416 }
04417 
04418 /*
04419 **  DKIMF_RESTART_CHECK -- initialize/check restart rate information
04420 **
04421 **  Parameters:
04422 **     n -- size of restart rate array to initialize/enforce
04423 **     t -- maximum time range for restarts (0 == init)
04424 **
04425 **  Return value:
04426 **     TRUE -- OK to continue
04427 **     FALSE -- error
04428 */
04429 
04430 static _Bool
04431 dkimf_restart_check(int n, time_t t)
04432 {
04433        static int idx;                           /* last filled slot */
04434        static int alen;                   /* allocated length */
04435        static time_t *list;
04436 
04437        if (t == 0)
04438        {
04439               alen = n * sizeof(time_t);
04440 
04441               list = (time_t *) malloc(alen);
04442 
04443               if (list == NULL)
04444                      return FALSE;
04445 
04446               memset(list, '\0', alen);
04447 
04448               idx = 0;
04449               alen = n;
04450 
04451               return TRUE;
04452        }
04453        else
04454        {
04455               int which;
04456 
04457               time_t now;
04458 
04459               (void) time(&now);
04460 
04461               which = (idx - 1) % alen;
04462               if (which == -1)
04463                      which = alen - 1;
04464 
04465               if (list[which] != 0 &&
04466                   list[which] + t > now)
04467                      return FALSE;
04468 
04469               list[which] = t;
04470               idx++;
04471 
04472               return TRUE;
04473        }
04474 }
04475 
04476 /*
04477 **  DKIMF_REPTOKEN -- replace a token in an input string with another string
04478 **
04479 **  Parameters:
04480 **     out -- output buffer
04481 **     outlen -- output buffer length
04482 **     in -- input string
04483 **     sub -- substitution string
04484 **
04485 **  Return value:
04486 **     Bytes of output; may be larger than "outlen" if "out" was too small.
04487 */
04488 
04489 size_t
04490 dkimf_reptoken(u_char *out, size_t outlen, u_char *in, u_char *sub)
04491 {
04492        size_t ret = 0;
04493        u_char *p;
04494        u_char *q;
04495        u_char *end;
04496 
04497        assert(out != NULL);
04498        assert(in != NULL);
04499        assert(sub != NULL);
04500 
04501        memset(out, '\0', outlen);
04502 
04503        q = out;
04504        end = q + outlen - 1;
04505 
04506        for (p = in; *p != '\0'; p++)
04507        {
04508               if (*p == '%')
04509               {
04510                      size_t c;
04511 
04512                      c = strlcpy((char *) q, (char *) sub, outlen - ret);
04513                      q += c;
04514                      ret += c;
04515               }
04516               else
04517               {
04518                      if (q < end)
04519                      {
04520                             *q = *p;
04521                             q++;
04522                             ret++;
04523                      }
04524               }
04525        }
04526 
04527        return ret;
04528 }
04529 
04530 /*
04531 **  DKIMF_INSECURE -- see if an open file is safe to use
04532 **
04533 **  Parameters:
04534 **     mode -- mode of an open file
04535 **     grp -- group ID of an open file
04536 **
04537 **  Return value:
04538 **     FALSE iff the file is safe to use.
04539 */
04540 
04541 _Bool
04542 dkimf_insecure(mode_t mode, gid_t grp)
04543 {
04544        /* read/write by others is always bad */
04545        if ((mode & (S_IROTH|S_IWOTH)) != 0)
04546               return TRUE;
04547 
04548        /* read/write by group is bad if it's not a group we're in */
04549        if ((mode & (S_IRGRP|S_IWGRP)) != 0)
04550        {
04551               int c;
04552               int ngroups;
04553               gid_t gid;
04554               gid_t egid;
04555               gid_t gids[NGROUPS_MAX];
04556 
04557               gid = getgid();
04558               egid = getegid();
04559               ngroups = getgroups(NGROUPS_MAX, gids);
04560 
04561               if (grp == gid || grp == egid)
04562                      return FALSE;
04563 
04564               for (c = 0; c < ngroups; c++)
04565               {
04566                      if (grp == gids[c])
04567                             return FALSE;
04568               }
04569 
04570               return TRUE;
04571        }
04572 
04573        /* anything that gets here is safe */
04574        return FALSE;
04575 }
04576 
04577 /*
04578 **  DKIMF_LOADKEY -- resolve a key
04579 **
04580 **  Parameters:
04581 **     buf -- key buffer
04582 **     buflen -- pointer to key buffer's length (updated)
04583 **     insecure -- key is insecure (returned)
04584 **     error -- string returned on error
04585 **
04586 **  Return value:
04587 **     TRUE on successful load, false otherwise
04588 */
04589 
04590 static _Bool
04591 dkimf_loadkey(char *buf, size_t *buflen, _Bool *insecure, char **error)
04592 {
04593        assert(buf != NULL);
04594        assert(buflen != NULL);
04595 
04596        if (buf[0] == '/' || (buf[0] == '.' && buf[1] == '/') ||
04597            (buf[0] == '.' && buf[1] == '.' && buf[2] == '/'))
04598        {
04599               int fd;
04600               int status;
04601               ssize_t rlen;
04602               struct stat s;
04603 
04604               fd = open(buf, O_RDONLY);
04605               if (fd < 0)
04606               {
04607                      if (error != NULL)
04608                             *error = strerror(errno);
04609                      return FALSE;
04610               }
04611 
04612               status = fstat(fd, &s);
04613               if (status != 0 || !S_ISREG(s.st_mode))
04614               {
04615                      if (error != NULL)
04616                      {
04617                             if (!S_ISREG(s.st_mode))
04618                                    *error = "Not a regular file";
04619                             else
04620                                    *error = strerror(errno);
04621                      }
04622                      close(fd);
04623                      return FALSE;
04624               }
04625 
04626               /*
04627               **  XXX -- really should check ancestor directories too,
04628               **  like sendmail's safefile()
04629               */
04630 
04631               if (insecure != NULL)
04632                      *insecure = dkimf_insecure(s.st_mode, s.st_gid);
04633 
04634               *buflen = MIN(s.st_size, *buflen);
04635               rlen = read(fd, buf, *buflen);
04636               close(fd);
04637 
04638               if (rlen < *buflen)
04639                      return FALSE;
04640        }
04641 
04642        return TRUE;
04643 }
04644 
04645 /*
04646 **  DKIMF_ADD_SIGNREQUEST -- add a signing request
04647 **
04648 **  Parameters:
04649 **     dfc -- message context
04650 **     keytable -- table from which to get key
04651 **     keyname -- name of private key to use
04652 **     signer -- signer identity to use
04653 **     signlen -- signature length
04654 **
04655 **  Return value:
04656 **     3 -- substitution token provided but domain not provided
04657 **     2 -- requested key could not be loaded
04658 **     1 -- requested key not found
04659 **     0 -- requested key added
04660 **     -1 -- requested key found but add failed (memory? or format)
04661 */
04662 
04663 static int
04664 dkimf_add_signrequest(struct msgctx *dfc, DKIMF_DB keytable, char *keyname,
04665                       char *signer, ssize_t signlen)
04666 {
04667        _Bool found = FALSE;
04668        size_t keydatasz;
04669        struct signreq *new;
04670        struct dkimf_db_data dbd[3];
04671        char keydata[MAXBUFRSZ + 1];
04672        char domain[DKIM_MAXHOSTNAMELEN + 1];
04673        char selector[BUFRSZ + 1];
04674 
04675        assert(dfc != NULL);
04676 
04677        /*
04678        **  Error out if we want the default key but the key or selector were
04679        **  not provided.
04680        */
04681 
04682        if (keyname == NULL)
04683        {
04684               if (curconf->conf_seckey == NULL ||
04685                   curconf->conf_selector == NULL)
04686                      return 1;
04687        }
04688 
04689        if (keytable != NULL)
04690        {
04691               _Bool insecure;
04692               char *errstr;
04693 
04694               assert(keyname != NULL);
04695 
04696               memset(domain, '\0', sizeof domain);
04697               memset(selector, '\0', sizeof selector);
04698               memset(keydata, '\0', sizeof keydata);
04699 
04700               dbd[0].dbdata_buffer = domain;
04701               dbd[0].dbdata_buflen = sizeof domain - 1;
04702               dbd[0].dbdata_flags = DKIMF_DB_DATA_OPTIONAL;
04703               dbd[1].dbdata_buffer = selector;
04704               dbd[1].dbdata_buflen = sizeof selector - 1;
04705               dbd[1].dbdata_flags = DKIMF_DB_DATA_OPTIONAL;
04706               dbd[2].dbdata_buffer = keydata;
04707               dbd[2].dbdata_buflen = sizeof keydata - 1;
04708               dbd[2].dbdata_flags = DKIMF_DB_DATA_OPTIONAL;
04709 
04710               if (dkimf_db_get(keytable, keyname, strlen(keyname),
04711                                dbd, 3, &found) != 0)
04712                      return -1;
04713 
04714               if (!found)
04715                      return 1;
04716 
04717               if (dbd[0].dbdata_buflen == 0 ||
04718                   dbd[0].dbdata_buflen == (size_t) -1 ||
04719                   dbd[1].dbdata_buflen == 0 ||
04720                   dbd[1].dbdata_buflen == (size_t) -1 ||
04721                   dbd[2].dbdata_buflen == 0 ||
04722                   dbd[2].dbdata_buflen == (size_t) -1)
04723               {
04724                      if (dolog)
04725                      {
04726                             syslog(LOG_ERR,
04727                                    "KeyTable entry for '%s' corrupt",
04728                                    keyname);
04729                      }
04730 
04731                      return 2;
04732               }
04733 
04734               if (domain[0] == '%' && domain[1] == '\0' &&
04735                   dfc->mctx_domain == NULL)
04736               {
04737                      if (dolog)
04738                      {
04739                             syslog(LOG_ERR,
04740                                    "KeyTable entry for '%s' cannot be resolved",
04741                                    keyname);
04742                      }
04743 
04744                      return 3;
04745               }
04746 
04747               if (keydata[0] == '/')
04748               {
04749                      char *d;
04750                      char tmpdata[MAXBUFRSZ + 1];
04751 
04752                      memset(tmpdata, '\0', sizeof tmpdata);
04753 
04754                      if (domain[0] == '%' && domain[1] == '\0')
04755                             d = dfc->mctx_domain;
04756                      else
04757                             d = domain;
04758 
04759                      dkimf_reptoken(tmpdata, sizeof tmpdata, keydata, d);
04760 
04761                      memcpy(keydata, tmpdata, sizeof keydata);
04762               }
04763 
04764               keydatasz = sizeof keydata - 1;
04765               insecure = FALSE;
04766               if (!dkimf_loadkey(dbd[2].dbdata_buffer, &keydatasz,
04767                                  &insecure, &errstr))
04768               {
04769                      if (dolog)
04770                      {
04771                             syslog(LOG_ERR, "can't load key from %s: %s",
04772                                    dbd[2].dbdata_buffer, errstr);
04773                      }
04774 
04775                      return 2;
04776               }
04777 
04778               if (insecure)
04779               {
04780                      if (dolog)
04781                      {
04782                             int sev;
04783 
04784                             sev = (curconf->conf_safekeys ? LOG_ERR
04785                                                           : LOG_WARNING);
04786 
04787                             syslog(sev, "%s: key data is not secure",
04788                                    keyname);
04789                      }
04790 
04791                      if (curconf->conf_safekeys)
04792                             return 2;
04793               }
04794        }
04795 
04796        new = malloc(sizeof *new);
04797        if (new == NULL)
04798               return -1;
04799 
04800        new->srq_next = NULL;
04801        new->srq_dkim = NULL;
04802        new->srq_domain = NULL;
04803        new->srq_selector = NULL;
04804        new->srq_keydata = NULL;
04805        new->srq_signlen = signlen;
04806        if (signer != NULL && signer[0] != '\0')
04807               new->srq_signer = (u_char *) strdup(signer);
04808        else
04809               new->srq_signer = NULL;
04810 
04811        if (keytable != NULL)
04812        {
04813               if (domain[0] == '%' && domain[1] == '\0')
04814                      new->srq_domain = (u_char *) strdup((char *) dfc->mctx_domain);
04815               else
04816                      new->srq_domain = (u_char *) strdup((char *) domain);
04817 
04818               new->srq_selector = (u_char *) strdup((char *) selector);
04819               new->srq_keydata = (void *) malloc(keydatasz + 1);
04820               if (new->srq_keydata == NULL)
04821               {
04822                      free(new);
04823                      return -1;
04824               }
04825               memset(new->srq_keydata, '\0', keydatasz + 1);
04826               memcpy(new->srq_keydata, dbd[2].dbdata_buffer, keydatasz);
04827        }
04828 
04829        if (dfc->mctx_srtail != NULL)
04830               dfc->mctx_srtail->srq_next = new;
04831        else
04832               dfc->mctx_srtail = new;
04833 
04834        if (dfc->mctx_srhead == NULL)
04835               dfc->mctx_srhead = new;
04836 
04837        return 0;
04838 }
04839 
04840 /*
04841 **  DKIMF_MSR_HEADER -- process headers for multiple signing requests
04842 **
04843 **  Parameters:
04844 **     srh -- head of the signature request list
04845 **     last -- last handle processed (returned on error)
04846 **     header -- header field name and value
04847 **     headerlen -- number of bytes at "header"
04848 **
04849 **  Return value:
04850 **     A DKIM_STAT_* constant, either DKIM_STAT_OK if all of them passed
04851 **     or some other constant if one of them failed.
04852 */
04853 
04854 static DKIM_STAT
04855 dkimf_msr_header(struct signreq *sr, DKIM **last, u_char *header,
04856                  size_t headerlen)
04857 {
04858        DKIM_STAT status;
04859 
04860        assert(sr != NULL);
04861        assert(header != NULL);
04862 
04863        while (sr != NULL)
04864        {
04865               status = dkim_header(sr->srq_dkim, header, headerlen);
04866               if (status != DKIM_STAT_OK)
04867               {
04868                      if (last != NULL)
04869                             *last = sr->srq_dkim;
04870                      return status;
04871               }
04872               sr = sr->srq_next;
04873        }
04874 
04875        return DKIM_STAT_OK;
04876 }
04877 
04878 /*
04879 **  DKIMF_MSR_EOH -- process end-of-headers for multiple signing requests
04880 **
04881 **  Parameters:
04882 **     srh -- head of the signature request list
04883 **     last -- last DKIM handle processed (returned on error)
04884 **
04885 **  Return value:
04886 **     A DKIM_STAT_* constant, either DKIM_STAT_OK if all of them passed
04887 **     or some other constant if one of them failed.
04888 */
04889 
04890 static DKIM_STAT
04891 dkimf_msr_eoh(struct signreq *sr, DKIM **last)
04892 {
04893        DKIM_STAT status;
04894 
04895        assert(sr != NULL);
04896 
04897        while (sr != NULL)
04898        {
04899               status = dkim_eoh(sr->srq_dkim);
04900               if (status != DKIM_STAT_OK)
04901               {
04902                      if (last != NULL)
04903                             *last = sr->srq_dkim;
04904                      return status;
04905               }
04906               sr = sr->srq_next;
04907        }
04908 
04909        return DKIM_STAT_OK;
04910 }
04911 
04912 /*
04913 **  DKIMF_MSR_BODY -- process a body chunk for multiple signing requests
04914 **
04915 **  Parameters:
04916 **     srh -- head of the signature request list
04917 **     last -- last DKIM handle processed (returned on error)
04918 **     body -- body chunk
04919 **     bodylen -- body length
04920 **
04921 **  Return value:
04922 **     A DKIM_STAT_* constant, either DKIM_STAT_OK if all of them passed
04923 **     or some other constant if one of them failed.
04924 */
04925 
04926 static DKIM_STAT
04927 dkimf_msr_body(struct signreq *sr, DKIM **last, u_char *body, size_t bodylen)
04928 {
04929        DKIM_STAT status;
04930 
04931        assert(sr != NULL);
04932        assert(body != NULL);
04933 
04934        while (sr != NULL)
04935        {
04936               status = dkim_body(sr->srq_dkim, body, bodylen);
04937               if (status != DKIM_STAT_OK)
04938               {
04939                      if (last != NULL)
04940                             *last = sr->srq_dkim;
04941                      return status;
04942               }
04943 
04944               sr = sr->srq_next;
04945        }
04946 
04947        return DKIM_STAT_OK;
04948 }
04949 
04950 /*
04951 **  DKIMF_MSR_MINBODY -- determine minimum body required to satisfy all
04952 **                       all open canonicalizations
04953 **
04954 **  Parameters:
04955 **     srh -- head of the signature request list
04956 **
04957 **  Return value:
04958 **     Maximum of all dkim_minbody() returns.
04959 */
04960 
04961 static int
04962 dkimf_msr_minbody(struct signreq *sr)
04963 {
04964        u_long mb = 0;
04965        u_long ret = 0;
04966 
04967        assert(sr != NULL);
04968 
04969        while (sr != NULL)
04970        {
04971               ret = dkim_minbody(sr->srq_dkim);
04972               if (ret > mb)
04973                      mb = ret;
04974               sr = sr->srq_next;
04975        }
04976 
04977        return mb;;
04978 }
04979 
04980 /*
04981 **  DKIMF_MSR_EOM -- process end-of-message for multiple signing requests
04982 **
04983 **  Parameters:
04984 **     srh -- head of the signature request list
04985 **     last -- last DKIM handle processed (returned)
04986 **
04987 **  Return value:
04988 **     A DKIM_STAT_* constant, either DKIM_STAT_OK if all of them passed
04989 **     or some other constant if one of them failed.
04990 */
04991 
04992 static DKIM_STAT
04993 dkimf_msr_eom(struct signreq *sr, DKIM **last)
04994 {
04995        _Bool testkey;
04996        DKIM_STAT status;
04997 
04998        assert(sr != NULL);
04999 
05000        while (sr != NULL)
05001        {
05002               status = dkim_eom(sr->srq_dkim, &testkey);
05003               if (status != DKIM_STAT_OK)
05004               {
05005                      if (last != NULL)
05006                             *last = sr->srq_dkim;
05007                      return status;
05008               }
05009               sr = sr->srq_next;
05010        }
05011 
05012        return DKIM_STAT_OK;
05013 }
05014 
05015 /*
05016 **  DKIMF_PRESCREEN -- check signatures against third-party limitations
05017 **
05018 **  Parameters:
05019 **     dkim -- DKIM handle
05020 **     sigs -- array of signatures
05021 **     nsigs -- size of signature array
05022 **
05023 **  Return value:
05024 **     DKIM_CBSTAT_CONTINUE
05025 */
05026 
05027 static DKIM_CBSTAT
05028 dkimf_prescreen(DKIM *dkim, DKIM_SIGINFO **sigs, int nsigs)
05029 {
05030        int c;
05031        unsigned int ni = 0;
05032        u_char *domain;
05033        u_char *sdomain;
05034        SMFICTX *ctx;
05035        connctx cc;
05036        msgctx dfc;
05037        struct dkimf_config *conf;
05038 
05039        ctx = (SMFICTX *) dkim_get_user_context(dkim);
05040        cc = (connctx) dkimf_getpriv(ctx);
05041        conf = cc->cctx_config;
05042        dfc = cc->cctx_msg;
05043        domain = dkim_getdomain(dkim);
05044 
05045        if (conf->conf_maxverify > 0)
05046        {
05047               int n;
05048               _Bool *ig = NULL;
05049 
05050               ig = (_Bool *) malloc(sizeof(_Bool) * nsigs);
05051               if (ig == NULL)
05052                      return DKIM_CBSTAT_ERROR;
05053 
05054               /* mark everything to be ignored */
05055               for (c = 0; c < nsigs; c++)
05056                      ig[c] = TRUE;
05057 
05058               n = conf->conf_maxverify;
05059 
05060               if (conf->conf_thirdpartydb != NULL)
05061               {
05062                      _Bool found;
05063 
05064                      /* unmark sigs that are explicitly trusted */
05065                      for (c = 0; c < nsigs; c++)
05066                      {
05067                             sdomain = dkim_sig_getdomain(sigs[c]);
05068 
05069                             found = FALSE;
05070 
05071                             if (dkimf_db_get(conf->conf_thirdpartydb,
05072                                              (char *) sdomain, 0, NULL, 0,
05073                                              &found) != 0)
05074                             {
05075                                    free(ig);
05076                                    return DKIM_CBSTAT_ERROR;
05077                             }
05078 
05079                             if (found)
05080                             {
05081                                    ig[c] = FALSE;
05082                                    n--;
05083                             }
05084                      }
05085               }
05086 
05087               /* unmark from the top down any that don't exceed the limit */
05088               for (c = 0; c < nsigs && n > 0; c++)
05089               {
05090                      if (ig[c])
05091                      {
05092                             n--;
05093                             ig[c] = FALSE;
05094                      }
05095               }
05096 
05097               /* mark what's left to be ignored */
05098               for (c = 0; c < nsigs; c++)
05099               {
05100                      if (ig[c])
05101                      {
05102                             dkim_sig_ignore(sigs[c]);
05103                             ni++;
05104                      }
05105               }
05106 
05107               if (conf->conf_dolog && ni > 0)
05108               {
05109                      syslog(LOG_INFO, "%s: ignoring %u signature%s",
05110                             dkim_getid(dkim), ni, ni == 1 ? "" : "s");
05111               }
05112 
05113               free(ig);
05114 
05115               return DKIM_CBSTAT_CONTINUE;
05116        }
05117 
05118        /* ignore signatures which are neither first-party nor trusted */
05119        for (c = 0; c < nsigs; c++)
05120        {
05121               sdomain = dkim_sig_getdomain(sigs[c]);
05122 
05123               /* author domain */
05124               if (strcasecmp((char *) sdomain, (char *) domain) == 0)
05125                      continue;
05126 
05127               /* trusted third party domain */
05128               if (conf->conf_thirdpartydb != NULL)
05129               {
05130                      _Bool found = FALSE;
05131 
05132                      if (dkimf_db_get(conf->conf_thirdpartydb,
05133                                          (char *) sdomain, 0, NULL, 0,
05134                                          &found) != 0)
05135                             return DKIM_CBSTAT_ERROR;
05136 
05137                      if (found)
05138                             continue;
05139               }
05140 
05141               /* neither; arrange to ignore it */
05142               dkim_sig_ignore(sigs[c]);
05143 
05144               if (conf->conf_dolog)
05145               {
05146                      syslog(LOG_INFO, "%s: ignoring signature from %s",
05147                             dfc->mctx_jobid, sdomain);
05148               }
05149        }
05150 
05151        return DKIM_CBSTAT_CONTINUE;
05152 }
05153 
05154 /*
05155 **  DKIMF_ARFTYPE -- return ARF message type to report
05156 **
05157 **  Parameters:
05158 **     dfc -- DKIM filter context
05159 **
05160 **  Return value:
05161 **     An ARF_TYPE_* constant.
05162 */
05163 
05164 static int
05165 dkimf_arftype(msgctx dfc)
05166 {
05167        assert(dfc != NULL);
05168 
05169        if (dfc->mctx_susp)
05170               return ARF_TYPE_FRAUD;
05171        else
05172               return ARF_TYPE_AUTHFAIL;
05173 }
05174 
05175 /*
05176 **  DKIMF_ARFDKIM -- return an appropriate ARF DKIM failure code
05177 **
05178 **  Parameters:
05179 **     dfc -- DKIM filter context
05180 **
05181 **  Return value:
05182 **     An ARF_DKIMF_* constant.
05183 */
05184 
05185 static int
05186 dkimf_arfdkim(msgctx dfc)
05187 {
05188        DKIM_SIGINFO *sig;
05189 
05190        assert(dfc != NULL);
05191 
05192        sig = dkim_getsignature(dfc->mctx_dkimv);
05193        if (sig == NULL)
05194               return ARF_DKIMF_UNKNOWN;
05195 
05196        if (dkim_sig_getbh(sig) == DKIM_SIGBH_MISMATCH)
05197               return ARF_DKIMF_BODYHASH;
05198 
05199        switch (dkim_sig_geterror(sig))
05200        {
05201          case DKIM_SIGERROR_BADSIG:
05202               return ARF_DKIMF_SIGNATURE;
05203 
05204          case DKIM_SIGERROR_KEYREVOKED:
05205               return ARF_DKIMF_REVOKED;
05206 
05207          case DKIM_SIGERROR_VERSION:
05208          case DKIM_SIGERROR_INVALID_HC:
05209          case DKIM_SIGERROR_INVALID_BC:
05210          case DKIM_SIGERROR_MISSING_A:
05211          case DKIM_SIGERROR_INVALID_A:
05212          case DKIM_SIGERROR_MISSING_H:
05213          case DKIM_SIGERROR_INVALID_L:
05214          case DKIM_SIGERROR_INVALID_Q:
05215          case DKIM_SIGERROR_INVALID_QO:
05216          case DKIM_SIGERROR_MISSING_D:
05217          case DKIM_SIGERROR_EMPTY_D:
05218          case DKIM_SIGERROR_MISSING_S:
05219          case DKIM_SIGERROR_EMPTY_S:
05220          case DKIM_SIGERROR_MISSING_B:
05221          case DKIM_SIGERROR_EMPTY_B:
05222          case DKIM_SIGERROR_CORRUPT_B:
05223          case DKIM_SIGERROR_DNSSYNTAX:
05224          case DKIM_SIGERROR_MISSING_BH:
05225          case DKIM_SIGERROR_EMPTY_BH:
05226          case DKIM_SIGERROR_CORRUPT_BH:
05227          case DKIM_SIGERROR_MULTIREPLY:
05228          case DKIM_SIGERROR_EMPTY_H:
05229          case DKIM_SIGERROR_INVALID_H:
05230          case DKIM_SIGERROR_TOOLARGE_L:
05231          case DKIM_SIGERROR_KEYVERSION:
05232          case DKIM_SIGERROR_KEYUNKNOWNHASH:
05233          case DKIM_SIGERROR_KEYTYPEMISSING:
05234          case DKIM_SIGERROR_KEYTYPEUNKNOWN:
05235               return ARF_DKIMF_SYNTAX;
05236 
05237          default:
05238               return ARF_DKIMF_OTHER;
05239        }
05240 }
05241 
05242 /*
05243 **  DKIMF_REPORTADDR -- set reporting address
05244 **
05245 **  Parameters:
05246 **     conf -- current configuration
05247 **
05248 **  Return value:
05249 **     None.
05250 */
05251 
05252 static void
05253 dkimf_reportaddr(struct dkimf_config *conf)
05254 {
05255        uid_t uid;
05256        struct passwd *pw;
05257        assert(conf != NULL);
05258 
05259        if (conf->conf_reportaddr != NULL)
05260        {
05261               int status;
05262               u_char *user;
05263               u_char *domain;
05264               u_char env[MAXADDRESS + 1]; /* reporting address */
05265 
05266               strlcpy(reportaddr, conf->conf_reportaddr, sizeof reportaddr);
05267               strlcpy((char *) env, conf->conf_reportaddr,
05268                       sizeof reportaddr);
05269               status = dkim_mail_parse(env, &user, &domain);
05270               if (status == 0 && user != NULL && domain != NULL)
05271               {
05272                      snprintf(reportcmd, sizeof reportcmd,
05273                               "%s -t -f%s@%s",
05274                               conf->conf_mtacommand, user, domain);
05275 
05276                      return;
05277               }
05278               else
05279               {
05280                      if (dolog)
05281                      {
05282                             syslog(LOG_ERR,
05283                                    "error parsing ReportAddress; using default");
05284                      }
05285               }
05286        }
05287 
05288        /* not successful case has already returned. Make up a value if not
05289         * set of an error occurs */
05290 
05291        uid = geteuid();
05292        pw = getpwuid(uid);
05293 
05294        if (pw == NULL)
05295        {
05296               snprintf(reportaddr, sizeof reportaddr,
05297                        "%u@%s", uid, myhostname);
05298        }
05299        else
05300        {
05301               snprintf(reportaddr, sizeof reportaddr,
05302                        "%s@%s", pw->pw_name, myhostname);
05303        }
05304 
05305        snprintf(reportcmd, sizeof reportcmd, "%s -t -f%s",
05306                 conf->conf_mtacommand, reportaddr);
05307 }
05308 
05309 /*
05310 **  DKIMF_CONFIGLOOKUP -- look up the integer code for a config option or value
05311 **
05312 **  Parameters:
05313 **     opt -- option to look up
05314 **     table -- lookup table to use
05315 **
05316 **  Return value:
05317 **     Integer version of the option, or -1 on error.
05318 */
05319 
05320 static int
05321 dkimf_configlookup(char *opt, struct lookup *table)
05322 {
05323        int c;
05324 
05325        for (c = 0; ; c++)
05326        {
05327               if (table[c].str == NULL ||
05328                   strcasecmp(opt, table[c].str) == 0)
05329                      return table[c].code;
05330        }
05331 }
05332 
05333 /*
05334 **  DKIMF_LOCAL_ADSP -- check for a local ADSP assertion
05335 **
05336 **  Parameters:
05337 **     conf -- configuration handle to check
05338 **     domain -- domain to evaluate
05339 **     pcode -- policy code (returned)
05340 **
05341 **  Return value:
05342 **     1 -- match, "pcode" updated
05343 **     0 -- no match, "pcode" unchanged
05344 */
05345 
05346 static int
05347 dkimf_local_adsp(struct dkimf_config *conf, char *domain, dkim_policy_t *pcode)
05348 {
05349        assert(conf != NULL);
05350        assert(domain != NULL);
05351        assert(pcode != NULL);
05352 
05353        if (conf->conf_localadsp_db != NULL)
05354        {
05355               _Bool found;
05356               size_t plen;
05357               char *p;
05358               char policy[BUFRSZ];
05359               struct dkimf_db_data dbd;
05360 
05361               memset(policy, '\0', sizeof policy);
05362               plen = sizeof policy;
05363 
05364               dbd.dbdata_buffer = policy;
05365               dbd.dbdata_buflen = plen;
05366               dbd.dbdata_flags = 0;
05367 
05368               if (dkimf_db_get(conf->conf_localadsp_db, domain, 0, 
05369                                     &dbd, 1, &found) != 0)
05370                      return 0;
05371 
05372               if (policy[0] == '\0')
05373                      found = FALSE;
05374 
05375               for (p = strchr(domain, '.');
05376                    p != NULL && !found;
05377                    p = strchr(p + 1, '.'))
05378               {
05379                      dbd.dbdata_buflen = plen;
05380 
05381                      if (dkimf_db_get(conf->conf_localadsp_db, p, 0,
05382                                            &dbd, 1, &found) != 0)
05383                             return 0;
05384 
05385                      if (policy[0] == '\0')
05386                             found = FALSE;
05387               }
05388 
05389               if (found)
05390               {
05391                      dkim_policy_t tmpp;
05392 
05393                      tmpp = dkimf_configlookup(policy, dkimf_policy);
05394                      if (tmpp != -1)
05395                      {
05396                             *pcode = tmpp;
05397                             return 1;
05398                      }
05399               }
05400        }
05401 
05402        return 0;
05403 }
05404 
05405 /*
05406 **  DKIMF_GETDKIM -- retrieve DKIM handle in use
05407 **
05408 **  Parameters:
05409 **     vp -- opaque pointer (from test.c)
05410 **
05411 **  Return value:
05412 **     DKIM handle in use, or NULL.
05413 */
05414 
05415 DKIM *
05416 dkimf_getdkim(void *vp)
05417 {
05418        struct connctx *cc;
05419 
05420        assert(vp != NULL);
05421 
05422        cc = vp;
05423        if (cc->cctx_msg != NULL)
05424               return cc->cctx_msg->mctx_dkimv;
05425        else
05426               return NULL;
05427 }
05428 
05429 /*
05430 **  DKIMF_GETSRLIST -- retrieve signing request list
05431 **
05432 **  Parameters:
05433 **     vp -- opaque pointer (from test.c)
05434 **
05435 **  Return value:
05436 **     Head of the signing request list.
05437 */
05438 
05439 struct signreq *
05440 dkimf_getsrlist(void *vp)
05441 {
05442        struct connctx *cc;
05443 
05444        assert(vp != NULL);
05445 
05446        cc = vp;
05447        if (cc->cctx_msg != NULL)
05448               return cc->cctx_msg->mctx_srhead;
05449        else
05450               return NULL;
05451 }
05452 
05453 /*
05454 **  DKIMF_SIGHANDLER -- signal handler
05455 **
05456 **  Parameters:
05457 **     sig -- signal received
05458 **
05459 **  Return value:
05460 **     None.
05461 */
05462 
05463 static void
05464 dkimf_sighandler(int sig)
05465 {
05466        if (sig == SIGINT || sig == SIGTERM || sig == SIGHUP)
05467        {
05468               diesig = sig;
05469               die = TRUE;
05470        }
05471        else if (sig == SIGUSR1)
05472        {
05473               if (conffile != NULL)
05474                      reload = TRUE;
05475        }
05476 }
05477 
05478 /*
05479 **  DKIMF_RELOADER -- reload signal thread
05480 **
05481 **  Parameters:
05482 **     vp -- void pointer required by thread API but not used
05483 **
05484 **  Return value:
05485 **     NULL.
05486 */
05487 
05488 static void *
05489 dkimf_reloader(/* UNUSED */ void *vp)
05490 {
05491        int sig;
05492        sigset_t mask;
05493 
05494        (void) pthread_detach(pthread_self());
05495 
05496        sigemptyset(&mask);
05497        sigaddset(&mask, SIGUSR1);
05498 
05499        while (!die)
05500        {
05501               (void) sigwait(&mask, &sig);
05502 
05503               if (conffile != NULL)
05504                      reload = TRUE;
05505        }
05506 
05507        return NULL;
05508 }
05509 
05510 /*
05511 **  DKIMF_KILLCHILD -- kill child process
05512 **
05513 **  Parameters:
05514 **     pid -- process ID to signal
05515 **     sig -- signal to use
05516 **     dolog -- log it?
05517 **
05518 **  Return value:
05519 **     None.
05520 */
05521 
05522 static void
05523 dkimf_killchild(pid_t pid, int sig, _Bool dolog)
05524 {
05525        if (kill(pid, sig) == -1 && dolog)
05526        {
05527               syslog(LOG_ERR, "kill(%d, %d): %s", pid, sig,
05528                      strerror(errno));
05529        }
05530 }
05531 
05532 /*
05533 **  DKIMF_ZAPKEY -- clobber the copy of the private key
05534 **
05535 **  Parameters:
05536 **     conf -- configuration handle in which to clobber the key
05537 **
05538 **  Return value:
05539 **     None.
05540 */
05541 
05542 static void
05543 dkimf_zapkey(struct dkimf_config *conf)
05544 {
05545        assert(conf != NULL);
05546 
05547        if (conf->conf_seckey != NULL)
05548        {
05549               memset(conf->conf_seckey, '\0', conf->conf_keylen);
05550               free(conf->conf_seckey);
05551               conf->conf_seckey = NULL;
05552        }
05553 }
05554 
05555 /*
05556 **  DKIMF_AUTHORSIGOK -- return TRUE iff a message was signed with an
05557 **                       author signature that passed
05558 **
05559 **  Parameters:
05560 **     msg -- a message context handle
05561 **
05562 **  Return value:
05563 **     TRUE iff the message referenced by "dkim" was signed with an
05564 **     author signature and that signature passed.
05565 */
05566 
05567 static _Bool
05568 dkimf_authorsigok(msgctx msg)
05569 {
05570        DKIM_STAT status;
05571        int c;
05572        int nsigs;
05573        DKIM_SIGINFO **sigs;
05574 
05575        assert(msg != NULL);
05576 
05577        status = dkim_getsiglist(msg->mctx_dkimv, &sigs, &nsigs);
05578        if (status != DKIM_STAT_OK)
05579               return FALSE;
05580 
05581        for (c = 0; c < nsigs; c++)
05582        {
05583               /* skip signatures with errors */
05584               if (dkim_sig_geterror(sigs[c]) != DKIM_SIGERROR_UNKNOWN &&
05585                   dkim_sig_geterror(sigs[c]) != DKIM_SIGERROR_OK)
05586                      continue;
05587 
05588               if (strcasecmp((char *) dkim_sig_getdomain(sigs[c]),
05589                              (char *) msg->mctx_domain) == 0 &&
05590                   (dkim_sig_getflags(sigs[c]) & DKIM_SIGFLAG_PASSED) != 0 &&
05591                   dkim_sig_getbh(sigs[c]) == DKIM_SIGBH_MATCH)
05592                      return TRUE;
05593        }
05594 
05595        return FALSE;
05596 }
05597 
05598 /*
05599 **  DKIMF_CONFIG_NEW -- get a new configuration handle
05600 **
05601 **  Parameters:
05602 **     None.
05603 **
05604 **  Return value:
05605 **     A new configuration handle, or NULL on error.
05606 */
05607 
05608 static struct dkimf_config *
05609 dkimf_config_new(void)
05610 {
05611        struct dkimf_config *new;
05612 
05613        new = (struct dkimf_config *) malloc(sizeof(struct dkimf_config));
05614        if (new == NULL)
05615               return NULL;
05616 
05617        memset(new, '\0', sizeof(struct dkimf_config));
05618        new->conf_hdrcanon = DKIM_CANON_DEFAULT;
05619        new->conf_bodycanon = DKIM_CANON_DEFAULT;
05620        new->conf_dnstimeout = DEFTIMEOUT;
05621        new->conf_maxverify = DEFMAXVERIFY;
05622        new->conf_maxhdrsz = DEFMAXHDRSZ;
05623        new->conf_signbytes = -1L;
05624        new->conf_sigmintype = SIGMIN_BYTES;
05625 #ifdef _FFR_DKIM_REPUTATION
05626        new->conf_repreject = DKIM_REP_DEFREJECT;
05627 #endif /* _FFR_DKIM_REPUTATION */
05628 #ifdef _FFR_REPUTATION
05629        new->conf_repfactor = DKIMF_REP_DEFFACTOR;
05630        new->conf_repcachettl = DKIMF_REP_DEFCACHETTL;
05631 #endif /* _FFR_REPUTATION */
05632        new->conf_safekeys = TRUE;
05633        new->conf_adspaction = SMFIS_CONTINUE;
05634 #ifdef _FFR_STATS
05635        new->conf_reporthost = myhostname;
05636 #endif /* _FFR_STATS */
05637 #ifdef _FFR_RATE_LIMIT
05638        new->conf_flowdatattl = DEFFLOWDATATTL;
05639        new->conf_flowfactor = 1;
05640 #endif /* _FFR_RATE_LIMIT */
05641        new->conf_mtacommand = SENDMAIL_PATH;
05642 #ifdef _FFR_ATPS
05643        new->conf_atpshash = dkimf_atpshash[0].str;
05644 #endif /* _FFR_ATPS */
05645        new->conf_selectcanonhdr = XSELECTCANONHDR;
05646 
05647        memcpy(&new->conf_handling, &defaults, sizeof new->conf_handling);
05648 
05649        return new;
05650 }
05651 
05652 /*
05653 **  DKIMF_CONFIG_FREE -- destroy a configuration handle
05654 **
05655 **  Parameters:
05656 **     conf -- pointer to the configuration handle to be destroyed
05657 **
05658 **  Return value:
05659 **     None.
05660 */
05661 
05662 static void
05663 dkimf_config_free(struct dkimf_config *conf)
05664 {
05665        assert(conf != NULL);
05666        assert(conf->conf_refcnt == 0);
05667 
05668        dkimf_zapkey(conf);
05669 
05670        if (conf->conf_libopendkim != NULL)
05671               dkim_close(conf->conf_libopendkim);
05672 
05673        if (conf->conf_testdnsdb != NULL)
05674               dkimf_db_close(conf->conf_testdnsdb);
05675 
05676        if (conf->conf_domainsdb != NULL)
05677               dkimf_db_close(conf->conf_domainsdb);
05678 
05679        if (conf->conf_bldb != NULL)
05680               dkimf_db_close(conf->conf_bldb);
05681 
05682        if (conf->conf_domlist != NULL)
05683               free(conf->conf_domlist);
05684 
05685        if (conf->conf_omithdrdb != NULL)
05686               dkimf_db_close(conf->conf_omithdrdb);
05687 
05688        if (conf->conf_thirdpartydb != NULL)
05689               dkimf_db_close(conf->conf_thirdpartydb);
05690 
05691        if (conf->conf_signhdrsdb != NULL)
05692               dkimf_db_close(conf->conf_signhdrsdb);
05693 
05694        if (conf->conf_alwayshdrsdb != NULL)
05695               dkimf_db_close(conf->conf_alwayshdrsdb);
05696 
05697        if (conf->conf_senderhdrsdb != NULL)
05698               dkimf_db_close(conf->conf_senderhdrsdb);
05699 
05700 #ifdef _FFR_OVERSIGN
05701        if (conf->conf_oversigndb != NULL)
05702               dkimf_db_close(conf->conf_oversigndb);
05703 #endif /* _FFR_OVERSIGN */
05704 
05705        if (conf->conf_mtasdb != NULL)
05706               dkimf_db_close(conf->conf_mtasdb);
05707 
05708        if (conf->conf_macrosdb != NULL)
05709               dkimf_db_close(conf->conf_macrosdb);
05710 
05711        if (conf->conf_mbsdb != NULL)
05712               dkimf_db_close(conf->conf_mbsdb);
05713 
05714        if (conf->conf_dontsigntodb != NULL)
05715               dkimf_db_close(conf->conf_dontsigntodb);
05716 
05717 #ifdef _FFR_ATPS
05718        if (conf->conf_atpsdb != NULL)
05719               dkimf_db_close(conf->conf_atpsdb);
05720 #endif /* _FFR_ATPS */
05721 
05722 #ifdef _FFR_DKIM_REPUTATION
05723        if (conf->conf_reproot != NULL)
05724               free(conf->conf_reproot);
05725 #endif /* _FFR_DKIM_REPUTATION */
05726 
05727        if (conf->conf_authservid != NULL)
05728               free(conf->conf_authservid);
05729 
05730        if (conf->conf_peerdb != NULL)
05731               dkimf_db_close(conf->conf_peerdb);
05732 
05733        if (conf->conf_internal != NULL)
05734               dkimf_db_close(conf->conf_internal);
05735 
05736        if (conf->conf_exignore != NULL)
05737               dkimf_db_close(conf->conf_exignore);
05738 
05739        if (conf->conf_exemptdb != NULL)
05740               dkimf_db_close(conf->conf_exemptdb);
05741 
05742 #ifdef _FFR_REPLACE_RULES
05743        if (conf->conf_replist != NULL)
05744               dkimf_free_replist(conf->conf_replist);
05745        if (conf->conf_rephdrsdb != NULL)
05746               dkimf_db_close(conf->conf_rephdrsdb);
05747 #endif /* _FFR_REPLACE_RULES */
05748 
05749 #ifdef _FFR_VBR
05750        if (conf->conf_vbr_trusteddb != NULL)
05751               dkimf_db_close(conf->conf_vbr_trusteddb);
05752 #endif /* _FFR_VBR */
05753 
05754        if (conf->conf_nosignpats != NULL)
05755        {
05756               int n;
05757 
05758               for (n = 0; conf->conf_nosignpats[n] != NULL; n++)
05759                      regfree(conf->conf_nosignpats[n]);
05760 
05761               free(conf->conf_nosignpats);
05762        }
05763 
05764        if (conf->conf_localadsp_db != NULL)
05765               dkimf_db_close(conf->conf_localadsp_db);
05766 
05767 #ifdef _FFR_RESIGN
05768        if (conf->conf_resigndb != NULL)
05769               dkimf_db_close(conf->conf_resigndb);
05770 #endif /* _FFR_RESIGN */
05771 
05772 #ifdef _FFR_RATE_LIMIT
05773        if (conf->conf_ratelimitdb != NULL)
05774               dkimf_db_close(conf->conf_ratelimitdb);
05775        if (conf->conf_flowdatadb != NULL)
05776               dkimf_db_close(conf->conf_flowdatadb);
05777 #endif /* _FFR_RATE_LIMIT */
05778 
05779 #ifdef _FFR_REPUTATION
05780        if (conf->conf_repratiosdb != NULL)
05781               dkimf_db_close(conf->conf_repratiosdb);
05782        if (conf->conf_replimitsdb != NULL)
05783               dkimf_db_close(conf->conf_replimitsdb);
05784        if (conf->conf_replimitmodsdb != NULL)
05785               dkimf_db_close(conf->conf_replimitmodsdb);
05786        if (conf->conf_repspamcheck != NULL)
05787               regfree(&conf->conf_repspamre);
05788        if (conf->conf_rep != NULL)
05789               dkimf_rep_close(conf->conf_rep);
05790 #endif /* _FFR_REPUTATION */
05791 
05792 #ifdef USE_LUA
05793        if (conf->conf_setupscript != NULL)
05794               free(conf->conf_setupscript);
05795        if (conf->conf_setupfunc != NULL)
05796               free(conf->conf_setupfunc);
05797        if (conf->conf_screenscript != NULL)
05798               free(conf->conf_screenscript);
05799        if (conf->conf_screenfunc != NULL)
05800               free(conf->conf_screenfunc);
05801 # ifdef _FFR_STATSEXT
05802        if (conf->conf_statsscript != NULL)
05803               free(conf->conf_statsscript);
05804        if (conf->conf_statsfunc != NULL)
05805               free(conf->conf_statsfunc);
05806 # endif /* _FFR_STATSEXT */
05807        if (conf->conf_finalscript != NULL)
05808               free(conf->conf_finalscript);
05809        if (conf->conf_finalfunc != NULL)
05810               free(conf->conf_finalfunc);
05811 #endif /* USE_LUA */
05812 
05813 #ifdef USE_UNBOUND
05814        if (conf->conf_unbound != NULL)
05815               dkimf_unbound_close(conf->conf_unbound);
05816 #endif /* USE_UNBOUND */
05817 
05818 #ifdef USE_ARLIB
05819        if (conf->conf_arlib != NULL)
05820               ar_shutdown(conf->conf_arlib);
05821 #endif /* USE_ARLIB */
05822 
05823        if (conf->conf_data != NULL)
05824               config_free(conf->conf_data);
05825 
05826        free(conf);
05827 }
05828 
05829 /*
05830 **  DKIMF_PARSEHANDLER -- parse a handler
05831 **
05832 **  Parameters:
05833 **     cfg -- configuration data structure to check
05834 **     name -- handler name
05835 **     hndl -- handler structure to update
05836 **
05837 **  Return value:
05838 **     None.
05839 */
05840 
05841 static void
05842 dkimf_parsehandler(struct config *cfg, char *name, struct handling *hndl)
05843 {
05844        int action;
05845        char *val = NULL;
05846 
05847        assert(name != NULL);
05848        assert(strncasecmp(name, "on-", 3) == 0);
05849        assert(hndl != NULL);
05850 
05851        if (cfg == NULL)
05852               return;
05853 
05854        (void) config_get(cfg, name, &val, sizeof val);
05855 
05856        if (val != NULL)
05857        {
05858               action = dkimf_configlookup(val, dkimf_values);
05859               if (action != -1)
05860               {
05861                      switch (dkimf_configlookup(name + 3, dkimf_params))
05862                      {
05863                        case HNDL_DEFAULT:
05864                             hndl->hndl_nosig = action;
05865                             hndl->hndl_badsig = action;
05866                             hndl->hndl_dnserr = action;
05867                             hndl->hndl_internal = action;
05868                             hndl->hndl_security = action;
05869                             hndl->hndl_nokey = action;
05870                             hndl->hndl_policyerr = action;
05871 #ifdef _FFR_REPUTATION
05872                             hndl->hndl_reperr = action;
05873 #endif /* _FFR_REPUTATION */
05874                             break;
05875 
05876                        case HNDL_NOSIGNATURE:
05877                             hndl->hndl_nosig = action;
05878                             break;
05879 
05880                        case HNDL_BADSIGNATURE:
05881                             hndl->hndl_badsig = action;
05882                             break;
05883 
05884                        case HNDL_DNSERROR:
05885                             hndl->hndl_dnserr = action;
05886                             break;
05887 
05888                        case HNDL_INTERNAL:
05889                             hndl->hndl_internal = action;
05890                             break;
05891 
05892                        case HNDL_SECURITY:
05893                             hndl->hndl_security = action;
05894                             break;
05895 
05896                        case HNDL_NOKEY:
05897                             hndl->hndl_nokey = action;
05898                             break;
05899 
05900                        case HNDL_POLICYERROR:
05901                             hndl->hndl_policyerr = action;
05902                             break;
05903 
05904 #ifdef _FFR_REPUTATION
05905                        case HNDL_REPERROR:
05906                             hndl->hndl_reperr = action;
05907                             break;
05908 #endif /* _FFR_REPUTATION */
05909 
05910                        default:
05911                             break;
05912                      }
05913               }
05914        }
05915 }
05916 
05917 /*
05918 **  DKIMF_CONFIG_LOAD -- load a configuration handle based on file content
05919 **
05920 **  Paramters:
05921 **     data -- configuration data loaded from config file
05922 **     conf -- configuration structure to load
05923 **     err -- where to write errors
05924 **     errlen -- bytes available at "err"
05925 **
05926 **  Return value:
05927 **     0 -- success
05928 **     !0 -- error
05929 **
05930 **  Side effects:
05931 **     openlog() may be called by this function
05932 */
05933 
05934 static int
05935 dkimf_config_load(struct config *data, struct dkimf_config *conf,
05936                   char *err, size_t errlen)
05937 {
05938        int maxsign;
05939        int dbflags = 0;
05940        char *str;
05941        char confstr[BUFRSZ + 1];
05942        char basedir[MAXPATHLEN + 1];
05943 
05944        assert(conf != NULL);
05945        assert(err != NULL);
05946 
05947        memset(basedir, '\0', sizeof basedir);
05948        memset(confstr, '\0', sizeof confstr);
05949 
05950        if (data != NULL)
05951        {
05952 #ifdef USE_LDAP
05953               (void) config_get(data, "LDAPSoftStart",
05954                                 &conf->conf_softstart,
05955                                 sizeof conf->conf_softstart);
05956 #endif /* USE_LDAP */
05957 
05958               (void) config_get(data, "AddAllSignatureResults",
05959                                 &conf->conf_allsigs,
05960                                 sizeof conf->conf_allsigs);
05961 
05962               (void) config_get(data, "DNSConnect",
05963                                 &conf->conf_dnsconnect,
05964                                 sizeof conf->conf_dnsconnect);
05965 
05966               (void) config_get(data, "ResolverTracing",
05967                                 &conf->conf_restrace,
05968                                 sizeof conf->conf_restrace);
05969 
05970               (void) config_get(data, "AlwaysAddARHeader",
05971                                 &conf->conf_alwaysaddar,
05972                                 sizeof conf->conf_alwaysaddar);
05973 
05974               str = NULL;
05975               (void) config_get(data, "AuthservID", &str, sizeof str);
05976               if (str != NULL)
05977               {
05978                      if (strcmp(str, "HOSTNAME") == 0)
05979                             conf->conf_authservid = strdup(myhostname);
05980                      else   
05981                             conf->conf_authservid = strdup(str);
05982               }
05983 
05984               (void) config_get(data, "AuthservIDWithJobID",
05985                                 &conf->conf_authservidwithjobid,
05986                                 sizeof conf->conf_authservidwithjobid);
05987 
05988               str = NULL;
05989               (void) config_get(data, "BaseDirectory", &str, sizeof str);
05990               if (str != NULL)
05991                      strlcpy(basedir, str, sizeof basedir);
05992 
05993               if (conf->conf_canonstr == NULL)
05994               {
05995                      (void) config_get(data, "Canonicalization",
05996                                        &conf->conf_canonstr,
05997                                        sizeof conf->conf_canonstr);
05998               }
05999 
06000               (void) config_get(data, "ClockDrift", &conf->conf_clockdrift,
06001                                 sizeof conf->conf_clockdrift);
06002 
06003 #ifdef _FFR_DEFAULT_SENDER
06004               (void) config_get(data, "DefaultSender", &conf->conf_defsender,
06005                                 sizeof conf->conf_defsender);
06006 #endif /* _FFR_DEFAULT_SENDER */
06007 
06008               (void) config_get(data, "Diagnostics", &conf->conf_ztags,
06009                                 sizeof conf->conf_ztags);
06010 
06011               (void) config_get(data, "DiagnosticDirectory",
06012                                 &conf->conf_diagdir,
06013                                 sizeof conf->conf_diagdir);
06014 
06015 #ifdef _FFR_REDIRECT
06016               (void) config_get(data, "RedirectFailuresTo",
06017                                 &conf->conf_redirect,
06018                                 sizeof conf->conf_redirect);
06019 #endif /* _FFR_REDIRECT */
06020 
06021 #ifdef _FFR_RESIGN
06022               (void) config_get(data, "ResignMailTo",
06023                                 &conf->conf_resign,
06024                                 sizeof conf->conf_resign);
06025               (void) config_get(data, "ResignAll",
06026                                 &conf->conf_resignall,
06027                                 sizeof conf->conf_resignall);
06028 #endif /* _FFR_RESIGN */
06029 
06030               if (conf->conf_dnstimeout == DEFTIMEOUT)
06031               {
06032                      (void) config_get(data, "DNSTimeout",
06033                                        &conf->conf_dnstimeout,
06034                                        sizeof conf->conf_dnstimeout);
06035               }
06036 
06037               (void) config_get(data, "EnableCoredumps",
06038                                 &conf->conf_enablecores,
06039                                 sizeof conf->conf_enablecores);
06040 
06041               (void) config_get(data, "RequestReports",
06042                                 &conf->conf_reqreports,
06043                                 sizeof conf->conf_reqreports);
06044 
06045               (void) config_get(data, "RequireSafeKeys",
06046                                 &conf->conf_safekeys,
06047                                 sizeof conf->conf_safekeys);
06048 
06049               (void) config_get(data, "TestDNSData",
06050                                 &conf->conf_testdnsdata,
06051                                 sizeof conf->conf_testdnsdata);
06052 
06053               (void) config_get(data, "NoHeaderB",
06054                                 &conf->conf_noheaderb,
06055                                 sizeof conf->conf_noheaderb);
06056 
06057               (void) config_get(data, "FixCRLF",
06058                                 &conf->conf_fixcrlf,
06059                                 sizeof conf->conf_fixcrlf);
06060 
06061               (void) config_get(data, "KeepTemporaryFiles",
06062                                 &conf->conf_keeptmpfiles,
06063                                 sizeof conf->conf_keeptmpfiles);
06064 
06065               (void) config_get(data, "StrictHeaders",
06066                                 &conf->conf_stricthdrs,
06067                                 sizeof conf->conf_stricthdrs);
06068 
06069               (void) config_get(data, "TemporaryDirectory",
06070                                 &conf->conf_tmpdir,
06071                                 sizeof conf->conf_tmpdir);
06072 
06073               (void) config_get(data, "MaximumHeaders", &conf->conf_maxhdrsz,
06074                                 sizeof conf->conf_maxhdrsz);
06075 
06076               (void) config_get(data, "MaximumSignaturesToVerify",
06077                                 &conf->conf_maxverify,
06078                                 sizeof conf->conf_maxverify);
06079 
06080 #ifdef _FFR_IDENTITY_HEADER
06081               (void) config_get(data, "IdentityHeader",
06082                               &conf->conf_identityhdr, 
06083                               sizeof conf->conf_identityhdr);
06084 
06085               (void) config_get(data, "IdentityHeaderRemove",
06086                                 &conf->conf_rmidentityhdr,
06087                                 sizeof conf->conf_rmidentityhdr);
06088 #endif /* _FFR_IDENTITY_HEADER */
06089 #ifdef _FFR_DKIM_REPUTATION
06090               (void) config_get(data, "DKIMReputationFail",
06091                                 &conf->conf_repfail,
06092                                 sizeof conf->conf_repfail);
06093 
06094               (void) config_get(data, "DKIMReputationPass",
06095                                 &conf->conf_reppass,
06096                                 sizeof conf->conf_reppass);
06097 
06098               (void) config_get(data, "DKIMReputationReject",
06099                                 &conf->conf_repreject,
06100                                 sizeof conf->conf_repreject);
06101 
06102               str = NULL;
06103               (void) config_get(data, "DKIMReputationRoot",
06104                                 &str, sizeof str);
06105               if (str != NULL)
06106                      conf->conf_reproot = strdup(str);
06107 
06108               if (conf->conf_repfail < conf->conf_reppass)
06109               {
06110                      snprintf(err, errlen,
06111                               "invalid reputation thresholds (DKIMReputationFail < DKIMReputationPass)");
06112                      return -1;
06113               }
06114 
06115               if (conf->conf_repreject < conf->conf_repfail)
06116               {
06117                      snprintf(err, errlen,
06118                               "invalid reputation thresholds (DKIMReputationReject < DKIMReputationFail)");
06119                      return -1;
06120               }
06121 #endif /* _FFR_DKIM_REPUTATION */
06122 
06123               if (conf->conf_siglimit == NULL)
06124               {
06125                      (void) config_get(data, "Minimum",
06126                                        &conf->conf_siglimit,
06127                                        sizeof conf->conf_siglimit);
06128               }
06129 
06130               if (conf->conf_modestr == NULL)
06131               {
06132                      (void) config_get(data, "Mode", &conf->conf_modestr,
06133                                        sizeof conf->conf_modestr);
06134               }
06135 
06136               dkimf_parsehandler(data, "On-Default", &conf->conf_handling);
06137               dkimf_parsehandler(data, "On-BadSignature",
06138                                  &conf->conf_handling);
06139               dkimf_parsehandler(data, "On-DNSError", &conf->conf_handling);
06140               dkimf_parsehandler(data, "On-KeyNotFound",
06141                                  &conf->conf_handling);
06142               dkimf_parsehandler(data, "On-InternalError",
06143                                  &conf->conf_handling);
06144               dkimf_parsehandler(data, "On-NoSignature",
06145                                  &conf->conf_handling);
06146               dkimf_parsehandler(data, "On-PolicyError",
06147                                  &conf->conf_handling);
06148 #ifdef _FFR_REPUTATION
06149               dkimf_parsehandler(data, "On-ReptuationError",
06150                                  &conf->conf_handling);
06151 #endif /* _FFR_REPUTATION */
06152               dkimf_parsehandler(data, "On-Security", &conf->conf_handling);
06153 
06154               (void) config_get(data, "RemoveARAll", &conf->conf_remarall,
06155                                 sizeof conf->conf_remarall);
06156 
06157               (void) config_get(data, "KeepAuthResults", &conf->conf_keepar,
06158                                 sizeof conf->conf_keepar);
06159 
06160               (void) config_get(data, "RemoveOldSignatures",
06161                                 &conf->conf_remsigs,
06162                                 sizeof conf->conf_remsigs);
06163 
06164               if (!conf->conf_reqhdrs)
06165               {
06166                      (void) config_get(data, "RequiredHeaders",
06167                                        &conf->conf_reqhdrs,
06168                                        sizeof conf->conf_reqhdrs);
06169               }
06170 
06171               if (conf->conf_selector == NULL)
06172               {
06173                      (void) config_get(data, "Selector",
06174                                        &conf->conf_selector,
06175                                        sizeof conf->conf_selector);
06176               }
06177 
06178 #ifdef _FFR_SENDER_MACRO
06179               if (conf->conf_sendermacro == NULL)
06180               {
06181                      (void) config_get(data, "SenderMacro",
06182                                        &conf->conf_sendermacro,
06183                                        sizeof conf->conf_sendermacro);
06184               }
06185 #endif /* _FFR_SENDER_MACRO */
06186 
06187               if (!conf->conf_sendreports)
06188               {
06189                      (void) config_get(data, "SendReports",
06190                                        &conf->conf_sendreports,
06191                                        sizeof conf->conf_sendreports);
06192               }
06193               (void) config_get(data, "MTACommand",
06194                                 &conf->conf_mtacommand,
06195                                 sizeof conf->conf_mtacommand);
06196 
06197               (void) config_get(data, "SendADSPReports",
06198                                 &conf->conf_sendadspreports,
06199                                 sizeof conf->conf_sendadspreports);
06200 
06201               (void) config_get(data, "ReportAddress",
06202                                 &conf->conf_reportaddr,
06203                                 sizeof conf->conf_reportaddr);
06204 
06205               (void) config_get(data, "ReportBccAddress",
06206                                 &conf->conf_reportaddrbcc,
06207                                 sizeof conf->conf_reportaddrbcc);
06208 
06209               if (conf->conf_signalgstr == NULL)
06210               {
06211                      (void) config_get(data, "SignatureAlgorithm",
06212                                        &conf->conf_signalgstr,
06213                                        sizeof conf->conf_signalgstr);
06214               }
06215 
06216               (void) config_get(data, "SignatureTTL", &conf->conf_sigttl,
06217                                 sizeof conf->conf_sigttl);
06218 
06219 #ifdef _FFR_STATS
06220               (void) config_get(data, "Statistics", &conf->conf_statspath,
06221                                 sizeof conf->conf_statspath);
06222 
06223               (void) config_get(data, "StatisticsPrefix",
06224                                 &conf->conf_reportprefix,
06225                                 sizeof conf->conf_reportprefix);
06226 
06227               str = NULL;
06228               (void) config_get(data, "StatisticsName", &str, sizeof str);
06229               if (str != NULL)
06230                      conf->conf_reporthost = str;
06231 #endif /* _FFR_STATS */
06232 
06233               if (!conf->conf_subdomains)
06234               {
06235                      (void) config_get(data, "SubDomains",
06236                                        &conf->conf_subdomains,
06237                                        sizeof conf->conf_subdomains);
06238               }
06239 
06240               if (!conf->conf_dolog)
06241               {
06242                      (void) config_get(data, "Syslog", &conf->conf_dolog,
06243                                        sizeof conf->conf_dolog);
06244               }
06245 
06246               if (!conf->conf_logwhy)
06247               {
06248                      (void) config_get(data, "LogWhy", &conf->conf_logwhy,
06249                                        sizeof conf->conf_logwhy);
06250               }
06251 
06252               (void) config_get(data, "LogResults", &conf->conf_logresults,
06253                                 sizeof conf->conf_logresults);
06254 
06255               (void) config_get(data, "MultipleSignatures",
06256                                 &conf->conf_multisig,
06257                                 sizeof conf->conf_multisig);
06258 
06259               (void) config_get(data, "SyslogSuccess",
06260                                 &conf->conf_dolog_success,
06261                                 sizeof conf->conf_dolog_success);
06262 
06263               (void) config_get(data, "WeakSyntaxChecks",
06264                                 &conf->conf_weaksyntax,
06265                                 sizeof conf->conf_weaksyntax);
06266 
06267               (void) config_get(data, "ADSPNoSuchDomain",
06268                                 &conf->conf_adspnxdomain,
06269                                 sizeof conf->conf_adspnxdomain);
06270 
06271               (void) config_get(data, "DisableADSP",
06272                                 &conf->conf_noadsp,
06273                                 sizeof conf->conf_noadsp);
06274 
06275               str = NULL;
06276               (void) config_get(data, "ADSPAction", &str, sizeof str);
06277               if (str != NULL)
06278               {
06279                      int c;
06280 
06281                      c = dkimf_configlookup(str, dkimf_adspactions);
06282                      if (c == -1)
06283                      {
06284                             snprintf(err, errlen,
06285                                      "unknown ADSP action '%s'", str);
06286                             return -1;
06287                      }
06288 
06289                      conf->conf_adspaction = c;
06290               }
06291 
06292               if (!conf->conf_addxhdr)
06293               {
06294                      (void) config_get(data, "X-Header",
06295                                        &conf->conf_addxhdr,
06296                                        sizeof conf->conf_addxhdr);
06297               }
06298 
06299               (void) config_get(data, "DomainKeysCompat",
06300                                 &conf->conf_acceptdk,
06301                                 sizeof conf->conf_acceptdk);
06302 
06303               (void) config_get(data, "CaptureUnknownErrors",
06304                                 &conf->conf_capture,
06305                                 sizeof conf->conf_capture);
06306 
06307               (void) config_get(data, "AllowSHA1Only",
06308                                 &conf->conf_allowsha1only,
06309                                 sizeof conf->conf_allowsha1only);
06310 
06311 #ifdef USE_LDAP
06312               (void) config_get(data, "LDAPUseTLS",
06313                                 &conf->conf_ldap_usetls,
06314                                 sizeof conf->conf_ldap_usetls);
06315 
06316               if (conf->conf_ldap_usetls)
06317                      dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_USETLS, "y");
06318               else
06319                      dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_USETLS, "n");
06320 
06321               (void) config_get(data, "LDAPTimeout",
06322                                 &conf->conf_ldap_timeout,
06323                                 sizeof conf->conf_ldap_timeout);
06324 
06325               dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_TIMEOUT,
06326                                       conf->conf_ldap_timeout);
06327 
06328               (void) config_get(data, "LDAPKeepaliveIdle",
06329                                 &conf->conf_ldap_kaidle,
06330                                 sizeof conf->conf_ldap_kaidle);
06331 
06332               dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_KA_IDLE,
06333                                       conf->conf_ldap_kaidle);
06334 
06335               (void) config_get(data, "LDAPKeepaliveProbes",
06336                                 &conf->conf_ldap_kaprobes,
06337                                 sizeof conf->conf_ldap_kaprobes);
06338 
06339               dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_KA_PROBES,
06340                                       conf->conf_ldap_kaprobes);
06341 
06342               (void) config_get(data, "LDAPKeepaliveInterval",
06343                                 &conf->conf_ldap_kainterval,
06344                                 sizeof conf->conf_ldap_kainterval);
06345 
06346               dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_KA_INTERVAL,
06347                                       conf->conf_ldap_kainterval);
06348 
06349               (void) config_get(data, "LDAPAuthMechanism",
06350                                 &conf->conf_ldap_authmech,
06351                                 sizeof conf->conf_ldap_authmech);
06352 
06353               dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_AUTHMECH,
06354                                       conf->conf_ldap_authmech);
06355 
06356 # ifdef USE_SASL
06357               (void) config_get(data, "LDAPAuthName",
06358                                 &conf->conf_ldap_authname,
06359                                 sizeof conf->conf_ldap_authname);
06360 
06361               dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_AUTHNAME,
06362                                       conf->conf_ldap_authname);
06363 
06364               (void) config_get(data, "LDAPAuthRealm",
06365                                 &conf->conf_ldap_authrealm,
06366                                 sizeof conf->conf_ldap_authrealm);
06367 
06368               dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_AUTHREALM,
06369                                       conf->conf_ldap_authrealm);
06370 
06371               (void) config_get(data, "LDAPAuthUser",
06372                                 &conf->conf_ldap_authuser,
06373                                 sizeof conf->conf_ldap_authuser);
06374 
06375               dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_AUTHUSER,
06376                                       conf->conf_ldap_authuser);
06377 # endif /* USE_SASL */
06378 
06379               (void) config_get(data, "LDAPBindPassword",
06380                                 &conf->conf_ldap_bindpw,
06381                                 sizeof conf->conf_ldap_bindpw);
06382 
06383               dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_BINDPW,
06384                                       conf->conf_ldap_bindpw);
06385 
06386               (void) config_get(data, "LDAPBindUser",
06387                                 &conf->conf_ldap_binduser,
06388                                 sizeof conf->conf_ldap_binduser);
06389 
06390               dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_BINDUSER,
06391                                       conf->conf_ldap_binduser);
06392 #endif /* USE_LDAP */
06393 
06394 #ifdef USE_UNBOUND
06395               (void) config_get(data, "TrustAnchorFile",
06396                                 &conf->conf_trustanchorpath,
06397                                 sizeof conf->conf_trustanchorpath);
06398 
06399               if (conf->conf_trustanchorpath != NULL &&
06400                   access(conf->conf_trustanchorpath, R_OK) != 0)
06401               {
06402                      snprintf(err, errlen, "%s: %s",
06403                               conf->conf_trustanchorpath, strerror(errno));
06404                      return -1;
06405               }
06406 
06407               (void) config_get(data, "UnboundConfigFile",
06408                                 &conf->conf_unboundconfig,
06409                                 sizeof conf->conf_unboundconfig);
06410 
06411               if (conf->conf_unboundconfig != NULL &&
06412                   access(conf->conf_unboundconfig, R_OK) != 0)
06413               {
06414                      snprintf(err, errlen, "%s: %s",
06415                               conf->conf_unboundconfig, strerror(errno));
06416                      return -1;
06417               }
06418 
06419               (void) config_get(data, "ResolvConf",
06420                                 &conf->conf_resolvconf,
06421                                 sizeof conf->conf_resolvconf);
06422 
06423               if (conf->conf_resolvconf != NULL &&
06424                   access(conf->conf_resolvconf, R_OK) != 0)
06425               {
06426                      snprintf(err, errlen, "%s: %s",
06427                               conf->conf_resolvconf, strerror(errno));
06428                      return -1;
06429               }
06430 
06431               str = NULL;
06432               (void) config_get(data, "BogusKey", &str, sizeof str);
06433               if (str != NULL)
06434               {
06435                      int c;
06436 
06437                      c = dkimf_configlookup(str, dkimf_keyactions);
06438                      if (c == -1)
06439                      {
06440                             snprintf(err, errlen,
06441                                      "unknown key action '%s'", str);
06442                             return -1;
06443                      }
06444 
06445                      conf->conf_boguskey = c;
06446               }
06447               else
06448               {
06449                      conf->conf_boguskey = DKIMF_KEYACTIONS_FAIL;
06450               }
06451 
06452               str = NULL;
06453               (void) config_get(data, "InsecureKey", &str, sizeof str);
06454               if (str != NULL)
06455               {
06456                      int c;
06457 
06458                      c = dkimf_configlookup(str, dkimf_keyactions);
06459                      if (c == -1)
06460                      {
06461                             snprintf(err, errlen,
06462                                      "unknown key action '%s'", str);
06463                             return -1;
06464                      }
06465 
06466                      conf->conf_insecurekey = c;
06467               }
06468               else
06469               {
06470                      conf->conf_boguskey = DKIMF_KEYACTIONS_NONE;
06471               }
06472 
06473               str = NULL;
06474               (void) config_get(data, "BogusPolicy", &str, sizeof str);
06475               if (str != NULL)
06476               {
06477                      int c;
06478 
06479                      c = dkimf_configlookup(str, dkimf_policyactions);
06480                      if (c == -1)
06481                      {
06482                             snprintf(err, errlen,
06483                                      "unknown policy action '%s'", str);
06484                             return -1;
06485                      }
06486 
06487                      conf->conf_boguspolicy = c;
06488               }
06489               else
06490               {
06491                      conf->conf_boguspolicy = DKIM_POLICYACTIONS_IGNORE;
06492               }
06493 
06494               str = NULL;
06495               (void) config_get(data, "InsecurePolicy", &str, sizeof str);
06496               if (str != NULL)
06497               {
06498                      int c;
06499 
06500                      c = dkimf_configlookup(str, dkimf_policyactions);
06501                      if (c == -1)
06502                      {
06503                             snprintf(err, errlen,
06504                                      "unknown policy action '%s'", str);
06505                             return -1;
06506                      }
06507 
06508                      conf->conf_insecurepolicy = c;
06509               }
06510               else
06511               {
06512                      conf->conf_insecurepolicy = DKIM_POLICYACTIONS_APPLY;
06513               }
06514 #endif /* USE_UNBOUND */
06515 
06516 #ifdef USE_LUA
06517               str = NULL;
06518               (void) config_get(data, "SetupPolicyScript", &str, sizeof str);
06519               if (str != NULL)
06520               {
06521                      int fd;
06522                      ssize_t rlen;
06523                      struct stat s;
06524                      struct dkimf_lua_script_result lres;
06525 
06526                      fd = open(str, O_RDONLY, 0);
06527                      if (fd < 0)
06528                      {
06529                             snprintf(err, errlen, "%s: open(): %s", str,
06530                                      strerror(errno));
06531                             return -1;
06532                      }
06533 
06534                      if (fstat(fd, &s) == -1)
06535                      {
06536                             snprintf(err, errlen, "%s: fstat(): %s", str,
06537                                      strerror(errno));
06538                             close(fd);
06539                             return -1;
06540                      }
06541 
06542                      conf->conf_setupscript = malloc(s.st_size + 1);
06543                      if (conf->conf_setupscript == NULL)
06544                      {
06545                             snprintf(err, errlen, "malloc(): %s",
06546                                      strerror(errno));
06547                             close(fd);
06548                             return -1;
06549                      }
06550 
06551                      memset(conf->conf_setupscript, '\0', s.st_size + 1);
06552                      rlen = read(fd, conf->conf_setupscript, s.st_size);
06553                      if (rlen == -1)
06554                      {
06555                             snprintf(err, errlen, "%s: read(): %s",
06556                                      str, strerror(errno));
06557                             close(fd);
06558                             return -1;
06559                      }
06560                      else if (rlen < s.st_size)
06561                      {
06562                             snprintf(err, errlen, "%s: early EOF",
06563                                      str);
06564                             close(fd);
06565                             return -1;
06566                      }
06567 
06568                      close(fd);
06569 
06570                      memset(&lres, '\0', sizeof lres);
06571                      if (dkimf_lua_setup_hook(NULL, conf->conf_setupscript,
06572                                               0, str, &lres,
06573                                               &conf->conf_setupfunc,
06574                                               &conf->conf_setupfuncsz) != 0)
06575                      {
06576                             strlcpy(err, lres.lrs_error, errlen);
06577                             free(lres.lrs_error);
06578                             return -1;
06579                      }
06580               }
06581 
06582               str = NULL;
06583               (void) config_get(data, "ScreenPolicyScript",
06584                                 &str, sizeof str);
06585               if (str != NULL)
06586               {
06587                      int fd;
06588                      ssize_t rlen;
06589                      struct stat s;
06590                      struct dkimf_lua_script_result lres;
06591 
06592                      fd = open(str, O_RDONLY, 0);
06593                      if (fd < 0)
06594                      {
06595                             snprintf(err, errlen, "%s: open(): %s", str,
06596                                      strerror(errno));
06597                             return -1;
06598                      }
06599 
06600                      if (fstat(fd, &s) == -1)
06601                      {
06602                             snprintf(err, errlen, "%s: fstat(): %s", str,
06603                                      strerror(errno));
06604                             close(fd);
06605                             return -1;
06606                      }
06607 
06608                      conf->conf_screenscript = malloc(s.st_size + 1);
06609                      if (conf->conf_screenscript == NULL)
06610                      {
06611                             snprintf(err, errlen, "malloc(): %s",
06612                                      strerror(errno));
06613                             close(fd);
06614                             return -1;
06615                      }
06616 
06617                      memset(conf->conf_screenscript, '\0', s.st_size + 1);
06618                      rlen = read(fd, conf->conf_screenscript, s.st_size);
06619                      if (rlen == -1)
06620                      {
06621                             snprintf(err, errlen, "%s: read(): %s",
06622                                      str, strerror(errno));
06623                             close(fd);
06624                             return -1;
06625                      }
06626                      else if (rlen < s.st_size)
06627                      {
06628                             snprintf(err, errlen, "%s: early EOF",
06629                                      str);
06630                             close(fd);
06631                             return -1;
06632                      }
06633 
06634                      close(fd);
06635 
06636                      memset(&lres, '\0', sizeof lres);
06637                      if (dkimf_lua_screen_hook(NULL,
06638                                                conf->conf_screenscript, 0,
06639                                                str, &lres,
06640                                                &conf->conf_screenfunc,
06641                                                &conf->conf_screenfuncsz) != 0)
06642                      {
06643                             strlcpy(err, lres.lrs_error, errlen);
06644                             free(lres.lrs_error);
06645                             return -1;
06646                      }
06647               }
06648 
06649 # ifdef _FFR_STATSEXT
06650               str = NULL;
06651               (void) config_get(data, "StatisticsPolicyScript", &str,
06652                                 sizeof str);
06653               if (str != NULL)
06654               {
06655                      int fd;
06656                      ssize_t rlen;
06657                      struct stat s;
06658                      struct dkimf_lua_script_result lres;
06659 
06660                      fd = open(str, O_RDONLY, 0);
06661                      if (fd < 0)
06662                      {
06663                             snprintf(err, errlen, "%s: open(): %s", str,
06664                                      strerror(errno));
06665                             return -1;
06666                      }
06667 
06668                      if (fstat(fd, &s) == -1)
06669                      {
06670                             snprintf(err, errlen, "%s: fstat(): %s", str,
06671                                      strerror(errno));
06672                             close(fd);
06673                             return -1;
06674                      }
06675 
06676                      conf->conf_statsscript = malloc(s.st_size + 1);
06677                      if (conf->conf_statsscript == NULL)
06678                      {
06679                             snprintf(err, errlen, "malloc(): %s",
06680                                      strerror(errno));
06681                             close(fd);
06682                             return -1;
06683                      }
06684 
06685                      memset(conf->conf_statsscript, '\0', s.st_size + 1);
06686                      rlen = read(fd, conf->conf_statsscript, s.st_size);
06687                      if (rlen == -1)
06688                      {
06689                             snprintf(err, errlen, "%s: read(): %s",
06690                                      str, strerror(errno));
06691                             close(fd);
06692                             return -1;
06693                      }
06694                      else if (rlen < s.st_size)
06695                      {
06696                             snprintf(err, errlen, "%s: early EOF",
06697                                      str);
06698                             close(fd);
06699                             return -1;
06700                      }
06701 
06702                      close(fd);
06703 
06704                      memset(&lres, '\0', sizeof lres);
06705                      if (dkimf_lua_stats_hook(NULL, conf->conf_statsscript,
06706                                               0, str, &lres,
06707                                               &conf->conf_statsfunc,
06708                                               &conf->conf_statsfuncsz) != 0)
06709                      {
06710                             strlcpy(err, lres.lrs_error, errlen);
06711                             free(lres.lrs_error);
06712                             return -1;
06713                      }
06714               }
06715 # endif /* _FFR_STATSEXT */
06716 
06717               str = NULL;
06718               (void) config_get(data, "FinalPolicyScript", &str, sizeof str);
06719               if (str != NULL)
06720               {
06721                      int fd;
06722                      ssize_t rlen;
06723                      struct stat s;
06724                      struct dkimf_lua_script_result lres;
06725 
06726                      fd = open(str, O_RDONLY, 0);
06727                      if (fd < 0)
06728                      {
06729                             snprintf(err, errlen, "%s: open(): %s", str,
06730                                      strerror(errno));
06731                             return -1;
06732                      }
06733 
06734                      if (fstat(fd, &s) == -1)
06735                      {
06736                             snprintf(err, errlen, "%s: fstat(): %s", str,
06737                                      strerror(errno));
06738                             close(fd);
06739                             return -1;
06740                      }
06741 
06742                      conf->conf_finalscript = malloc(s.st_size + 1);
06743                      if (conf->conf_finalscript == NULL)
06744                      {
06745                             snprintf(err, errlen, "malloc(): %s",
06746                                      strerror(errno));
06747                             close(fd);
06748                             return -1;
06749                      }
06750 
06751                      memset(conf->conf_finalscript, '\0', s.st_size + 1);
06752                      rlen = read(fd, conf->conf_finalscript, s.st_size);
06753                      if (rlen == -1)
06754                      {
06755                             snprintf(err, errlen, "%s: read(): %s",
06756                                      str, strerror(errno));
06757                             close(fd);
06758                             return -1;
06759                      }
06760                      else if (rlen < s.st_size)
06761                      {
06762                             snprintf(err, errlen, "%s: early EOF",
06763                                      str);
06764                             close(fd);
06765                             return -1;
06766                      }
06767 
06768                      close(fd);
06769 
06770                      memset(&lres, '\0', sizeof lres);
06771                      if (dkimf_lua_final_hook(NULL, conf->conf_finalscript,
06772                                               0, str, &lres,
06773                                               &conf->conf_finalfunc,
06774                                               &conf->conf_finalfuncsz) != 0)
06775                      {
06776                             strlcpy(err, lres.lrs_error, errlen);
06777                             free(lres.lrs_error);
06778                             return -1;
06779                      }
06780               }
06781 #endif /* USE_LUA */
06782        }
06783 
06784 #ifdef USE_LDAP
06785        if (conf->conf_softstart)
06786               dbflags |= DKIMF_DB_FLAG_SOFTSTART;
06787 #endif /* USE_LDAP */
06788 
06789        if (basedir[0] != '\0')
06790        {
06791               if (chdir(basedir) != 0)
06792               {
06793                      snprintf(err, errlen, "%s: chdir(): %s",
06794                               basedir, strerror(errno));
06795                      return -1;
06796               }
06797        }
06798 
06799        str = NULL;
06800        if (conf->conf_peerfile != NULL)
06801        {
06802               str = conf->conf_peerfile;
06803        }
06804        else if (data != NULL)
06805        {
06806               (void) config_get(data, "PeerList", &str, sizeof str);
06807        }
06808        if (str != NULL && !testmode)
06809        {
06810               int status;
06811               char *dberr = NULL;
06812 
06813               status = dkimf_db_open(&conf->conf_peerdb, str,
06814                                      (dbflags | 
06815                                       DKIMF_DB_FLAG_ICASE |
06816                                       DKIMF_DB_FLAG_READONLY),
06817                                      NULL, &dberr);
06818               if (status != 0)
06819               {
06820                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
06821                               str, dberr);
06822                      return -1;
06823               }
06824        }
06825 
06826        if (conf->conf_testdnsdata != NULL)
06827        {
06828               int status;
06829               char *dberr = NULL;
06830 
06831               status = dkimf_db_open(&conf->conf_testdnsdb,
06832                                      conf->conf_testdnsdata,
06833                                      (dbflags | 
06834                                       DKIMF_DB_FLAG_ICASE |
06835                                       DKIMF_DB_FLAG_READONLY),
06836                                      NULL, &dberr);
06837               if (status != 0)
06838               {
06839                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
06840                               str, dberr);
06841                      return -1;
06842               }
06843        }
06844 
06845        /* internal list */
06846        str = NULL;
06847        if (conf->conf_internalfile != NULL)
06848        {
06849               str = conf->conf_internalfile;
06850        }
06851        else if (data != NULL)
06852        {
06853               (void) config_get(data, "InternalHosts", &str, sizeof str);
06854        }
06855        if (str != NULL && !testmode)
06856        {
06857               int status;
06858               char *dberr = NULL;
06859 
06860               status = dkimf_db_open(&conf->conf_internal, str,
06861                                      (dbflags | 
06862                                       DKIMF_DB_FLAG_ICASE |
06863                                       DKIMF_DB_FLAG_READONLY),
06864                                      NULL, &dberr);
06865               if (status != 0)
06866               {
06867                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
06868                               str, dberr);
06869                      return -1;
06870               }
06871        }
06872        else
06873        {
06874               int status;
06875               char *dberr = NULL;
06876 
06877               status = dkimf_db_open(&conf->conf_internal, DEFINTERNAL,
06878                                      (dbflags | 
06879                                       DKIMF_DB_FLAG_ICASE |
06880                                       DKIMF_DB_FLAG_READONLY),
06881                                      NULL, &dberr);
06882               if (status != 0)
06883               {
06884                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
06885                               DEFINTERNAL, dberr);
06886                      return -1;
06887               }
06888        }
06889 
06890        /* external ignore list */
06891        str = NULL;
06892        if (conf->conf_externalfile != NULL)
06893        {
06894               str = conf->conf_externalfile;
06895        }
06896        else if (data != NULL)
06897        {
06898               (void) config_get(data, "ExternalIgnoreList", &str,
06899                                 sizeof str);
06900        }
06901        if (str != NULL && !testmode)
06902        {
06903               int status;
06904               char *dberr = NULL;
06905 
06906               status = dkimf_db_open(&conf->conf_exignore, str,
06907                                      (dbflags | 
06908                                       DKIMF_DB_FLAG_ICASE |
06909                                       DKIMF_DB_FLAG_READONLY),
06910                                      NULL, &dberr);
06911               if (status != 0)
06912               {
06913                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
06914                               str, dberr);
06915                      return -1;
06916               }
06917        }
06918 
06919        /* exempt domains list */
06920        str = NULL;
06921        if (conf->conf_exemptfile != NULL)
06922        {
06923               str = conf->conf_exemptfile;
06924        }
06925        else if (data != NULL)
06926        {
06927               (void) config_get(data, "ExemptDomains", &str, sizeof str);
06928        }
06929        if (str != NULL && !testmode)
06930        {
06931               int status;
06932               char *dberr = NULL;
06933 
06934               status = dkimf_db_open(&conf->conf_exemptdb, str,
06935                                      (dbflags | 
06936                                       DKIMF_DB_FLAG_ICASE |
06937                                       DKIMF_DB_FLAG_READONLY),
06938                                      NULL, &dberr);
06939               if (status != 0)
06940               {
06941                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
06942                               str, dberr);
06943                      return -1;
06944               }
06945        }
06946 
06947        /* BodyLengthDB */
06948        str = NULL;
06949        if (data != NULL)
06950               (void) config_get(data, "BodyLengthDB", &str, sizeof str);
06951        if (str != NULL)
06952        {
06953               int status;
06954               char *dberr = NULL;
06955 
06956               status = dkimf_db_open(&conf->conf_bldb, str,
06957                                      (dbflags | 
06958                                       DKIMF_DB_FLAG_ICASE |
06959                                       DKIMF_DB_FLAG_READONLY),
06960                                      NULL, &dberr);
06961               if (status != 0)
06962               {
06963                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
06964                               str, dberr);
06965                      return -1;
06966               }
06967        }
06968 
06969        str = NULL;
06970        if (data != NULL)
06971               (void) config_get(data, "SignHeaders", &str, sizeof str);
06972        if (str != NULL)
06973        {
06974               int status;
06975               char *dberr = NULL;
06976 
06977               status = dkimf_db_open(&conf->conf_signhdrsdb, str,
06978                                      (dbflags | 
06979                                       DKIMF_DB_FLAG_ICASE |
06980                                       DKIMF_DB_FLAG_READONLY),
06981                                      NULL, &dberr);
06982               if (status != 0)
06983               {
06984                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
06985                               str, dberr);
06986                      return -1;
06987               }
06988        }
06989 
06990        str = NULL;
06991        if (data != NULL)
06992               (void) config_get(data, "RemoveARFrom", &str, sizeof str);
06993        if (str != NULL)
06994        {
06995               int status;
06996               char *dberr = NULL;
06997 
06998               status = dkimf_db_open(&conf->conf_remardb, str,
06999                                      (dbflags | 
07000                                       DKIMF_DB_FLAG_ICASE |
07001                                       DKIMF_DB_FLAG_READONLY),
07002                                      NULL, &dberr);
07003               if (status != 0)
07004               {
07005                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
07006                               str, dberr);
07007                      return -1;
07008               }
07009        }
07010 
07011 #ifdef _FFR_ADSP_LISTS
07012        str = NULL;
07013        if (data != NULL)
07014        {
07015               (void) config_get(data, "NoDiscardableMailTo", &str,
07016                                 sizeof str);
07017        }
07018        if (str != NULL)
07019        {
07020               int status;
07021               char *dberr = NULL;
07022 
07023               status = dkimf_db_open(&conf->conf_nodiscardto, str,
07024                                      (dbflags | 
07025                                       DKIMF_DB_FLAG_ICASE |
07026                                       DKIMF_DB_FLAG_READONLY),
07027                                      NULL, &dberr);
07028               if (status != 0)
07029               {
07030                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
07031                               str, dberr);
07032                      return -1;
07033               }
07034        }
07035 #endif /* _FFR_ADSP_LISTS */
07036 
07037 #ifdef _FFR_ATPS
07038 
07039        str = NULL;
07040        if (data != NULL)
07041        {
07042               (void) config_get(data, "ATPSHashAlgorithm",
07043                                 &conf->conf_atpshash,
07044                                 sizeof conf->conf_atpshash);
07045               (void) config_get(data, "ATPSDomains", &str, sizeof str);
07046        }
07047 
07048        if (dkimf_configlookup(conf->conf_atpshash, dkimf_atpshash) != 1)
07049        {
07050               snprintf(err, errlen, "unknown ATPS hash \"%s\"",
07051                        conf->conf_atpshash);
07052               return -1;
07053        }
07054 
07055        if (str != NULL)
07056        {
07057               int status;
07058               char *dberr = NULL;
07059 
07060               status = dkimf_db_open(&conf->conf_atpsdb, str,
07061                                      (dbflags | 
07062                                       DKIMF_DB_FLAG_ICASE |
07063                                       DKIMF_DB_FLAG_READONLY),
07064                                      NULL, &dberr);
07065               if (status != 0)
07066               {
07067                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
07068                               str, dberr);
07069                      return -1;
07070               }
07071        }
07072 #endif /* _FFR_ATPS */
07073 
07074        str = NULL;
07075        if (data != NULL)
07076               (void) config_get(data, "DontSignMailTo", &str, sizeof str);
07077        if (str != NULL)
07078        {
07079               int status;
07080               char *dberr = NULL;
07081 
07082               status = dkimf_db_open(&conf->conf_dontsigntodb, str,
07083                                      (dbflags | 
07084                                       DKIMF_DB_FLAG_ICASE |
07085                                       DKIMF_DB_FLAG_READONLY),
07086                                      NULL, &dberr);
07087               if (status != 0)
07088               {
07089                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
07090                               str, dberr);
07091                      return -1;
07092               }
07093        }
07094 
07095        str = NULL;
07096        if (data != NULL)
07097               (void) config_get(data, "MustBeSigned", &str, sizeof str);
07098        if (str != NULL)
07099        {
07100               int status;
07101               char *dberr = NULL;
07102 
07103               status = dkimf_db_open(&conf->conf_mbsdb, str,
07104                                      (dbflags |
07105                                       DKIMF_DB_FLAG_ICASE |
07106                                       DKIMF_DB_FLAG_READONLY),
07107                                      NULL, &dberr);
07108               if (status != 0)
07109               {
07110                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
07111                               str, dberr);
07112                      return -1;
07113               }
07114        }
07115 
07116        str = NULL;
07117        if (conf->conf_omitlist != NULL)
07118        {
07119               str = conf->conf_omitlist;
07120        }
07121        else if (data != NULL)
07122        {
07123               (void) config_get(data, "OmitHeaders", &str, sizeof str);
07124        }
07125        if (str != NULL)
07126        {
07127               int status;
07128               char *dberr = NULL;
07129 
07130               status = dkimf_db_open(&conf->conf_omithdrdb, str,
07131                                      (dbflags |
07132                                       DKIMF_DB_FLAG_ICASE |
07133                                       DKIMF_DB_FLAG_READONLY),
07134                                      NULL, &dberr);
07135               if (status != 0)
07136               {
07137                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
07138                               str, dberr);
07139                      return -1;
07140               }
07141        }
07142 
07143        str = NULL;
07144        if (data != NULL)
07145        {
07146               (void) config_get(data, "MTA", &str, sizeof str);
07147        }
07148        if (str != NULL)
07149        {
07150               int status;
07151               char *dberr = NULL;
07152 
07153               status = dkimf_db_open(&conf->conf_mtasdb, str,
07154                                      (dbflags | DKIMF_DB_FLAG_READONLY),
07155                                      NULL, &dberr);
07156               if (status != 0)
07157               {
07158                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
07159                               str, dberr);
07160                      return -1;
07161               }
07162 
07163               status = dkimf_db_mkarray(conf->conf_mtasdb, &conf->conf_mtas,
07164                                         NULL);
07165               if (status == -1)
07166                      return -1;
07167        }
07168 
07169        str = NULL;
07170        if (data != NULL)
07171               (void) config_get(data, "AlwaysSignHeaders", &str, sizeof str);
07172        if (str != NULL)
07173        {
07174               int status;
07175               char *dberr = NULL;
07176 
07177               status = dkimf_db_open(&conf->conf_alwayshdrsdb, str,
07178                                      (dbflags |
07179                                       DKIMF_DB_FLAG_ICASE |
07180                                       DKIMF_DB_FLAG_READONLY),
07181                                      NULL, &dberr);
07182               if (status != 0)
07183               {
07184                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
07185                               str, dberr);
07186                      return -1;
07187               }
07188        }
07189 
07190 #ifdef _FFR_OVERSIGN
07191        str = NULL;
07192        if (data != NULL)
07193               (void) config_get(data, "OverSignHeaders", &str, sizeof str);
07194        if (str != NULL)
07195        {
07196               int status;
07197               char *dberr = NULL;
07198 
07199               status = dkimf_db_open(&conf->conf_oversigndb, str,
07200                                      (dbflags |
07201                                       DKIMF_DB_FLAG_ICASE |
07202                                       DKIMF_DB_FLAG_READONLY),
07203                                      NULL, &dberr);
07204               if (status != 0)
07205               {
07206                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
07207                               str, dberr);
07208                      return -1;
07209               }
07210        }
07211 #endif /* _FFR_OVERSIGN */
07212 
07213        str = NULL;
07214        if (data != NULL)
07215               (void) config_get(data, "SenderHeaders", &str, sizeof str);
07216        if (str != NULL)
07217        {
07218               int status;
07219               char *dberr = NULL;
07220 
07221               status = dkimf_db_open(&conf->conf_senderhdrsdb, str,
07222                                      (dbflags |
07223                                       DKIMF_DB_FLAG_ICASE |
07224                                       DKIMF_DB_FLAG_READONLY),
07225                                      NULL, &dberr);
07226               if (status != 0)
07227               {
07228                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
07229                               str, dberr);
07230                      return -1;
07231               }
07232 
07233               status = dkimf_db_mkarray(conf->conf_senderhdrsdb,
07234                                         &conf->conf_senderhdrs,
07235                                         (const char **) dkim_default_senderhdrs);
07236               if (status == -1)
07237                      return -1;
07238        }
07239        else
07240        {
07241               conf->conf_senderhdrs = (char **) dkim_default_senderhdrs;
07242        }
07243 
07244 #ifdef _FFR_VBR
07245        if (data != NULL)
07246        {
07247               (void) config_get(data, "VBR-Type", &conf->conf_vbr_deftype,
07248                                 sizeof conf->conf_vbr_deftype);
07249               (void) config_get(data, "VBR-Certifiers",
07250                                 &conf->conf_vbr_defcert,
07251                                 sizeof conf->conf_vbr_defcert);
07252        }
07253 
07254        str = NULL;
07255        if (data != NULL)
07256        {
07257               (void) config_get(data, "VBR-TrustedCertifiers", &str,
07258                                 sizeof str);
07259        }
07260        if (str != NULL)
07261        {
07262               char *dberr = NULL;
07263               int status;
07264 
07265               status = dkimf_db_open(&conf->conf_vbr_trusteddb, str,
07266                                      (dbflags |
07267                                       DKIMF_DB_FLAG_ICASE |
07268                                       DKIMF_DB_FLAG_READONLY),
07269                                      NULL, &dberr);
07270               if (status != 0)
07271               {
07272                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
07273                               str, dberr);
07274                      return -1;
07275               }
07276 
07277               (void) dkimf_db_mkarray(conf->conf_vbr_trusteddb,
07278                                       (char ***) &conf->conf_vbr_trusted,
07279                                       NULL);
07280        }
07281 
07282        if (data != NULL)
07283        {
07284               (void) config_get(data, "VBR-PurgeFields",
07285                                 &conf->conf_vbr_purge,
07286                                 sizeof conf->conf_vbr_purge);
07287 
07288               (void) config_get(data, "VBR-TrustedCertifiersOnly",
07289                                 &conf->conf_vbr_trustedonly,
07290                                 sizeof conf->conf_vbr_trustedonly);
07291        }
07292 #endif /* _FFR_VBR */
07293 
07294        if (data != NULL)
07295        {
07296               (void) config_get(data, "SigningTable", &conf->conf_signtable,
07297                                 sizeof conf->conf_signtable);
07298 
07299               if (conf->conf_signtable != NULL)
07300               {
07301                      int status;
07302                      char *dberr = NULL;
07303 
07304                      status = dkimf_db_open(&conf->conf_signtabledb,
07305                                             conf->conf_signtable,
07306                                             (dbflags |
07307                                              DKIMF_DB_FLAG_ICASE |
07308                                              DKIMF_DB_FLAG_ASCIIONLY |
07309                                              DKIMF_DB_FLAG_READONLY),
07310                                             NULL, &dberr);
07311                      if (status != 0)
07312                      {
07313                             snprintf(err, errlen,
07314                                      "%s: dkimf_db_open(): %s",
07315                                      conf->conf_signtable, dberr);
07316                             return -1;
07317                      }
07318               }
07319        }
07320 
07321        if (data != NULL)
07322        {
07323               (void) config_get(data, "KeyTable", &conf->conf_keytable,
07324                                 sizeof conf->conf_keytable);
07325 
07326               if (conf->conf_keytable == NULL)
07327               {
07328                      (void) config_get(data, "KeyFile", &conf->conf_keyfile,
07329                                        sizeof conf->conf_keyfile);
07330               }
07331               else
07332               {
07333                      int status;
07334                      char *dberr = NULL;
07335 
07336                      status = dkimf_db_open(&conf->conf_keytabledb,
07337                                             conf->conf_keytable,
07338                                             (dbflags |
07339                                              DKIMF_DB_FLAG_READONLY), NULL,
07340                                             &dberr);
07341                      if (status != 0)
07342                      {
07343                             snprintf(err, errlen,
07344                                      "%s: dkimf_db_open(): %s",
07345                                      conf->conf_keytable, dberr);
07346                             return -1;
07347                      }
07348 
07349                      conf->conf_selector = NULL;
07350               }
07351        }
07352 
07353        if (conf->conf_signtabledb != NULL && conf->conf_keytabledb == NULL)
07354        {
07355               snprintf(err, errlen, "use of SigningTable requires KeyTable");
07356               return -1;
07357        }
07358 
07359        str = NULL;
07360        if (conf->conf_localadsp_file != NULL)
07361        {
07362               str = conf->conf_localadsp_file;
07363        }
07364        else if (data != NULL)
07365        {
07366               (void) config_get(data, "LocalADSP", &str, sizeof str);
07367        }
07368        if (str != NULL)
07369        {
07370               int status;
07371               char *dberr = NULL;
07372 
07373               status = dkimf_db_open(&conf->conf_localadsp_db, str,
07374                                      (dbflags | DKIMF_DB_FLAG_ICASE |
07375                                       DKIMF_DB_FLAG_READONLY),
07376                                      NULL, &dberr);
07377               if (status != 0)
07378               {
07379                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
07380                               str, dberr);
07381                      return -1;
07382               }
07383        }
07384 
07385        str = NULL;
07386        if (data != NULL)
07387        {
07388               (void) config_get(data, "TrustSignaturesFrom", &str,
07389                                 sizeof str);
07390        }
07391        if (str != NULL)
07392        {
07393               int status;
07394               char *dberr = NULL;
07395 
07396               status = dkimf_db_open(&conf->conf_thirdpartydb, str,
07397                                      (dbflags | DKIMF_DB_FLAG_ICASE |
07398                                       DKIMF_DB_FLAG_READONLY),
07399                                      NULL, &dberr);
07400               if (status != 0)
07401               {
07402                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
07403                               str, dberr);
07404                      return -1;
07405               }
07406        }
07407 
07408 #ifdef _FFR_RESIGN
07409        str = NULL;
07410        if (conf->conf_resign != NULL)
07411        {
07412               str = conf->conf_resign;
07413        }
07414        else if (data != NULL)
07415        {
07416               (void) config_get(data, "ResignMailTo", &str, sizeof str);
07417        }
07418        if (str != NULL)
07419        {
07420               int status;
07421               char *dberr = NULL;
07422 
07423               status = dkimf_db_open(&conf->conf_resigndb, str,
07424                                      (dbflags | DKIMF_DB_FLAG_ICASE |
07425                                       DKIMF_DB_FLAG_READONLY),
07426                                      NULL, &dberr);
07427               if (status != 0)
07428               {
07429                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
07430                               str, dberr);
07431                      return -1;
07432               }
07433        }
07434 #endif /* _FFR_RESIGN */
07435 
07436 #ifdef _FFR_RATE_LIMIT
07437        str = NULL;
07438        if (data != NULL)
07439        {
07440               (void) config_get(data, "RateLimits", &str, sizeof str);
07441        }
07442        if (str != NULL)
07443        {
07444               int status;
07445               char *dberr = NULL;
07446 
07447               status = dkimf_db_open(&conf->conf_ratelimitdb, str,
07448                                      (dbflags | DKIMF_DB_FLAG_ICASE |
07449                                       DKIMF_DB_FLAG_READONLY),
07450                                      NULL, &dberr);
07451               if (status != 0)
07452               {
07453                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
07454                               str, dberr);
07455                      return -1;
07456               }
07457        }
07458 
07459        str = NULL;
07460        if (data != NULL)
07461        {
07462               (void) config_get(data, "FlowData", &str, sizeof str);
07463 
07464               (void) config_get(data, "FlowDataTTL", &conf->conf_flowdatattl,
07465                                 sizeof conf->conf_flowdatattl);
07466 
07467               (void) config_get(data, "FlowDataFactor",
07468                                 &conf->conf_flowfactor,
07469                                 sizeof conf->conf_flowfactor);
07470        }
07471        if (str != NULL)
07472        {
07473               int dbtype;
07474               int status;
07475               char *dberr = NULL;
07476 
07477               status = dkimf_db_open(&conf->conf_flowdatadb, str,
07478                                      (dbflags | DKIMF_DB_FLAG_ICASE |
07479                                       DKIMF_DB_FLAG_MAKELOCK),
07480                                      NULL, &dberr);
07481               if (status != 0)
07482               {
07483                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
07484                               str, dberr);
07485                      return -1;
07486               }
07487 
07488               dbtype = dkimf_db_type(conf->conf_flowdatadb);
07489               if (dbtype != DKIMF_DB_TYPE_BDB)
07490               {
07491                      snprintf(err, errlen,
07492                               "%s: invalid data set type for FlowData",
07493                               str);
07494                      return -1;
07495               }
07496        }
07497 #endif /* _FFR_RATE_LIMIT */
07498 
07499        str = NULL;
07500        if (conf->conf_domlist != NULL)
07501        {
07502               str = conf->conf_domlist;
07503        }
07504        else if (data != NULL)
07505        {
07506               (void) config_get(data, "Domain", &str, sizeof str);
07507        }
07508        if (str != NULL && conf->conf_keytabledb == NULL)
07509        {
07510               int status;
07511               char *dberr = NULL;
07512 
07513               status = dkimf_db_open(&conf->conf_domainsdb, str,
07514                                      (dbflags | DKIMF_DB_FLAG_READONLY |
07515                                       DKIMF_DB_FLAG_ICASE),
07516                                      NULL, &dberr);
07517               if (status != 0)
07518               {
07519                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
07520                               str, dberr);
07521                      return -1;
07522               }
07523        }
07524 
07525        str = NULL;
07526        if (data != NULL)
07527        {
07528               (void) config_get(data, "MacroList", &str, sizeof str);
07529        }
07530        if (str != NULL)
07531        {
07532               int status;
07533               int dbtype;
07534               char *dberr = NULL;
07535 
07536               status = dkimf_db_open(&conf->conf_macrosdb, str,
07537                                      (dbflags | DKIMF_DB_FLAG_READONLY |
07538                                       DKIMF_DB_FLAG_VALLIST |
07539                                       DKIMF_DB_FLAG_MATCHBOTH), NULL,
07540                                      &dberr);
07541               if (status != 0)
07542               {
07543                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
07544                               str, dberr);
07545                      return -1;
07546               }
07547 
07548               dbtype = dkimf_db_type(conf->conf_macrosdb);
07549               if (dbtype != DKIMF_DB_TYPE_FILE &&
07550                   dbtype != DKIMF_DB_TYPE_CSL)
07551               {
07552                      snprintf(err, errlen,
07553                               "%s: invalid data set type for MacroList",
07554                               str);
07555                      return -1;
07556               }
07557 
07558               (void) dkimf_db_mkarray(conf->conf_macrosdb,
07559                                       &conf->conf_macros, NULL);
07560        }
07561 
07562        if (conf->conf_signalgstr != NULL)
07563        {
07564               conf->conf_signalg = dkimf_configlookup(conf->conf_signalgstr,
07565                                                       dkimf_sign);
07566               if (conf->conf_signalg == -1)
07567               {
07568                      snprintf(err, errlen,
07569                               "unknown signing algorithm \"%s\"",
07570                               conf->conf_signalgstr);
07571                      return -1;
07572               }
07573        }
07574        else
07575        {
07576               conf->conf_signalg = DKIM_SIGN_DEFAULT;
07577        }
07578 
07579        if (conf->conf_canonstr != NULL)
07580        {
07581               char *p;
07582 
07583               p = strchr(conf->conf_canonstr, '/');
07584               if (p == NULL)
07585               {
07586                      conf->conf_hdrcanon = dkimf_configlookup(conf->conf_canonstr,
07587                                                               dkimf_canon);
07588                      if (conf->conf_hdrcanon == -1)
07589                      {
07590                             snprintf(err, errlen,
07591                                      "unknown canonicalization algorithm \"%s\"",
07592                                      conf->conf_canonstr);
07593                             return -1;
07594                      }
07595 
07596                      conf->conf_bodycanon = DKIM_CANON_DEFAULT;
07597               }
07598               else
07599               {
07600                      *p = '\0';
07601 
07602                      conf->conf_hdrcanon = dkimf_configlookup(conf->conf_canonstr,
07603                                                               dkimf_canon);
07604                      if (conf->conf_hdrcanon == -1)
07605                      {
07606                             snprintf(err, errlen,
07607                                      "unknown canonicalization algorithm \"%s\"",
07608                                      conf->conf_canonstr);
07609                             return -1;
07610                      }
07611 
07612                      conf->conf_bodycanon = dkimf_configlookup(p + 1,
07613                                                                dkimf_canon);
07614                      if (conf->conf_bodycanon == -1)
07615                      {
07616                             snprintf(err, errlen,
07617                                      "unknown canonicalization algorithm \"%s\"",
07618                                      p + 1);
07619                             return -1;
07620                      }
07621 
07622                      *p = '/';
07623               }
07624        }
07625 
07626        str = NULL;
07627        if (conf->conf_siglimit != NULL)
07628        {
07629               str = conf->conf_siglimit;
07630        }
07631        else if (data != NULL)
07632        {
07633               (void) config_get(data, "Minimum", &str, sizeof str);
07634        }
07635        if (str != NULL)
07636        {
07637               unsigned long tmpl;
07638               char *p;
07639 
07640               errno = 0;
07641 
07642               if (str[0] == '-')
07643               {
07644                      tmpl = ULONG_MAX;
07645                      errno = ERANGE;
07646               }
07647 
07648               tmpl = strtoul(str, &p, 10);
07649               if (tmpl > UINT_MAX || errno != 0)
07650               {
07651                      snprintf(err, errlen, "illegal value for \"Minimum\"");
07652                      return -1;
07653               }
07654 
07655               conf->conf_sigmin = (unsigned int) tmpl;
07656 
07657               if (*p == '%')
07658               {
07659                      if (conf->conf_sigmin > 100)
07660                      {
07661                             snprintf(err, errlen,
07662                                      "illegal value for \"Minimum\"");
07663                             return -1;
07664                      }
07665 
07666                      conf->conf_sigmintype = SIGMIN_PERCENT;
07667               }
07668               else if (*p == '+')
07669               {
07670                      conf->conf_sigmintype = SIGMIN_MAXADD;
07671               }
07672               else if (*p != '\0')
07673               {
07674                      snprintf(err, errlen, "illegal value for \"Minimum\"");
07675                      return -1;
07676               }
07677        }
07678 
07679        maxsign = -1;
07680        if (data != NULL)
07681        {
07682               (void) config_get(data, "MaximumSignedBytes", &maxsign,
07683                                 sizeof maxsign);
07684        }
07685        if (maxsign != -1)
07686        {
07687               conf->conf_signbytes = (long) maxsign;
07688               conf->conf_blen = TRUE;
07689        }
07690 
07691        if (conf->conf_modestr == NULL)
07692        {
07693               conf->conf_mode = (testmode ? DKIMF_MODE_VERIFIER
07694                                           : DKIMF_MODE_DEFAULT);
07695        }
07696        else
07697        {
07698               char *p;
07699 
07700               conf->conf_mode = 0;
07701 
07702               for (p = conf->conf_modestr; *p != '\0'; p++)
07703               {
07704                      switch (*p)
07705                      {
07706                        case 's':
07707                             conf->conf_mode |= DKIMF_MODE_SIGNER;
07708                             break;
07709 
07710                        case 'v':
07711                             conf->conf_mode |= DKIMF_MODE_VERIFIER;
07712                             break;
07713 
07714                        default:
07715                             snprintf(err, errlen, "unknown mode \"%c\"",
07716                                      *p);
07717                             return -1;
07718                      }
07719               }
07720        }
07721 
07722 #ifdef _FFR_REPLACE_RULES
07723        /* replacement list */
07724        str = NULL;
07725        if (data != NULL)
07726        {
07727               (void) config_get(data, "ReplaceHeaders", &str, sizeof str);
07728        }
07729        if (str != NULL)
07730        {
07731               int status;
07732               char *dberr = NULL;
07733 
07734               status = dkimf_db_open(&conf->conf_rephdrsdb, str,
07735                                      (dbflags | DKIMF_DB_FLAG_READONLY |
07736                                       DKIMF_DB_FLAG_ICASE), NULL,
07737                                      &dberr);
07738               if (status != 0)
07739               {
07740                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
07741                               str, dberr);
07742                      return -1;
07743               }
07744        }
07745 
07746        str = NULL;
07747        if (data != NULL)
07748               (void) config_get(data, "ReplaceRules", &str, sizeof str);
07749        if (str != NULL)
07750        {
07751               FILE *f;
07752 
07753               f = fopen(str, "r");
07754               if (f == NULL)
07755               {
07756                      snprintf(err, errlen, "%s: fopen(): %s", str,
07757                               strerror(errno));
07758                      return -1;
07759               }
07760 
07761               if (!dkimf_load_replist(f, &conf->conf_replist))
07762               {
07763                      snprintf(err, errlen,
07764                               "failed to load ReplaceRules from %s", str);
07765                      fclose(f);
07766                      return -1;
07767               }
07768 
07769               fclose(f);
07770        }
07771 #endif /* _FFR_REPLACE_RULES */
07772 
07773 #ifdef _FFR_REPUTATION
07774        if (data != NULL)
07775        {
07776               (void) config_get(data, "ReputationVerbose",
07777                                 &conf->conf_repverbose,
07778                                 sizeof conf->conf_repverbose);
07779 
07780               (void) config_get(data, "ReputationLimits",
07781                                 &conf->conf_replimits,
07782                                 sizeof conf->conf_replimits);
07783 
07784               (void) config_get(data, "ReputationLimitModifiers",
07785                                 &conf->conf_replimitmods,
07786                                 sizeof conf->conf_replimitmods);
07787 
07788               (void) config_get(data, "ReputationCache",
07789                                 &conf->conf_repcache,
07790                                 sizeof conf->conf_repcache);
07791 
07792               (void) config_get(data, "ReputationCacheTTL",
07793                                 &conf->conf_repcachettl,
07794                                 sizeof conf->conf_repcachettl);
07795 
07796               (void) config_get(data, "ReputationDuplicates",
07797                                 &conf->conf_repdups,
07798                                 sizeof conf->conf_repdups);
07799 
07800               (void) config_get(data, "ReputationRatios",
07801                                 &conf->conf_repratios,
07802                                 sizeof conf->conf_repratios);
07803 
07804               (void) config_get(data, "ReputationLowTime",
07805                                 &conf->conf_replowtime,
07806                                 sizeof conf->conf_replowtime);
07807 
07808               (void) config_get(data, "ReputationTimeFactor",
07809                                 &conf->conf_repfactor,
07810                                 sizeof conf->conf_repfactor);
07811 
07812               (void) config_get(data, "ReputationSpamCheck",
07813                                 &conf->conf_repspamcheck,
07814                                 sizeof conf->conf_repspamcheck);
07815 
07816               (void) config_get(data, "ReputationMinimum",
07817                                 &conf->conf_repminimum,
07818                                 sizeof conf->conf_repminimum);
07819        }
07820 
07821        if (conf->conf_repspamcheck != NULL)
07822        {
07823               size_t tmplen;
07824               char tmpre[BUFRSZ + 1];
07825 
07826               tmplen = strlen(conf->conf_repspamcheck);
07827               if (tmplen < 3 ||
07828                   conf->conf_repspamcheck[0] != '/' ||
07829                   conf->conf_repspamcheck[tmplen - 1] != '/')
07830               {
07831                      snprintf(err, errlen,
07832                               "invalid value for ReputationSpamCheck");
07833                      return -1;
07834               }
07835 
07836               strlcpy(tmpre, conf->conf_repspamcheck + 1, sizeof tmpre);
07837               tmpre[tmplen - 2] = '\0';
07838 
07839               if (regcomp(&conf->conf_repspamre, tmpre, REG_EXTENDED) != 0)
07840               {
07841                      snprintf(err, errlen,
07842                               "unusable value for ReputationSpamCheck");
07843                      return -1;
07844               }
07845        }
07846 
07847        if (conf->conf_replowtime != NULL)
07848        {
07849               int status;
07850               char *dberr = NULL;
07851 
07852               status = dkimf_db_open(&conf->conf_replowtimedb,
07853                                      conf->conf_replowtime,
07854                                      (dbflags | DKIMF_DB_FLAG_READONLY),
07855                                      NULL, &dberr);
07856               if (status != 0)
07857               {
07858                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
07859                               conf->conf_replowtime, dberr);
07860                      return -1;
07861               }
07862        }
07863 
07864        if (conf->conf_repratios != NULL)
07865        {
07866               int status;
07867               char *dberr = NULL;
07868 
07869               if (conf->conf_replimits != NULL)
07870               {
07871                      status = dkimf_db_open(&conf->conf_replimitsdb,
07872                                             conf->conf_replimits,
07873                                             (dbflags |
07874                                              DKIMF_DB_FLAG_READONLY), NULL,
07875                                             &dberr);
07876                      if (status != 0)
07877                      {
07878                             snprintf(err, errlen,
07879                                      "%s: dkimf_db_open(): %s",
07880                                      conf->conf_replimits, dberr);
07881                             return -1;
07882                      }
07883               }
07884 
07885               if (conf->conf_replimitmods != NULL)
07886               {
07887                      status = dkimf_db_open(&conf->conf_replimitmodsdb,
07888                                             conf->conf_replimitmods,
07889                                             (dbflags |
07890                                              DKIMF_DB_FLAG_READONLY), NULL,
07891                                             &dberr);
07892                      if (status != 0)
07893                      {
07894                             snprintf(err, errlen,
07895                                      "%s: dkimf_db_open(): %s",
07896                                      conf->conf_replimitmods, dberr);
07897                             return -1;
07898                      }
07899               }
07900 
07901               status = dkimf_db_open(&conf->conf_repratiosdb,
07902                                      conf->conf_repratios,
07903                                      (dbflags | DKIMF_DB_FLAG_READONLY),
07904                                      NULL, &dberr);
07905               if (status != 0)
07906               {
07907                      snprintf(err, errlen, "%s: dkimf_db_open(): %s",
07908                               conf->conf_repratios, dberr);
07909                      return -1;
07910               }
07911 
07912               if (dkimf_rep_init(&conf->conf_rep, conf->conf_repfactor,
07913                                   conf->conf_repminimum,
07914                                   conf->conf_repcachettl,
07915                                   conf->conf_repcache,
07916                                   conf->conf_repdups,
07917                                   conf->conf_replimitsdb,
07918                                   conf->conf_replimitmodsdb,
07919                                   conf->conf_repratiosdb,
07920                                  conf->conf_replowtimedb) != 0)
07921               {
07922                      snprintf(err, errlen,
07923                               "can't initialize reputation subsystem");
07924                      return -1;
07925               }
07926        }
07927 #endif /* _FFR_REPUTATION */
07928 
07929        dkimf_reportaddr(conf);
07930 
07931        /* load the secret key, if one was specified */
07932        if (conf->conf_keyfile != NULL)
07933        {
07934               int status;
07935               int fd;
07936               ssize_t rlen;
07937               u_char *s33krit;
07938               struct stat s;
07939 
07940               status = stat(conf->conf_keyfile, &s);
07941               if (status != 0)
07942               {
07943                      if (conf->conf_dolog)
07944                      {
07945                             int saveerrno;
07946 
07947                             saveerrno = errno;
07948 
07949                             syslog(LOG_ERR, "%s: stat(): %s",
07950                                    conf->conf_keyfile,
07951                                    strerror(errno));
07952 
07953                             errno = saveerrno;
07954                      }
07955 
07956                      snprintf(err, errlen, "%s: stat(): %s",
07957                               conf->conf_keyfile, strerror(errno));
07958                      return -1;
07959               }
07960 
07961               if (dkimf_insecure(s.st_mode, s.st_gid))
07962               {
07963                      if (conf->conf_dolog)
07964                      {
07965                             int sev;
07966 
07967                             sev = (conf->conf_safekeys ? LOG_ERR
07968                                                        : LOG_WARNING);
07969 
07970                             syslog(sev, "%s: key data is not secure",
07971                                    conf->conf_keyfile);
07972                      }
07973 
07974                      if (conf->conf_safekeys)
07975                      {
07976                             snprintf(err, errlen,
07977                                      "%s: key data is not secure",
07978                                      conf->conf_keyfile);
07979                             return -1;
07980                      }
07981               }
07982 
07983               s33krit = malloc(s.st_size + 1);
07984               if (s33krit == NULL)
07985               {
07986                      if (conf->conf_dolog)
07987                      {
07988                             int saveerrno;
07989 
07990                             saveerrno = errno;
07991 
07992                             syslog(LOG_ERR, "malloc(): %s", 
07993                                    strerror(errno));
07994 
07995                             errno = saveerrno;
07996                      }
07997 
07998                      snprintf(err, errlen, "malloc(): %s", strerror(errno));
07999                      return -1;
08000               }
08001               conf->conf_keylen = s.st_size + 1;
08002 
08003               fd = open(conf->conf_keyfile, O_RDONLY, 0);
08004               if (fd < 0)
08005               {
08006                      if (conf->conf_dolog)
08007                      {
08008                             int saveerrno;
08009 
08010                             saveerrno = errno;
08011 
08012                             syslog(LOG_ERR, "%s: open(): %s",
08013                                    conf->conf_keyfile,
08014                                    strerror(errno));
08015 
08016                             errno = saveerrno;
08017                      }
08018 
08019                      snprintf(err, errlen, "%s: open(): %s",
08020                               conf->conf_keyfile, strerror(errno));
08021                      free(s33krit);
08022                      return -1;
08023               }
08024               else if (!S_ISREG(s.st_mode))
08025               {
08026                      snprintf(err, errlen, "%s: open(): Not a regular file",
08027                               conf->conf_keyfile);
08028                      close(fd);
08029                      free(s33krit);
08030                      return -1;
08031               }
08032 
08033               rlen = read(fd, s33krit, s.st_size + 1);
08034               if (rlen == (ssize_t) -1)
08035               {
08036                      if (conf->conf_dolog)
08037                      {
08038                             int saveerrno;
08039 
08040                             saveerrno = errno;
08041 
08042                             syslog(LOG_ERR, "%s: read(): %s",
08043                                    conf->conf_keyfile,
08044                                    strerror(errno));
08045 
08046                             errno = saveerrno;
08047                      }
08048 
08049                      snprintf(err, errlen, "%s: read(): %s",
08050                               conf->conf_keyfile, strerror(errno));
08051                      close(fd);
08052                      free(s33krit);
08053                      return -1;
08054               }
08055               else if (rlen != s.st_size)
08056               {
08057                      if (conf->conf_dolog)
08058                      {
08059                             syslog(LOG_ERR, "%s: read() wrong size (%lu)",
08060                                    conf->conf_keyfile, (u_long) rlen);
08061                      }
08062 
08063                      snprintf(err, errlen, "%s: read() wrong size (%lu)",
08064                               conf->conf_keyfile, (u_long) rlen);
08065                      close(fd);
08066                      free(s33krit);
08067                      return -1;
08068               }
08069 
08070               close(fd);
08071               s33krit[s.st_size] = '\0';
08072               conf->conf_seckey = s33krit;
08073        }
08074 
08075        /* confirm signing mode parameters */
08076        if ((conf->conf_mode & DKIMF_MODE_SIGNER) != 0)
08077        {
08078               if ((conf->conf_selector != NULL &&
08079                    conf->conf_keyfile == NULL) ||
08080                   (conf->conf_selector == NULL &&
08081                    conf->conf_keyfile != NULL))
08082               {
08083                      snprintf(err, errlen,
08084                               "KeyFile and Selector must both be defined or both be undefined");
08085                      return -1;
08086               }
08087 
08088               if (conf->conf_domainsdb != NULL &&
08089                   (conf->conf_selector == NULL ||
08090                    conf->conf_keyfile == NULL))
08091               {
08092                      snprintf(err, errlen,
08093                               "Domain requires KeyFile and Selector");
08094                      return -1;
08095               }
08096 
08097               if (conf->conf_signtable != NULL &&
08098                   conf->conf_keytable == NULL)
08099               {
08100                      snprintf(err, errlen,
08101                               "SigningTable requires KeyTable");
08102                      return -1;
08103               }
08104 
08105 #ifdef USE_LUA
08106               if (conf->conf_keytable != NULL &&
08107                   conf->conf_signtable == NULL &&
08108                   conf->conf_setupscript == NULL)
08109               {
08110                      snprintf(err, errlen,
08111                               "KeyTable requires either SigningTable or SetupPolicyScript");
08112                      return -1;
08113               }
08114 #else /* USE_LUA */
08115               if (conf->conf_keytable != NULL &&
08116                   conf->conf_signtable == NULL)
08117               {
08118                      snprintf(err, errlen,
08119                               "KeyTable requires SigningTable");
08120                      return -1;
08121               }
08122 #endif /* USE_LUA */
08123        }
08124 
08125        /* activate logging if requested */
08126        if (conf->conf_dolog)
08127        {
08128               char *log_facility = NULL;
08129 
08130               if (data != NULL)
08131               {
08132                      (void) config_get(data, "SyslogFacility", &log_facility,
08133                                        sizeof log_facility);
08134               }
08135 
08136               dkimf_init_syslog(log_facility);
08137        }
08138 
08139        return 0;
08140 }
08141 
08142 /*
08143 **  DKIMF_CONFIG_SETLIB -- set library options based on configuration file
08144 **
08145 **  Parameters:
08146 **     conf -- DKIM filter configuration data
08147 **     err -- error string (returned; may be NULL)
08148 **
08149 **  Return value:
08150 **     TRUE on success, FALSE otherwise.
08151 */
08152 
08153 static _Bool
08154 dkimf_config_setlib(struct dkimf_config *conf, char **err)
08155 {
08156        DKIM_STAT status;
08157        u_int opts;
08158        DKIM_LIB *lib;
08159        assert(conf != NULL);
08160 
08161        lib = conf->conf_libopendkim;
08162        if (lib == NULL)
08163        {
08164               lib = dkim_init(NULL, NULL);
08165               if (lib == NULL)
08166               {
08167                      if (err != NULL)
08168                             *err = "failed to initialize DKIM library";
08169                      return FALSE;
08170               }
08171 
08172               conf->conf_libopendkim = lib;
08173        }
08174 
08175        (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS,
08176                            &opts, sizeof opts);
08177        opts |= (DKIM_LIBFLAGS_ACCEPTV05 | DKIM_LIBFLAGS_DROPSIGNER);
08178        if (conf->conf_weaksyntax)
08179               opts |= DKIM_LIBFLAGS_BADSIGHANDLES;
08180 #ifdef QUERY_CACHE
08181        if (querycache)
08182        {
08183               opts |= DKIM_LIBFLAGS_CACHE;
08184               (void) time(&cache_lastlog);
08185        }
08186 #endif /* QUERY_CACHE */
08187        (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS,
08188                            &opts, sizeof opts);
08189 
08190        /* set the DNS callback */
08191        (void) dkim_set_dns_callback(lib, dkimf_sendprogress, CBINTERVAL);
08192 
08193        if (conf->conf_testdnsdb != NULL)
08194        {
08195               (void) dkimf_filedns_setup(lib, conf->conf_testdnsdb);
08196        }
08197        else
08198        {
08199 #ifdef USE_ARLIB
08200               conf->conf_arlib = ar_init(NULL, NULL, NULL,
08201                                          (curconf->conf_restrace ? AR_FLAG_TRACELOGGING
08202                                                                  : 0) |
08203                                          (curconf->conf_dnsconnect ? AR_FLAG_USETCP
08204                                                                    : 0));
08205               if (conf->conf_arlib == NULL)
08206               {
08207                      if (err != NULL)
08208                             *err = "failed to initialize libar";
08209 
08210                      return FALSE;
08211               }
08212 
08213               (void) dkimf_arlib_setup(lib, conf->conf_arlib);
08214 #endif /* USE_ARLIB */
08215 
08216 #ifdef USE_UNBOUND
08217               if (dkimf_unbound_init(&conf->conf_unbound) != 0)
08218               {
08219                      if (err != NULL)
08220                             *err = "failed to initialize libunbound";
08221 
08222                      return FALSE;
08223               }
08224 
08225               if (conf->conf_trustanchorpath != NULL)
08226               {
08227                      if (access(conf->conf_trustanchorpath, R_OK) != 0)
08228                      {
08229                             if (err != NULL)
08230                                    *err = "can't access unbound trust anchor";
08231                             return FALSE;
08232                      }
08233 
08234                      status = dkimf_unbound_add_trustanchor(conf->conf_unbound,
08235                                                             conf->conf_trustanchorpath);
08236                      if (status != DKIM_STAT_OK)
08237                      {
08238                             if (err != NULL)
08239                                    *err = "failed to add unbound trust anchor";
08240                             return FALSE;
08241                      }
08242               }
08243 
08244               if (conf->conf_unboundconfig != NULL)
08245               {
08246                      if (access(conf->conf_unboundconfig, R_OK) != 0)
08247                      {
08248                             if (err != NULL)
08249                                    *err = "can't access unbound configuration file";
08250                             return FALSE;
08251                      }
08252 
08253                      status = dkimf_unbound_add_conffile(conf->conf_unbound,
08254                                                          conf->conf_unboundconfig);
08255                      if (status != DKIM_STAT_OK)
08256                      {
08257                             if (err != NULL)
08258                                    *err = "failed to add unbound configuration file";
08259               
08260                             return FALSE;
08261                      }
08262               }
08263 
08264               if (conf->conf_resolvconf != NULL)
08265               {
08266                      if (access(conf->conf_resolvconf, R_OK) != 0)
08267                      {
08268                             if (err != NULL)
08269                                    *err = "can't access unbound resolver configuration file";
08270                             return FALSE;
08271                      }
08272 
08273                      status = dkimf_unbound_add_resolvconf(conf->conf_unbound,
08274                                                            conf->conf_resolvconf);
08275                      if (status != DKIM_STAT_OK)
08276                      {
08277                             if (err != NULL)
08278                                    *err = "failed to add unbound resolver configuration file";
08279               
08280                             return FALSE;
08281                      }
08282               }
08283 
08284               (void) dkimf_unbound_setup(lib, conf->conf_unbound);
08285 #endif /* USE_UNBOUND */
08286        }
08287 
08288        (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_TIMEOUT,
08289                            &conf->conf_dnstimeout,
08290                            sizeof conf->conf_dnstimeout);
08291 
08292        if (conf->conf_clockdrift != 0)
08293        {
08294               uint64_t drift = conf->conf_clockdrift;
08295 
08296               status = dkim_options(lib, DKIM_OP_SETOPT,
08297                                     DKIM_OPTS_CLOCKDRIFT, &drift,
08298                                     sizeof drift);
08299 
08300               if (status != DKIM_STAT_OK)
08301               {
08302                      if (err != NULL)
08303                             *err = "failed to set DKIM clock drift limit";
08304                      return FALSE;
08305               }
08306        }
08307 
08308        if (conf->conf_sigttl != 0)
08309        {
08310               uint64_t sigtime = conf->conf_sigttl;
08311 
08312               status = dkim_options(lib, DKIM_OP_SETOPT,
08313                                     DKIM_OPTS_SIGNATURETTL, &sigtime,
08314                                     sizeof sigtime);
08315 
08316               if (status != DKIM_STAT_OK)
08317               {
08318                      if (err != NULL)
08319                             *err = "failed to set DKIM signature TTL";
08320                      return FALSE;
08321               }
08322        }
08323 
08324        if (conf->conf_sendreports || conf->conf_keeptmpfiles ||
08325            conf->conf_stricthdrs || conf->conf_blen || conf->conf_ztags ||
08326            conf->conf_fixcrlf)
08327        {
08328               u_int opts;
08329 
08330               status = dkim_options(conf->conf_libopendkim, DKIM_OP_GETOPT,
08331                                     DKIM_OPTS_FLAGS, &opts, sizeof opts);
08332 
08333               if (status != DKIM_STAT_OK)
08334               {
08335                      if (err != NULL)
08336                             *err = "failed to retrieve DKIM library options";
08337                      return FALSE;
08338               }
08339 
08340               if (conf->conf_sendreports || conf->conf_keeptmpfiles)
08341                      opts |= DKIM_LIBFLAGS_TMPFILES;
08342               if (conf->conf_keeptmpfiles)
08343                      opts |= DKIM_LIBFLAGS_KEEPFILES;
08344               if (conf->conf_blen)
08345                      opts |= DKIM_LIBFLAGS_SIGNLEN;
08346               if (conf->conf_ztags)
08347                      opts |= DKIM_LIBFLAGS_ZTAGS;
08348               if (conf->conf_fixcrlf)
08349                      opts |= DKIM_LIBFLAGS_FIXCRLF;
08350               if (conf->conf_acceptdk)
08351                      opts |= DKIM_LIBFLAGS_ACCEPTDK;
08352               if (conf->conf_stricthdrs)
08353                      opts |= DKIM_LIBFLAGS_STRICTHDRS;
08354 
08355               status = dkim_options(conf->conf_libopendkim, DKIM_OP_SETOPT,
08356                                     DKIM_OPTS_FLAGS, &opts, sizeof opts);
08357 
08358               if (status != DKIM_STAT_OK)
08359               {
08360                      if (err != NULL)
08361                             *err = "failed to set DKIM library options";
08362                      return FALSE;
08363               }
08364        }
08365 
08366        if (conf->conf_alwayshdrsdb != NULL)
08367        {
08368               status = dkimf_db_mkarray(conf->conf_alwayshdrsdb,
08369                                         &conf->conf_alwayshdrs, NULL);
08370               if (status == -1)
08371               {
08372                      if (err != NULL)
08373                             *err = "failed to generate DB array";
08374                      return FALSE;
08375               }
08376 
08377               status = dkim_options(conf->conf_libopendkim, DKIM_OP_SETOPT,
08378                                     DKIM_OPTS_ALWAYSHDRS,
08379                                     conf->conf_alwayshdrs,
08380                                     sizeof conf->conf_alwayshdrs);
08381 
08382               if (status != DKIM_STAT_OK)
08383               {
08384                      if (err != NULL)
08385                             *err = "failed to set DKIM library options";
08386                      return FALSE;
08387               }
08388        }
08389 
08390 #ifdef _FFR_OVERSIGN
08391        if (conf->conf_oversigndb != NULL)
08392        {
08393               status = dkimf_db_mkarray(conf->conf_oversigndb,
08394                                         &conf->conf_oversignhdrs, NULL);
08395               if (status == -1)
08396               {
08397                      if (err != NULL)
08398                             *err = "failed to generate DB array";
08399                      return FALSE;
08400               }
08401 
08402               status = dkim_options(conf->conf_libopendkim, DKIM_OP_SETOPT,
08403                                     DKIM_OPTS_OVERSIGNHDRS,
08404                                     conf->conf_oversignhdrs,
08405                                     sizeof conf->conf_oversignhdrs);
08406 
08407               if (status != DKIM_STAT_OK)
08408               {
08409                      if (err != NULL)
08410                             *err = "failed to set DKIM library options";
08411                      return FALSE;
08412               }
08413        }
08414 #endif /* _FFR_OVERSIGN */
08415 
08416        if (conf->conf_mbsdb != NULL)
08417        {
08418               status = dkimf_db_mkarray(conf->conf_mbsdb, &conf->conf_mbs,
08419                                         NULL);
08420               if (status == -1)
08421               {
08422                      if (err != NULL)
08423                             *err = "failed to generate DB array";
08424                      return FALSE;
08425               }
08426 
08427               status = dkim_options(conf->conf_libopendkim, DKIM_OP_SETOPT,
08428                                     DKIM_OPTS_MUSTBESIGNED,
08429                                     conf->conf_mbs, sizeof conf->conf_mbs);
08430 
08431               if (status != DKIM_STAT_OK)
08432               {
08433                      if (err != NULL)
08434                             *err = "failed to set DKIM library options";
08435                      return FALSE;
08436               }
08437        }
08438 
08439        if (conf->conf_omithdrdb != NULL)
08440        {
08441               status = dkimf_db_mkarray(conf->conf_omithdrdb,
08442                                         &conf->conf_omithdrs,
08443                                         (const char **) dkim_should_not_signhdrs);
08444               if (status == -1)
08445               {
08446                      if (err != NULL)
08447                             *err = "failed to generate DB array";
08448                      return FALSE;
08449               }
08450 
08451               status = dkim_options(conf->conf_libopendkim, DKIM_OP_SETOPT,
08452                                     DKIM_OPTS_SKIPHDRS,
08453                                     conf->conf_omithdrs,
08454                                     sizeof conf->conf_omithdrs);
08455 
08456               if (status != DKIM_STAT_OK)
08457               {
08458                      if (err != NULL)
08459                             *err = "failed to set DKIM library options";
08460                      return FALSE;
08461               }
08462        }
08463        else
08464        {
08465               status = dkim_options(conf->conf_libopendkim, DKIM_OP_SETOPT,
08466                                     DKIM_OPTS_SKIPHDRS,
08467                                     (void *) dkim_should_not_signhdrs,
08468                                     sizeof (u_char **));
08469 
08470               if (status != DKIM_STAT_OK)
08471               {
08472                      if (err != NULL)
08473                             *err = "failed to set DKIM library options";
08474                      return FALSE;
08475               }
08476        }
08477 
08478        if (conf->conf_signhdrsdb != NULL)
08479        {
08480               status = dkimf_db_mkarray(conf->conf_signhdrsdb,
08481                                         &conf->conf_signhdrs,
08482                                         (const char **) dkim_should_signhdrs);
08483               if (status == -1)
08484               {
08485                      if (err != NULL)
08486                             *err = "failed to set DKIM library options";
08487                      return FALSE;
08488               }
08489 
08490               status = dkim_options(conf->conf_libopendkim, DKIM_OP_SETOPT,
08491                                     DKIM_OPTS_SIGNHDRS, conf->conf_signhdrs,
08492                                     sizeof conf->conf_signhdrs);
08493 
08494               if (status != DKIM_STAT_OK)
08495               {
08496                      if (err != NULL)
08497                             *err = "failed to set DKIM library options";
08498                      return FALSE;
08499               }
08500        }
08501        else
08502        {
08503               status = dkim_options(conf->conf_libopendkim, DKIM_OP_SETOPT,
08504                                     DKIM_OPTS_SIGNHDRS,
08505                                     (void *) dkim_should_signhdrs,
08506                                     sizeof (u_char **));
08507 
08508               if (status != DKIM_STAT_OK)
08509               {
08510                      if (err != NULL)
08511                             *err = "failed to set DKIM library options";
08512                      return FALSE;
08513               }
08514        }
08515 
08516        status = dkim_options(conf->conf_libopendkim, DKIM_OP_SETOPT,
08517                              DKIM_OPTS_TMPDIR,
08518                              (void *) conf->conf_tmpdir,
08519                              sizeof conf->conf_tmpdir);
08520 
08521        if (status != DKIM_STAT_OK)
08522        {
08523               if (err != NULL)
08524                      *err = "failed to set DKIM library options";
08525               return FALSE;
08526        }
08527 
08528        status = dkim_set_prescreen(conf->conf_libopendkim, dkimf_prescreen);
08529        if (status != DKIM_STAT_OK)
08530        {
08531               if (err != NULL)
08532                      *err = "failed to set DKIM prescreen function";
08533               return FALSE;
08534        }
08535 
08536        return TRUE;
08537 }
08538 
08539 /*
08540 **  DKIMF_CONFIG_RELOAD -- reload configuration if requested
08541 **
08542 **  Parameters:
08543 **     None.
08544 **
08545 **  Return value:
08546 **     None.
08547 **
08548 **  Side effects:
08549 **     If a reload was requested and is successful, "curconf" now points
08550 **     to a new configuration handle.
08551 */
08552 
08553 static void
08554 dkimf_config_reload(void)
08555 {
08556        struct dkimf_config *new;
08557        char errbuf[BUFRSZ + 1];
08558 
08559        pthread_mutex_lock(&conf_lock);
08560 
08561        if (!reload)
08562        {
08563               pthread_mutex_unlock(&conf_lock);
08564               return;
08565        }
08566 
08567        if (conffile == NULL)
08568        {
08569               if (curconf->conf_dolog)
08570                      syslog(LOG_ERR, "ignoring reload signal");
08571 
08572               reload = FALSE;
08573 
08574               pthread_mutex_unlock(&conf_lock);
08575               return;
08576        }
08577 
08578        new = dkimf_config_new();
08579        if (new == NULL)
08580        {
08581               if (curconf->conf_dolog)
08582                      syslog(LOG_ERR, "malloc(): %s", strerror(errno));
08583        }
08584        else
08585        {
08586               _Bool err = FALSE;
08587               u_int line;
08588               struct config *cfg;
08589               char *missing;
08590               char *errstr = NULL;
08591               char path[MAXPATHLEN + 1];
08592 
08593               strlcpy(path, conffile, sizeof path);
08594 
08595               cfg = config_load(conffile, dkimf_config, &line,
08596                                 path, sizeof path);
08597 
08598               if (cfg == NULL)
08599               {
08600                      if (curconf->conf_dolog)
08601                      {
08602                             syslog(LOG_ERR,
08603                                    "%s: configuration error at line %u: %s",
08604                                     path, line, config_error());
08605                      }
08606                      dkimf_config_free(new);
08607                      err = TRUE;
08608               }
08609 
08610               if (!err)
08611               {
08612                      missing = config_check(cfg, dkimf_config);
08613                      if (missing != NULL)
08614                      {
08615                             if (curconf->conf_dolog)
08616                             {
08617                                    syslog(LOG_ERR,
08618                                            "%s: required parameter \"%s\" missing",
08619                                            conffile, missing);
08620                             }
08621                             config_free(cfg);
08622                             dkimf_config_free(new);
08623                             err = TRUE;
08624                      }
08625               }
08626 
08627               if (!err && dkimf_config_load(cfg, new, errbuf,
08628                                             sizeof errbuf) != 0)
08629               {
08630                      if (curconf->conf_dolog)
08631                             syslog(LOG_ERR, "%s: %s", conffile, errbuf);
08632                      config_free(cfg);
08633                      dkimf_config_free(new);
08634                      err = TRUE;
08635               }
08636 
08637               if (!err && !dkimf_config_setlib(new, &errstr))
08638               {
08639                      if (curconf->conf_dolog)
08640                      {
08641                             syslog(LOG_WARNING,
08642                                    "can't configure DKIM library: %s; continuing",
08643                                    errstr);
08644                      }
08645                      config_free(cfg);
08646                      dkimf_config_free(new);
08647                      err = TRUE;
08648               }
08649 
08650               if (!err)
08651               {
08652                      if (curconf->conf_refcnt == 0)
08653                             dkimf_config_free(curconf);
08654 
08655                      dolog = new->conf_dolog;
08656                      curconf = new;
08657                      new->conf_data = cfg;
08658 
08659                      if (new->conf_dolog)
08660                      {
08661                             syslog(LOG_INFO,
08662                                    "configuration reloaded from %s",
08663                                    conffile);
08664                      }
08665               }
08666        }
08667 
08668        reload = FALSE;
08669 
08670        pthread_mutex_unlock(&conf_lock);
08671 
08672        return;
08673 }
08674 
08675 /*
08676 **  DKIMF_CHECKBLDB -- determine if an envelope recipient is one for which
08677 **                     signing should be done with body length tags
08678 **
08679 **  Parameters:
08680 **     db -- DB handle
08681 **     to -- the recipient header
08682 **     jobid -- string of job ID for logging
08683 **
08684 **  Return value:
08685 **     TRUE iff the recipient email was found in the body length database.
08686 */
08687 
08688 static _Bool
08689 dkimf_checkbldb(DKIMF_DB db, char *to, char *jobid)
08690 {
08691        int c;
08692        _Bool exists = FALSE;
08693        DKIM_STAT status;
08694        size_t out;
08695        char *domain;
08696        char *user;
08697        char *p;
08698        char addr[MAXADDRESS + 1];
08699        char dbaddr[MAXADDRESS + 1];
08700 
08701        strlcpy(addr, to, sizeof addr);
08702        status = dkim_mail_parse(addr, (u_char **) &user, (u_char **) &domain);
08703        if (status != 0 || user == NULL || domain == NULL)
08704        {
08705               if (dolog)
08706               {
08707                      syslog(LOG_INFO, "%s: can't parse %s: header",
08708                             jobid, to);
08709               }
08710 
08711               return FALSE;
08712        }
08713 
08714        for (p = domain; ; p = strchr(p + 1, '.'))
08715        {
08716               for (c = 0; c < 2; c++)
08717               {
08718                      if (c == 1 && p == NULL)
08719                      {
08720                             dbaddr[0] = '*';
08721                             dbaddr[1] = '\0';
08722                      }
08723                      else if (snprintf(dbaddr, sizeof dbaddr, "%s@%s",
08724                                        c == 0 ? user : "*",
08725                                        p == NULL ? "*" : p) >= (int) sizeof dbaddr)
08726                      {
08727                             if (dolog)
08728                             {
08729                                    syslog(LOG_ERR,
08730                                           "%s: overflow parsing \"%s\"",
08731                                           jobid, to);
08732                             }
08733 
08734                             return FALSE;
08735                      }
08736 
08737                      status = dkimf_db_get(db, dbaddr, 0, NULL, 0, &exists);
08738                      if (status == 0)
08739                      {
08740                             if (exists)
08741                                    return TRUE;
08742                      }
08743                      else if (dolog)
08744                      {
08745                             dkimf_db_error(db, dbaddr);
08746                      }
08747               }
08748 
08749               if (p == NULL)
08750                      break;
08751        }
08752 
08753        return FALSE;
08754 }
08755 
08756 /*
08757 **  DKIMF_STDIO -- set up the base descriptors to go nowhere
08758 **
08759 **  Parameters:
08760 **     None.
08761 **
08762 **  Return value:
08763 **     None.
08764 */
08765 
08766 static void
08767 dkimf_stdio(void)
08768 {
08769        int devnull;
08770 
08771        /* this only fails silently, but that's OK */
08772        devnull = open(_PATH_DEVNULL, O_RDWR, 0);
08773        if (devnull != -1)
08774        {
08775               (void) dup2(devnull, 0);
08776               (void) dup2(devnull, 1);
08777               (void) dup2(devnull, 2);
08778               if (devnull > 2)
08779                      (void) close(devnull);
08780        }
08781 
08782        (void) setsid();
08783 }
08784 
08785 /*
08786 **  DKIMF_SENDPROGRESS -- tell the MTA "we're working on it!"
08787 **
08788 **  Parameters:
08789 **     ctx -- context
08790 **
08791 **  Return value:
08792 **     None (yet).
08793 */
08794 
08795 void
08796 dkimf_sendprogress(const void *ctx)
08797 {
08798        if (ctx != NULL)
08799        {
08800               struct connctx *cc;
08801               struct msgctx *dfc;
08802 
08803               cc = (struct connctx *) dkimf_getpriv((SMFICTX *) ctx);
08804               dfc = cc->cctx_msg;
08805 
08806               if (dfc->mctx_eom)
08807               {
08808                      if (testmode)
08809                             (void) dkimf_test_progress((SMFICTX *) ctx);
08810 #ifdef HAVE_SMFI_PROGRESS
08811                      else
08812                             (void) smfi_progress((SMFICTX *) ctx);
08813 #endif /* HAVE_SMFI_PROGRESS */
08814               }
08815        }
08816 }
08817 
08818 /*
08819 **  DKIMF_INITCONTEXT -- initialize filter context
08820 **
08821 **  Parameters:
08822 **     conf -- pointer to the configuration for this connection
08823 **
08824 **  Return value:
08825 **     A pointer to an allocated and initialized filter context, or NULL
08826 **     on failure.
08827 **
08828 **  Side effects:
08829 **     Crop circles near Birmingham.
08830 */
08831 
08832 static msgctx
08833 dkimf_initcontext(struct dkimf_config *conf)
08834 {
08835        msgctx ctx;
08836 
08837        assert(conf != NULL);
08838 
08839        ctx = (msgctx) malloc(sizeof(struct msgctx));
08840        if (ctx == NULL)
08841               return NULL;
08842 
08843        (void) memset(ctx, '\0', sizeof(struct msgctx));
08844 
08845        ctx->mctx_status = DKIMF_STATUS_UNKNOWN;
08846        ctx->mctx_hdrcanon = conf->conf_hdrcanon;
08847        ctx->mctx_bodycanon = conf->conf_bodycanon;
08848        ctx->mctx_signalg = DKIM_SIGN_DEFAULT;
08849        ctx->mctx_queryalg = DKIM_QUERY_DEFAULT;
08850 #ifdef USE_UNBOUND
08851        ctx->mctx_dnssec_key = DKIM_DNSSEC_UNKNOWN;
08852        ctx->mctx_dnssec_policy = DKIM_DNSSEC_UNKNOWN;
08853 #endif /* USE_UNBOUND */
08854        ctx->mctx_pcode = DKIM_POLICY_NONE;
08855        ctx->mctx_presult = DKIM_PRESULT_NONE;
08856 #ifdef _FFR_ATPS
08857        ctx->mctx_atps = DKIM_ATPS_UNKNOWN;
08858 #endif /* _FFR_ATPS */
08859 #ifdef _FFR_REPUTATION
08860        SHA1_Init(&ctx->mctx_hash);
08861 #endif /* _FFR_REPUTATION */
08862 
08863        return ctx;
08864 }
08865 
08866 /*
08867 **  DKIMF_LOG_SSL_ERRORS -- log any queued SSL library errors
08868 **
08869 **  Parameters:
08870 **     jobid -- job ID to include in log messages
08871 **     selector -- selector to include in log messages (may be NULL)
08872 **     domain -- domain to use in log messsages (may be NULL)
08873 **
08874 **  Return value:
08875 **     None.
08876 */
08877 
08878 static void
08879 dkimf_log_ssl_errors(char *jobid, char *selector, char *domain)
08880 {
08881 #ifdef USE_GNUTLS
08882        const char *errbuf;
08883 
08884        errbuf = dkimf_crypto_geterror();
08885        if (errbuf != NULL)
08886        {
08887               if (selector != NULL && domain != NULL)
08888               {
08889                      syslog(LOG_INFO, "%s: s=%s d=%s SSL %s", jobid,
08890                             selector, domain, errbuf);
08891               }
08892               else
08893               {
08894                      syslog(LOG_INFO, "%s: SSL %s", jobid, errbuf);
08895               }
08896        }
08897 #else /* USE_GNUTLS */
08898        assert(jobid != NULL);
08899 
08900        /* log any queued SSL error messages */
08901        if (ERR_peek_error() != 0)
08902        {
08903               int n;
08904               int saveerr;
08905               u_long e;
08906               char errbuf[BUFRSZ + 1];
08907               char tmp[BUFRSZ + 1];
08908 
08909               saveerr = errno;
08910 
08911               memset(errbuf, '\0', sizeof errbuf);
08912 
08913               for (n = 0; ; n++)
08914               {
08915                      e = ERR_get_error();
08916                      if (e == 0)
08917                             break;
08918 
08919                      memset(tmp, '\0', sizeof tmp);
08920                      (void) ERR_error_string_n(e, tmp, sizeof tmp);
08921                      if (n != 0)
08922                             strlcat(errbuf, "; ", sizeof errbuf);
08923                      strlcat(errbuf, tmp, sizeof errbuf);
08924               }
08925 
08926               if (selector != NULL && domain != NULL)
08927               {
08928                      syslog(LOG_INFO, "%s: s=%s d=%s SSL %s", jobid,
08929                             selector, domain, errbuf);
08930               }
08931               else
08932               {
08933                      syslog(LOG_INFO, "%s: SSL %s", jobid, errbuf);
08934               }
08935 
08936               errno = saveerr;
08937        }
08938 #endif /* USE_GNUTLS */
08939 }
08940 
08941 /*
08942 **  DKIMF_CLEANUP -- release local resources related to a message
08943 **
08944 **  Parameters:
08945 **     ctx -- milter context
08946 **
08947 **  Return value:
08948 **     None.
08949 */
08950 
08951 static void
08952 dkimf_cleanup(SMFICTX *ctx)
08953 {
08954        msgctx dfc;
08955        connctx cc;
08956 
08957        assert(ctx != NULL);
08958 
08959        cc = (connctx) dkimf_getpriv(ctx);
08960 
08961        if (cc == NULL)
08962               return;
08963 
08964        dfc = cc->cctx_msg;
08965 
08966        /* release memory, reset state */
08967        if (dfc != NULL)
08968        {
08969               if (dfc->mctx_hqhead != NULL)
08970               {
08971                      Header hdr;
08972                      Header prev;
08973 
08974                      hdr = dfc->mctx_hqhead;
08975                      while (hdr != NULL)
08976                      {
08977                             TRYFREE(hdr->hdr_hdr);
08978                             TRYFREE(hdr->hdr_val);
08979                             prev = hdr;
08980                             hdr = hdr->hdr_next;
08981                             TRYFREE(prev);
08982                      }
08983               }
08984 
08985               if (dfc->mctx_rcptlist != NULL)
08986               {
08987                      struct addrlist *addr;
08988                      struct addrlist *next;
08989 
08990                      addr = dfc->mctx_rcptlist;
08991                      while (addr != NULL)
08992                      {
08993                             next = addr->a_next;
08994 
08995                             TRYFREE(addr->a_addr);
08996                             TRYFREE(addr);
08997 
08998                             addr = next;
08999                      }
09000               }
09001 
09002               if (dfc->mctx_srhead != NULL)
09003               {
09004                      struct signreq *sr;
09005                      struct signreq *next;
09006 
09007                      sr = dfc->mctx_srhead;
09008                      while (sr != NULL)
09009                      {
09010                             next = sr->srq_next;
09011 
09012                             if (sr->srq_dkim != NULL)
09013                                    dkim_free(sr->srq_dkim);
09014                             TRYFREE(sr->srq_keydata);
09015                             TRYFREE(sr->srq_domain);
09016                             TRYFREE(sr->srq_selector);
09017                             TRYFREE(sr->srq_signer);
09018                             TRYFREE(sr);
09019 
09020                             sr = next;
09021                      }
09022               }
09023 
09024 #ifdef _FFR_ADSP_LISTS
09025               if (dfc->mctx_pstate != NULL)
09026                      dkim_policy_state_free(dfc->mctx_pstate);
09027 #endif /* _FFR_ADSP_LISTS */
09028 
09029               if (dfc->mctx_dkimv != NULL)
09030                      dkim_free(dfc->mctx_dkimv);
09031 
09032 #ifdef _FFR_VBR
09033               if (dfc->mctx_vbr != NULL)
09034                      vbr_close(dfc->mctx_vbr);
09035 
09036               TRYFREE(dfc->mctx_vbrinfo);
09037 #endif /* _FFR_VBR */
09038 
09039               if (dfc->mctx_tmpstr != NULL)
09040                      dkimf_dstring_free(dfc->mctx_tmpstr);
09041 
09042 #ifdef _FFR_STATSEXT
09043               if (dfc->mctx_statsext != NULL)
09044               {
09045                      struct statsext *cur;
09046                      struct statsext *next;
09047 
09048                      cur = dfc->mctx_statsext;
09049                      while (cur != NULL)
09050                      {
09051                             next = cur->se_next;
09052        
09053                             free(cur);
09054 
09055                             cur = next;
09056                      }
09057               }
09058 #endif /* _FFR_STATSEXT */
09059 
09060 #ifdef _FFR_LUA_GLOBALS
09061               if (dfc->mctx_luaglobalh != NULL)
09062               {
09063                      struct lua_global *cur;
09064                      struct lua_global *next;
09065 
09066                      cur = dfc->mctx_luaglobalh;
09067                      while (cur != NULL)
09068                      {
09069                             next = cur->lg_next;
09070 
09071                             if (cur->lg_type == LUA_TNUMBER ||
09072                                 cur->lg_type == LUA_TSTRING)
09073                                    free(cur->lg_value);
09074 
09075                             free(cur);
09076 
09077                             cur = next;
09078                      }
09079               }
09080 #endif /* _FFR_LUA_GLOBALS */
09081 
09082               free(dfc);
09083               cc->cctx_msg = NULL;
09084        }
09085 }
09086 
09087 /*
09088 **  DKIMF_MILTERCODE -- apply an internal result code to libmilter
09089 **
09090 **  Parameters:
09091 **     ctx -- milter context
09092 **     dmc -- DKIMF_MILTER_* code
09093 **     str -- quarantine string (optional)
09094 **
09095 **  Return value:
09096 **     An SMFIS_* constant.
09097 */
09098 
09099 sfsistat
09100 dkimf_miltercode(SMFICTX *ctx, int dmc, char *str)
09101 {
09102        assert(ctx != NULL);
09103 
09104        switch (dmc)
09105        {
09106          case DKIMF_MILTER_ACCEPT:
09107               return SMFIS_ACCEPT;
09108 
09109          case DKIMF_MILTER_DISCARD:
09110               return SMFIS_DISCARD;
09111 
09112          case DKIMF_MILTER_QUARANTINE:
09113               (void) dkimf_quarantine(ctx, str == NULL ? progname : str);
09114               return SMFIS_ACCEPT;
09115 
09116          case DKIMF_MILTER_REJECT:
09117               return SMFIS_REJECT;
09118 
09119          case DKIMF_MILTER_TEMPFAIL:
09120               return SMFIS_TEMPFAIL;
09121        }
09122 
09123        /* NOTREACHED */
09124        return SMFIS_ACCEPT;
09125 }
09126 
09127 /*
09128 **  DKIMF_LIBSTATUS -- process a final status returned from libopendkim
09129 **
09130 **  Parameters:
09131 **     ctx -- milter context
09132 **     dkim -- DKIM handle producing the status
09133 **     where -- what function reported the error
09134 **     status -- status returned by a libdk call (DKIM_STAT_*)
09135 **
09136 **  Return value:
09137 **     An smfistat value to be returned to libmilter.
09138 */
09139 
09140 static sfsistat
09141 dkimf_libstatus(SMFICTX *ctx, DKIM *dkim, char *where, int status)
09142 {
09143        int retcode = SMFIS_CONTINUE;
09144        msgctx dfc;
09145        connctx cc;
09146        DKIM_SIGINFO *sig;
09147        char *rcode = NULL;
09148        char *xcode = NULL;
09149        char *replytxt = NULL;
09150        struct dkimf_config *conf;
09151        u_char smtpprefix[BUFRSZ];
09152 
09153        assert(ctx != NULL);
09154 
09155        cc = dkimf_getpriv(ctx);
09156        assert(cc != NULL);
09157        dfc = cc->cctx_msg;
09158        assert(dfc != NULL);
09159        conf = cc->cctx_config;
09160 
09161        memset(smtpprefix, '\0', sizeof smtpprefix);
09162 
09163        switch (status)
09164        {
09165          case DKIM_STAT_OK:
09166               retcode = SMFIS_CONTINUE;
09167               break;
09168 
09169          case DKIM_STAT_INTERNAL:
09170               retcode = dkimf_miltercode(ctx,
09171                                          conf->conf_handling.hndl_internal,
09172                                          NULL);
09173               if (conf->conf_capture)
09174                      dfc->mctx_capture = TRUE;
09175               if (conf->conf_dolog)
09176               {
09177                      const char *err = NULL;
09178 
09179                      if (dkim != NULL)
09180                             err = dkim_geterror(dkim);
09181                      if (err == NULL)
09182                             err = strerror(errno);
09183 
09184                      syslog(LOG_ERR,
09185                             "%s: %s%sinternal error from libopendkim: %s",
09186                             JOBID(dfc->mctx_jobid),
09187                             where == NULL ? "" : where,
09188                             where == NULL ? "" : ": ", err);
09189               }
09190               replytxt = "internal DKIM error";
09191               break;
09192 
09193          case DKIM_STAT_BADSIG:
09194               assert(dkim != NULL);
09195               retcode = dkimf_miltercode(ctx,
09196                                          conf->conf_handling.hndl_badsig,
09197                                          NULL);
09198               if (conf->conf_dolog)
09199               {
09200                      syslog(LOG_NOTICE, "%s: bad signature data",
09201                             JOBID(dfc->mctx_jobid));
09202               }
09203               replytxt = "bad DKIM signature data";
09204 
09205               memset(smtpprefix, '\0', sizeof smtpprefix);
09206               sig = dkim_getsignature(dkim);
09207               (void) dkim_sig_getreportinfo(dkim, sig,
09208                                             NULL, 0,
09209                                             NULL, 0,
09210                                             NULL, 0,
09211                                             smtpprefix, sizeof smtpprefix,
09212                                             NULL);
09213 
09214               break;
09215 
09216          case DKIM_STAT_NOSIG:
09217               retcode = dkimf_miltercode(ctx,
09218                                          conf->conf_handling.hndl_nosig,
09219                                          NULL);
09220               if (conf->conf_dolog)
09221               {
09222                      if (conf->conf_logwhy ||
09223                          retcode != SMFIS_ACCEPT)
09224                      {
09225                             syslog(retcode == SMFIS_ACCEPT ? LOG_DEBUG
09226                                                            : LOG_NOTICE,
09227                                    "%s: no signature data",
09228                                    JOBID(dfc->mctx_jobid));
09229                      }
09230               }
09231               replytxt = "no DKIM signature data";
09232               break;
09233 
09234          case DKIM_STAT_NORESOURCE:
09235               retcode = dkimf_miltercode(ctx,
09236                                          conf->conf_handling.hndl_internal,
09237                                          NULL);
09238               if (conf->conf_capture)
09239                      dfc->mctx_capture = TRUE;
09240               if (conf->conf_dolog)
09241               {
09242                      const char *err = NULL;
09243 
09244                      if (dkim != NULL)
09245                             err = dkim_geterror(dkim);
09246                      if (err == NULL)
09247                             err = strerror(errno);
09248 
09249                      syslog(LOG_ERR, "%s: %s%sresource unavailable: %s",
09250                             JOBID(dfc->mctx_jobid),
09251                             where == NULL ? "" : where,
09252                             where == NULL ? "" : ": ", err);
09253               }
09254               replytxt = "resource unavailable";
09255               break;
09256 
09257          case DKIM_STAT_CANTVRFY:
09258               retcode = dkimf_miltercode(ctx,
09259                                          conf->conf_handling.hndl_badsig,
09260                                          NULL);
09261               if (conf->conf_dolog && dkim != NULL)
09262               {
09263                      const char *err = NULL;
09264                      err = dkim_geterror(dkim);
09265                      if (err == NULL)
09266                             err = "unknown cause";
09267 
09268                      syslog(LOG_ERR, "%s: signature processing failed: %s",
09269                             JOBID(dfc->mctx_jobid), err);
09270               }
09271               replytxt = "DKIM signature processing failed";
09272               break;
09273 
09274          case DKIM_STAT_REVOKED:
09275               retcode = dkimf_miltercode(ctx,
09276                                          conf->conf_handling.hndl_badsig,
09277                                          NULL);
09278               if (conf->conf_dolog)
09279               {
09280                      u_char *selector = NULL;
09281                      u_char *domain = NULL;
09282                      DKIM_SIGINFO *sig;
09283 
09284                      sig = dkim_getsignature(dkim);
09285                      if (sig != NULL)
09286                      {
09287                             selector = dkim_sig_getselector(sig);
09288                             domain = dkim_sig_getdomain(sig);
09289                      }
09290 
09291                      if (selector != NULL && domain != NULL)
09292                      {
09293                             syslog(LOG_NOTICE,
09294                                    "%s: key revoked (s=%s, d=%s)",
09295                                    JOBID(dfc->mctx_jobid), selector,
09296                                    domain);
09297                      }
09298               }
09299               break;
09300 
09301          case DKIM_STAT_KEYFAIL:
09302          case DKIM_STAT_NOKEY:
09303               if (status == DKIM_STAT_KEYFAIL)
09304               {
09305                      retcode = dkimf_miltercode(ctx,
09306                                                 conf->conf_handling.hndl_dnserr,
09307                                                 NULL);
09308               }
09309               else
09310               {
09311                      retcode = dkimf_miltercode(ctx,
09312                                                 conf->conf_handling.hndl_nokey,
09313                                                 NULL);
09314               }
09315 
09316               if (conf->conf_dolog)
09317               {
09318                      const char *err = NULL;
09319                      u_char *selector = NULL;
09320                      u_char *domain = NULL;
09321                      DKIM_SIGINFO *sig;
09322 
09323                      err = dkim_geterror(dkim);
09324 
09325                      sig = dkim_getsignature(dkim);
09326                      if (sig != NULL)
09327                      {
09328                             selector = dkim_sig_getselector(sig);
09329                             domain = dkim_sig_getdomain(sig);
09330                      }
09331 
09332                      if (selector != NULL && domain != NULL)
09333                      {
09334                             syslog(LOG_ERR,
09335                                    "%s: key retrieval failed (s=%s, d=%s)%s%s",
09336                                    JOBID(dfc->mctx_jobid), selector,
09337                                    domain,
09338                                    err == NULL ? "" : ": ",
09339                                    err == NULL ? "" : err);
09340                      }
09341                      else
09342                      {
09343                             syslog(LOG_ERR, "%s: key retrieval failed%s%s",
09344                                    JOBID(dfc->mctx_jobid),
09345                                    err == NULL ? "" : ": ",
09346                                    err == NULL ? "" : err);
09347                      }
09348               }
09349               replytxt = "DKIM key retrieval failed";
09350               break;
09351 
09352          case DKIM_STAT_SYNTAX:
09353               retcode = dkimf_miltercode(ctx,
09354                                          conf->conf_handling.hndl_badsig,
09355                                          NULL);
09356               if (conf->conf_dolog)
09357               {
09358                      const char *err = NULL;
09359 
09360                      if (dkim != NULL)
09361                             err = dkim_geterror(dkim);
09362                      if (err == NULL)
09363                             err = "unspecified";
09364 
09365                      syslog(LOG_ERR, "%s: syntax error: %s",
09366                             JOBID(dfc->mctx_jobid), err);
09367               }
09368               replytxt = "DKIM signature syntax error";
09369               break;
09370        }
09371 
09372        switch (retcode)
09373        {
09374          case SMFIS_REJECT:
09375               rcode = "550";
09376               xcode = "5.7.0";
09377               break;
09378 
09379          case SMFIS_TEMPFAIL:
09380               rcode = "451";
09381               if (status == DKIM_STAT_KEYFAIL || status == DKIM_STAT_NOKEY)
09382                      xcode = "4.7.5";
09383               else
09384                      xcode = "4.7.0";
09385               break;
09386 
09387          default:
09388               break;
09389        }
09390 
09391        if (rcode != NULL && xcode != NULL && replytxt != NULL)
09392        {
09393               char replybuf[BUFRSZ];
09394 
09395               if (smtpprefix[0] == '\0')
09396               {
09397                      strlcpy(replybuf, replytxt, sizeof replybuf);
09398               }
09399               else
09400               {
09401                      snprintf(replybuf, sizeof replybuf, "%s: %s",
09402                               smtpprefix, replytxt);
09403               }
09404 
09405               (void) dkimf_setreply(ctx, rcode, xcode, replybuf);
09406        }
09407 
09408        return retcode;
09409 }
09410 
09411 /*
09412 **  DKIMF_FINDHEADER -- find a header
09413 **
09414 **  Parameters:
09415 **     dfc -- filter context
09416 **     hname -- name of the header of interest
09417 **     instance -- which instance is wanted (0 = first)
09418 **
09419 **  Return value:
09420 **     Header handle, or NULL if not found.
09421 **
09422 **  Notes:
09423 **     Negative values of "instance" search backwards from the end.
09424 */
09425 
09426 static Header
09427 dkimf_findheader(msgctx dfc, char *hname, int instance)
09428 {
09429        Header hdr;
09430 
09431        assert(dfc != NULL);
09432        assert(hname != NULL);
09433 
09434        if (instance < 0)
09435               hdr = dfc->mctx_hqtail;
09436        else
09437               hdr = dfc->mctx_hqhead;
09438 
09439        while (hdr != NULL)
09440        {
09441               if (strcasecmp(hdr->hdr_hdr, hname) == 0)
09442               {
09443                      if (instance == 0 || instance == -1)
09444                             return hdr;
09445                      else if (instance > 0)
09446                             instance--;
09447                      else
09448                             instance++;
09449               }
09450 
09451               if (instance < 0)
09452                      hdr = hdr->hdr_prev;
09453               else
09454                      hdr = hdr->hdr_next;
09455        }
09456 
09457        return NULL;
09458 }
09459 
09460 /*
09461 **  DKIMF_APPLY_SIGNTABLE -- apply the signing table to a message
09462 **
09463 **  Parameters:
09464 **     dfc -- message context
09465 **     keydb -- database handle for key table
09466 **     signdb -- database handle for signing table
09467 **     user -- userid (local-part)
09468 **     domain -- domain
09469 **     errkey -- where to write the name of a key that failed
09470 **     errlen -- bytes available at "errkey"
09471 **     multisig -- apply multiple signature logic
09472 **
09473 **  Return value:
09474 **     >= 0 -- number of signatures added
09475 **     -1 -- signing table read error
09476 **     -2 -- unknown key
09477 **     -3 -- key load error
09478 */
09479 
09480 static int
09481 dkimf_apply_signtable(struct msgctx *dfc, DKIMF_DB keydb, DKIMF_DB signdb,
09482                       unsigned char *user, unsigned char *domain, char *errkey,
09483                       size_t errlen, _Bool multisig)
09484 {
09485        _Bool found;
09486        int nfound = 0;
09487        char keyname[BUFRSZ + 1];
09488        u_char tmp[BUFRSZ + 1];
09489 
09490        assert(dfc != NULL);
09491        assert(keydb != NULL);
09492        assert(signdb != NULL);
09493        assert(user != NULL);
09494        assert(domain != NULL);
09495 
09496        if (dkimf_db_type(signdb) == DKIMF_DB_TYPE_REFILE)
09497        {
09498               int status;
09499               void *ctx = NULL;
09500               struct dkimf_db_data dbd[2];
09501               char addr[MAXADDRESS + 1];
09502               u_char signer[MAXADDRESS + 1];
09503 
09504               snprintf(addr, sizeof addr, "%s@%s", user, domain);
09505 
09506               memset(&dbd, '\0', sizeof dbd);
09507               dbd[0].dbdata_buffer = keyname;
09508               dbd[1].dbdata_buffer = (char *) signer;
09509               dbd[1].dbdata_flags = DKIMF_DB_DATA_OPTIONAL;
09510 
09511               /* walk RE set, find match(es), make request(s) */
09512               for (;;)
09513               {
09514                      memset(keyname, '\0', sizeof keyname);
09515                      dbd[0].dbdata_buflen = sizeof keyname - 1;
09516                      memset(signer, '\0', sizeof signer);
09517                      dbd[1].dbdata_buflen = sizeof signer - 1;
09518 
09519                      status = dkimf_db_rewalk(signdb, addr, dbd, 2, &ctx);
09520                      if (status == -1)
09521                             return -1;
09522                      else if (status == 1)
09523                             break;
09524 
09525                      if (keyname[0] == '%' && keyname[1] == '\0')
09526                             dkim_strlcpy(keyname, domain, sizeof keyname);
09527 
09528                      dkimf_reptoken(tmp, sizeof tmp, signer, domain);
09529                      status = dkimf_add_signrequest(dfc, keydb, keyname,
09530                                                     (char *) tmp,
09531                                                     (ssize_t) -1);
09532                      if (status != 0 && errkey != NULL)
09533                             strlcpy(errkey, keyname, errlen);
09534                      if (status == 1)
09535                             return -2;
09536                      else if (status == 2 || status == 3 || status == -1)
09537                             return -3;
09538 
09539                      nfound++;
09540 
09541                      if (!multisig)
09542                             return nfound;
09543               }
09544        }
09545        else
09546        {
09547               int status;
09548               char *p;
09549               char tmpaddr[MAXADDRESS + 1];
09550               u_char signer[MAXADDRESS + 1];
09551               struct dkimf_db_data req[2];
09552 
09553               memset(&req, '\0', sizeof req);
09554 
09555               memset(keyname, '\0', sizeof keyname);
09556               memset(signer, '\0', sizeof signer);
09557               req[0].dbdata_buffer = keyname;
09558               req[0].dbdata_buflen = sizeof keyname - 1;
09559               req[1].dbdata_buffer = (char *) signer;
09560               req[1].dbdata_buflen = sizeof signer - 1;
09561               req[1].dbdata_flags = DKIMF_DB_DATA_OPTIONAL;
09562 
09563               /* first try full "user@host" */
09564               snprintf(tmpaddr, sizeof tmpaddr, "%s@%s", user, domain);
09565 
09566               found = FALSE;
09567               status = dkimf_db_get(signdb, tmpaddr, strlen(tmpaddr),
09568                                     req, 2, &found);
09569               if (status != 0 ||
09570                   (found && (req[0].dbdata_buflen == 0 ||
09571                              req[0].dbdata_buflen == (size_t) -1)))
09572               {
09573                      if (status != 0 && dolog)
09574                             dkimf_db_error(signdb, tmpaddr);
09575                      return -1;
09576               }
09577               else if (found)
09578               {
09579                      if (keyname[0] == '%' && keyname[1] == '\0')
09580                             dkim_strlcpy(keyname, domain, sizeof keyname);
09581 
09582                      dkimf_reptoken(tmp, sizeof tmp, signer, domain);
09583 
09584                      status = dkimf_add_signrequest(dfc, keydb, keyname,
09585                                                     (char *) tmp,
09586                                                     (ssize_t) -1);
09587                      if (status != 0 && errkey != NULL)
09588                             strlcpy(errkey, keyname, errlen);
09589                      if (status == 1)
09590                             return -2;
09591                      else if (status == 2 || status == 3 || status == -1)
09592                             return -3;
09593 
09594                      nfound++;
09595 
09596                      if (!multisig)
09597                             return nfound;
09598               }
09599 
09600               /* now just "host" */
09601               found = FALSE;
09602               req[0].dbdata_buflen = sizeof keyname - 1;
09603               req[1].dbdata_buflen = sizeof signer - 1;
09604               memset(keyname, '\0', sizeof keyname);
09605               memset(signer, '\0', sizeof signer);
09606               status = dkimf_db_get(signdb, domain, strlen((char *) domain),
09607                                     req, 2, &found);
09608               if (status != 0 ||
09609                   (found && (req[0].dbdata_buflen == 0 ||
09610                              req[0].dbdata_buflen == (size_t) -1)))
09611               {
09612                      if (status != 0 && dolog)
09613                             dkimf_db_error(signdb, (char *) domain);
09614                      return -1;
09615               }
09616               else if (found)
09617               {
09618                      if (keyname[0] == '%' && keyname[1] == '\0')
09619                             dkim_strlcpy(keyname, domain, sizeof keyname);
09620 
09621                      dkimf_reptoken(tmp, sizeof tmp, signer, domain);
09622 
09623                      status = dkimf_add_signrequest(dfc, keydb, keyname,
09624                                                     (char *) tmp,
09625                                                     (ssize_t) -1);
09626                      if (status != 0 && errkey != NULL)
09627                             strlcpy(errkey, keyname, errlen);
09628                      if (status == 1)
09629                             return -2;
09630                      else if (status == 2 || status == 3 || status == -1)
09631                             return -3;
09632 
09633                      nfound++;
09634 
09635                      if (!multisig)
09636                             return nfound;
09637               }
09638 
09639               /* next "user@.domain" and ".domain", degrading */
09640               for (p = strchr((char *) domain, '.');
09641                    p != NULL;
09642                    p = strchr(p + 1, '.'))
09643               {
09644                      snprintf(tmpaddr, sizeof tmpaddr, "%s@%s",
09645                               user, p);
09646 
09647                      found = FALSE;
09648                      req[0].dbdata_buflen = sizeof keyname - 1;
09649                      req[1].dbdata_buflen = sizeof signer - 1;
09650                      memset(keyname, '\0', sizeof keyname);
09651                      memset(signer, '\0', sizeof signer);
09652                      status = dkimf_db_get(signdb, tmpaddr, strlen(tmpaddr),
09653                                            req, 2, &found);
09654                      if (status != 0 ||
09655                          (found && (req[0].dbdata_buflen == 0 ||
09656                                     req[0].dbdata_buflen == (size_t) -1)))
09657                      {
09658                             if (status != 0 && dolog)
09659                                    dkimf_db_error(signdb, tmpaddr);
09660                             return -1;
09661                      }
09662                      else if (found)
09663                      {
09664                             if (keyname[0] == '%' && keyname[1] == '\0')
09665                             {
09666                                    dkim_strlcpy(keyname, domain,
09667                                                 sizeof keyname);
09668                             }
09669 
09670                             dkimf_reptoken(tmp, sizeof tmp, signer,
09671                                            domain);
09672 
09673                             status = dkimf_add_signrequest(dfc, keydb,
09674                                                            keyname,
09675                                                            (char *) tmp,
09676                                                            (ssize_t) -1);
09677                             if (status != 0 && errkey != NULL)
09678                                    strlcpy(errkey, keyname, errlen);
09679                             if (status == 1)
09680                                    return -2;
09681                             else if (status == 2 || status == 3 ||
09682                                      status == -1)
09683                                    return -3;
09684 
09685                             nfound++;
09686 
09687                             if (!multisig)
09688                                    return nfound;
09689                      }
09690 
09691                      found = FALSE;
09692                      req[0].dbdata_buflen = sizeof keyname - 1;
09693                      req[1].dbdata_buflen = sizeof signer - 1;
09694                      memset(keyname, '\0', sizeof keyname);
09695                      memset(signer, '\0', sizeof signer);
09696                      status = dkimf_db_get(signdb, p, strlen(p),
09697                                            req, 2, &found);
09698                      if (status != 0 ||
09699                          (found && (req[0].dbdata_buflen == 0 ||
09700                                     req[0].dbdata_buflen == (size_t) -1)))
09701                      {
09702                             if (status != 0 && dolog)
09703                                    dkimf_db_error(signdb, p);
09704                             return -1;
09705                      }
09706                      else if (found)
09707                      {
09708                             if (keyname[0] == '%' && keyname[1] == '\0')
09709                             {
09710                                    dkim_strlcpy(keyname, domain,
09711                                                 sizeof keyname);
09712                             }
09713 
09714                             dkimf_reptoken(tmp, sizeof tmp, signer,
09715                                            domain);
09716 
09717                             status = dkimf_add_signrequest(dfc, keydb,
09718                                                            keyname,
09719                                                            (char *) tmp,
09720                                                            (ssize_t) -1);
09721                             if (status != 0 && errkey != NULL)
09722                                    strlcpy(errkey, keyname, errlen);
09723                             if (status == 1)
09724                                    return -2;
09725                             else if (status == 2 || status == 3 ||
09726                                      status == -1)
09727                                    return -3;
09728 
09729                             nfound++;
09730 
09731                             if (!multisig)
09732                                    return nfound;
09733                      }
09734               }
09735 
09736               /* now "user@*" */
09737               snprintf(tmpaddr, sizeof tmpaddr, "%s@*", user);
09738 
09739               found = FALSE;
09740               req[0].dbdata_buflen = sizeof keyname - 1;
09741               req[1].dbdata_buflen = sizeof signer - 1;
09742               memset(keyname, '\0', sizeof keyname);
09743               memset(signer, '\0', sizeof signer);
09744               status = dkimf_db_get(signdb, tmpaddr, strlen(tmpaddr),
09745                                     req, 2, &found);
09746               if (status != 0 ||
09747                   (found && (req[0].dbdata_buflen == 0 ||
09748                              req[0].dbdata_buflen == (size_t) -1)))
09749               {
09750                      if (status != 0 && dolog)
09751                             dkimf_db_error(signdb, tmpaddr);
09752                      return -1;
09753               }
09754               else if (found)
09755               {
09756                      if (keyname[0] == '%' && keyname[1] == '\0')
09757                             dkim_strlcpy(keyname, domain, sizeof keyname);
09758 
09759                      dkimf_reptoken(tmp, sizeof tmp, signer, domain);
09760 
09761                      status = dkimf_add_signrequest(dfc, keydb, keyname,
09762                                                     (char *) tmp,
09763                                                     (ssize_t) -1);
09764                      if (status != 0 && errkey != NULL)
09765                             strlcpy(errkey, keyname, errlen);
09766                      if (status == 1)
09767                             return -2;
09768                      else if (status == 2 || status == 3 || status == -1)
09769                             return -3;
09770 
09771                      nfound++;
09772 
09773                      if (!multisig)
09774                             return nfound;
09775               }
09776 
09777               /* finally just "*" */
09778               found = FALSE;
09779               req[0].dbdata_buflen = sizeof keyname - 1;
09780               req[1].dbdata_buflen = sizeof signer - 1;
09781               memset(keyname, '\0', sizeof keyname);
09782               memset(signer, '\0', sizeof signer);
09783               status = dkimf_db_get(signdb, "*", 1, req, 2, &found);
09784               if (status != 0 ||
09785                   (found && (req[0].dbdata_buflen == 0 ||
09786                              req[0].dbdata_buflen == (size_t) -1)))
09787               {
09788                      if (status != 0 && dolog)
09789                             dkimf_db_error(signdb, "*");
09790                      return -1;
09791               }
09792               else if (found)
09793               {
09794                      if (keyname[0] == '%' && keyname[1] == '\0')
09795                             dkim_strlcpy(keyname, domain, sizeof keyname);
09796 
09797                      dkimf_reptoken(tmp, sizeof tmp, signer, domain);
09798 
09799                      status = dkimf_add_signrequest(dfc, keydb, keyname,
09800                                                     (char *) tmp,
09801                                                     (ssize_t) -1);
09802                      if (status != 0 && errkey != NULL)
09803                             strlcpy(errkey, keyname, errlen);
09804                      if (status == 1)
09805                             return -2;
09806                      else if (status == 2 || status == 3 || status == -1)
09807                             return -3;
09808 
09809                      nfound++;
09810 
09811                      if (!multisig)
09812                             return nfound;
09813               }
09814        }
09815 
09816        return nfound;
09817 }
09818 
09819 /*
09820 **  DKIMF_SIGREPORT -- generate a report on signature failure (if possible)
09821 **
09822 **  Parameters:
09823 **     cc -- connection context
09824 **     conf -- current configuration object
09825 **     hostname -- hostname to use for reporting MTA
09826 **
09827 **  Return value:
09828 **     None.
09829 */
09830 
09831 static void
09832 dkimf_sigreport(connctx cc, struct dkimf_config *conf, char *hostname)
09833 {
09834        _Bool sendreport = FALSE;
09835        int bfd = -1;
09836        int hfd = -1;
09837        int status;
09838        int arftype = ARF_TYPE_UNKNOWN;
09839        int arfdkim = ARF_DKIMF_UNKNOWN;
09840        u_int pct = 100;
09841        u_int rn;
09842        time_t now;
09843        DKIM_STAT repstatus;
09844        char *p;
09845        char *last;
09846        FILE *out;
09847        msgctx dfc;
09848        DKIM_SIGINFO *sig;
09849        struct Header *hdr;
09850        struct tm tm;
09851        char ipstr[DKIM_MAXHOSTNAMELEN + 1];
09852        char opts[BUFRSZ];
09853        char fmt[BUFRSZ];
09854        u_char addr[MAXADDRESS + 1];
09855 
09856        assert(cc != NULL);
09857 
09858        dfc = cc->cctx_msg;
09859 
09860        assert(dfc->mctx_dkimv != NULL);
09861        assert(conf != NULL);
09862        assert(hostname != NULL);
09863 
09864        memset(addr, '\0', sizeof addr);
09865        memset(opts, '\0', sizeof opts);
09866 
09867        sig = dkim_getsignature(dfc->mctx_dkimv);
09868 
09869        /* if no report is possible, just skip it */
09870        repstatus = dkim_sig_getreportinfo(dfc->mctx_dkimv, sig,
09871                                           &hfd, &bfd,
09872                                           (u_char *) addr, sizeof addr,
09873                                           (u_char *) opts, sizeof opts,
09874                                           NULL, 0, &pct);
09875        if (repstatus != DKIM_STAT_OK || addr[0] == '\0')
09876               return;
09877 
09878        if (pct < 100)
09879        {
09880               rn = random() % 100;
09881               if (rn > pct)
09882                      return;
09883        }
09884 
09885        /* ignore any domain name in "r=" */
09886        p = strchr((char *) addr, '@');
09887        if (p != NULL)
09888               *p = '\0';
09889 
09890        /* ensure the event being reported was requested */
09891        if (opts[0] == '\0')
09892        {
09893               sendreport = TRUE;
09894        }
09895        else
09896        {
09897               for (p = strtok_r(opts, ":", &last);
09898                    p != NULL;
09899                    p = strtok_r(NULL, ":", &last))
09900               {
09901                      if (strcasecmp(p, ARF_OPTIONS_DKIM_ALL) == 0)
09902                      {
09903                             sendreport = TRUE;
09904                             break;
09905                      }
09906                      else if (strcasecmp(p, ARF_OPTIONS_DKIM_SYNTAX) == 0)
09907                      {
09908                             int err;
09909 
09910                             err = dkim_sig_geterror(sig);
09911 
09912                             if (err == DKIM_SIGERROR_TIMESTAMPS ||
09913                                 err == DKIM_SIGERROR_INVALID_HC ||
09914                                 err == DKIM_SIGERROR_INVALID_BC ||
09915                                 err == DKIM_SIGERROR_MISSING_A ||
09916                                 err == DKIM_SIGERROR_INVALID_A ||
09917                                 err == DKIM_SIGERROR_MISSING_H ||
09918                                 err == DKIM_SIGERROR_INVALID_L ||
09919                                 err == DKIM_SIGERROR_INVALID_Q ||
09920                                 err == DKIM_SIGERROR_INVALID_QO ||
09921                                 err == DKIM_SIGERROR_MISSING_D ||
09922                                 err == DKIM_SIGERROR_EMPTY_D ||
09923                                 err == DKIM_SIGERROR_MISSING_S ||
09924                                 err == DKIM_SIGERROR_EMPTY_S ||
09925                                 err == DKIM_SIGERROR_MISSING_B ||
09926                                 err == DKIM_SIGERROR_EMPTY_B ||
09927                                 err == DKIM_SIGERROR_CORRUPT_B ||
09928                                 err == DKIM_SIGERROR_MISSING_BH ||
09929                                 err == DKIM_SIGERROR_EMPTY_BH ||
09930                                 err == DKIM_SIGERROR_CORRUPT_BH ||
09931                                 err == DKIM_SIGERROR_EMPTY_H ||
09932                                 err == DKIM_SIGERROR_INVALID_H ||
09933                                 err == DKIM_SIGERROR_TOOLARGE_L ||
09934                                 err == DKIM_SIGERROR_MISSING_V ||
09935                                 err == DKIM_SIGERROR_EMPTY_V)
09936                             {
09937                                    sendreport = TRUE;
09938                                    break;
09939                             }
09940                      }
09941                      else if (strcasecmp(p, ARF_OPTIONS_DKIM_EXPIRED) == 0)
09942                      {
09943                             if (dkim_sig_geterror(sig) == DKIM_SIGERROR_EXPIRED)
09944                             {
09945                                    sendreport = TRUE;
09946                                    break;
09947                             }
09948                      }
09949                      else if (strcasecmp(p, ARF_OPTIONS_DKIM_VERIFY) == 0)
09950                      {
09951                             if (dkim_sig_geterror(sig) == DKIM_SIGERROR_BADSIG ||
09952                                 dkim_sig_getbh(sig) == DKIM_SIGBH_MISMATCH)
09953                             {
09954                                    sendreport = TRUE;
09955                                    break;
09956                             }
09957                      }
09958                      else if (strcasecmp(p, ARF_OPTIONS_DKIM_DNS) == 0)
09959                      {
09960                             int err;
09961 
09962                             err = dkim_sig_geterror(sig);
09963 
09964                             if (err == DKIM_SIGERROR_NOKEY ||
09965                                 err == DKIM_SIGERROR_DNSSYNTAX ||
09966                                 err == DKIM_SIGERROR_KEYFAIL ||
09967                                 err == DKIM_SIGERROR_KEYDECODE ||
09968                                 err == DKIM_SIGERROR_MULTIREPLY)
09969                             {
09970                                    sendreport = TRUE;
09971                                    break;
09972                             }
09973                      }
09974                      else if (strcasecmp(p, ARF_OPTIONS_DKIM_POLICY) == 0)
09975                      {
09976                             int err;
09977 
09978                             err = dkim_sig_geterror(sig);
09979 
09980                             if (err == DKIM_SIGERROR_MBSFAILED)
09981                             {
09982                                    sendreport = TRUE;
09983                                    break;
09984                             }
09985                      }
09986                      else if (strcasecmp(p, ARF_OPTIONS_DKIM_OTHER) == 0)
09987                      {
09988                             int err;
09989 
09990                             err = dkim_sig_geterror(sig);
09991 
09992                             if (err == DKIM_SIGERROR_SUBDOMAIN ||
09993                                 err == DKIM_SIGERROR_KEYVERSION ||
09994                                 err == DKIM_SIGERROR_KEYUNKNOWNHASH ||
09995                                 err == DKIM_SIGERROR_KEYHASHMISMATCH ||
09996                                 err == DKIM_SIGERROR_NOTEMAILKEY ||
09997                                 err == DKIM_SIGERROR_KEYTYPEMISSING ||
09998                                 err == DKIM_SIGERROR_KEYTYPEUNKNOWN ||
09999                                 err == DKIM_SIGERROR_KEYREVOKED)
10000                             {
10001                                    sendreport = TRUE;
10002                                    break;
10003                             }
10004                      }
10005               }
10006        }
10007 
10008        if (!sendreport)
10009               return;
10010 
10011        out = popen(reportcmd, "w");
10012        if (out == NULL)
10013        {
10014               if (conf->conf_dolog)
10015               {
10016                      syslog(LOG_ERR, "%s: popen(): %s",
10017                             dfc->mctx_jobid, strerror(errno));
10018               }
10019 
10020               return;
10021        }
10022 
10023        /* determine the type of ARF failure and, if needed, a DKIM fail code */
10024        arftype = dkimf_arftype(dfc);
10025        if (arftype == ARF_TYPE_AUTHFAIL)
10026               arfdkim = dkimf_arfdkim(dfc);
10027 
10028        /* From: */
10029        fprintf(out, "From: %s\n", reportaddr);
10030 
10031        /* To: */
10032        fprintf(out, "To: %s@%s\n", addr, dkim_sig_getdomain(sig));
10033 
10034        /* Bcc: */
10035        if (conf->conf_reportaddrbcc != NULL)
10036               fprintf(out, "Bcc: %s\n", conf->conf_reportaddrbcc);
10037 
10038        /* Date: */
10039        memset(fmt, '\0', sizeof fmt);
10040        (void) time(&now);
10041        (void) localtime_r(&now, &tm);
10042        (void) strftime(fmt, sizeof fmt, "%a, %e %b %Y %H:%M:%S %z (%Z)", &tm);
10043        fprintf(out, "Date: %s\n", fmt);
10044 
10045        /* Subject: */
10046        fprintf(out, "Subject: DKIM failure report for %s\n",
10047                dfc->mctx_jobid);
10048 
10049        /* MIME stuff */
10050        fprintf(out, "MIME-Version: 1.0\n");
10051        fprintf(out,
10052                "Content-Type: multipart/report; report-type=feedback-report;\n\tboundary=\"dkimreport/%s/%s\"",
10053                hostname, dfc->mctx_jobid);
10054 
10055        /* ok, now then... */
10056        fprintf(out, "\n");
10057 
10058        /* first part: a text blob explaining what this is */
10059        fprintf(out, "--dkimreport/%s/%s\n", hostname, dfc->mctx_jobid);
10060        fprintf(out, "Content-Type: text/plain\n");
10061        fprintf(out, "\n");
10062        fprintf(out, "DKIM failure report for job %s on %s\n\n",
10063                dfc->mctx_jobid, hostname);
10064        fprintf(out,
10065                "The canonicalized form of the failed message's header and body are\nattached.\n");
10066        fprintf(out, "\n");
10067 
10068        /* second part: formatted gunk */
10069        memset(ipstr, '\0', sizeof ipstr);
10070 
10071        switch (cc->cctx_ip.ss_family)
10072        {
10073          case AF_INET:
10074          {
10075               struct sockaddr_in sin4;
10076 
10077               memcpy(&sin4, &cc->cctx_ip, sizeof sin4);
10078 
10079               (void) inet_ntop(AF_INET, &sin4.sin_addr, ipstr, sizeof ipstr);
10080 
10081               break;
10082          }
10083 
10084 #ifdef AF_INET6
10085          case AF_INET6:
10086          {
10087               struct sockaddr_in6 sin6;
10088 
10089               memcpy(&sin6, &cc->cctx_ip, sizeof sin6);
10090 
10091               (void) inet_ntop(AF_INET6, &sin6.sin6_addr, ipstr, sizeof ipstr);
10092 
10093               break;
10094          }
10095 #endif /* AF_INET6 */
10096        }
10097 
10098        hdr = dkimf_findheader(dfc, (char *) "Message-ID", 0);
10099 
10100        fprintf(out, "--dkimreport/%s/%s\n", hostname, dfc->mctx_jobid);
10101        fprintf(out, "Content-Type: message/feedback-report\n");
10102        fprintf(out, "\n");
10103        fprintf(out, "User-Agent: %s/%s\n", DKIMF_PRODUCTNS, VERSION);
10104        fprintf(out, "Version: %s\n", ARF_VERSION);
10105        fprintf(out, "Original-Envelope-Id: %s\n", dfc->mctx_jobid);
10106        fprintf(out, "Original-Mail-From: %s\n", dfc->mctx_envfrom);
10107        fprintf(out, "Reporting-MTA: %s\n", hostname);
10108        fprintf(out, "Source-IP: %s\n", ipstr);
10109        fprintf(out, "Message-ID:%s%s\n",
10110                cc->cctx_noleadspc ? "" : " ",
10111                hdr == NULL ? "(none)" : hdr->hdr_val);
10112        fprintf(out, "Arrival-Date: %s\n", fmt);
10113        fprintf(out, "Reported-Domain: %s\n", dkim_sig_getdomain(sig));
10114        fprintf(out, "Delivery-Result: other\n");
10115        fprintf(out, "Feedback-Type: %s\n", arf_type_string(arftype));
10116        if (arftype == ARF_TYPE_AUTHFAIL)
10117        {
10118               fprintf(out, "Auth-Failure: ");
10119               if (dkim_sig_getbh(sig) == DKIM_SIGBH_MISMATCH)
10120               {
10121                      fprintf(out, "bodyhash\n");
10122               }
10123               else
10124               {
10125                      const char *tmperror;
10126 
10127                      switch (dkim_sig_geterror(sig))
10128                      {
10129                        case DKIM_SIGERROR_KEYREVOKED:
10130                             fprintf(out, "revoked\n");
10131                             break;
10132 
10133                        default:
10134                             tmperror = dkim_sig_geterrorstr(dkim_sig_geterror(sig));
10135                             fprintf(out, "signature");
10136                             if (tmperror != NULL)
10137                                    fprintf(out, " (%s)", tmperror);
10138                             fprintf(out, "\n");
10139                             break;
10140                      }
10141               }
10142 
10143               memset(addr, '\0', sizeof addr);
10144               dkim_sig_getidentity(dfc->mctx_dkimv, sig, addr,
10145                                    sizeof addr - 1);
10146 
10147               /* fprintf(out, "Authentication-Results: %s\n", ...); */
10148               fprintf(out, "DKIM-Failure: %s\n",
10149                       arf_dkim_failure_string(arfdkim));
10150               fprintf(out, "DKIM-Domain: %s\n", dkim_sig_getdomain(sig));
10151               fprintf(out, "DKIM-Selector: %s\n", dkim_sig_getselector(sig));
10152               fprintf(out, "DKIM-Identity: %s\n", addr);
10153               if (hfd != -1)
10154               {
10155                      fprintf(out, "DKIM-Canonicalized-Header: ");
10156                      (void) dkimf_base64_encode_file(hfd, out, 4, 75, 27);
10157                      fprintf(out, "\n");
10158               }
10159               if (bfd != -1)
10160               {
10161                      fprintf(out, "DKIM-Canonicalized-Body: ");
10162                      (void) dkimf_base64_encode_file(bfd, out, 4, 75, 25);
10163                      fprintf(out, "\n");
10164               }
10165        }
10166 
10167        fprintf(out, "\n");
10168 
10169        /* third part: header block */
10170        fprintf(out, "--dkimreport/%s/%s\n", hostname, dfc->mctx_jobid);
10171        fprintf(out, "Content-Type: text/rfc822-headers\n");
10172        fprintf(out, "\n");
10173 
10174        for (hdr = dfc->mctx_hqhead; hdr != NULL; hdr = hdr->hdr_next)
10175        {
10176               fprintf(out, "%s:%s%s\n", hdr->hdr_hdr,
10177                       cc->cctx_noleadspc ? "" : " ", hdr->hdr_val);
10178        }
10179 
10180        /* end */
10181        fprintf(out, "\n--dkimreport/%s/%s--\n", hostname, dfc->mctx_jobid);
10182