Back to index

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