Back to index

opendkim  2.6.6
opendkim-testmsg.c
Go to the documentation of this file.
00001 /*
00002 **  Copyright (c) 2011, The OpenDKIM Project.  All rights reserved.
00003 **
00004 **  $Id: opendkim-testmsg.c,v 1.8 2010/06/19 15:29:12 cm-msk Exp $
00005 */
00006 
00007 #ifndef lint
00008 static char opendkim_testmsg_c_id[] = "@(#)$Id: opendkim-testadsp.c,v 1.8 2010/06/19 15:29:12 cm-msk Exp $";
00009 #endif /* !lint */
00010 
00011 /* system includes */
00012 #include <sys/types.h>
00013 #include <sys/stat.h>
00014 #include <stdlib.h>
00015 #include <fcntl.h>
00016 #include <errno.h>
00017 #include <stdio.h>
00018 #include <sysexits.h>
00019 #include <string.h>
00020 #include <unistd.h>
00021 
00022 /* libopendkim includes */
00023 #include <dkim.h>
00024 
00025 /* macros */
00026 #ifndef FALSE
00027 # define FALSE              0
00028 #endif /* ! FALSE */
00029 #ifndef TRUE
00030 # define TRUE        1
00031 #endif /* ! TRUE */
00032 
00033 #define       BUFRSZ        1024
00034 #define       CMDLINEOPTS   "Cd:k:s:"
00035 #define STRORNULL(x) ((x) == NULL ? "(null)" : (x))
00036 #define       TMPTEMPLATE   "/var/tmp/dkimXXXXXX"
00037 
00038 /* prototypes */
00039 int usage(void);
00040 
00041 /* globals */
00042 char *progname;
00043 
00044 /*
00045 **  USAGE -- print a usage message
00046 **
00047 **  Parameters:
00048 **     None.
00049 **
00050 **  Return value:
00051 **     EX_CONFIG
00052 */
00053 
00054 int
00055 usage(void)
00056 {
00057        fprintf(stderr,
00058                "%s: usage: %s [options]\nValid options:\n"
00059                "\t-C         \tpreserve CRLFs\n"
00060                "\t-d domain  \tset signing domain\n"
00061                "\t-k keyfile \tprivate key file\n"
00062                "\t-s selector\tset signing selector\n",
00063                progname, progname);
00064 
00065        return EX_CONFIG;
00066 }
00067 
00068 /*
00069 **  DECR -- remove CRs from a string
00070 **
00071 **  Parameters:
00072 **     str -- string to modify; must be NULL-terminated
00073 **
00074 **  Return value:
00075 **     None.
00076 */
00077 
00078 void
00079 decr(char *str)
00080 {
00081        char *p;
00082        char *q;
00083 
00084        for (p = str, q = str; *p != '\0'; p++)
00085        {
00086               if (*p == '\r')
00087                      continue;
00088 
00089               if (p != q)
00090                      *q = *p;
00091 
00092               q++;
00093        }
00094 }
00095 
00096 /*
00097 **  MAIN -- program mainline
00098 **
00099 **  Parameters:
00100 **     argc, argv -- the usual
00101 **
00102 **  Return value:
00103 **     Exit status.
00104 */
00105 
00106 int
00107 main(int argc, char **argv)
00108 {
00109        _Bool keepcrlf = FALSE;
00110        _Bool testkey = FALSE;
00111        int c;
00112        int n = 0;
00113        int tfd;
00114        dkim_policy_t pcode;
00115        int presult;
00116        u_int flags;
00117        DKIM_STAT status;
00118        ssize_t rlen;
00119        ssize_t wlen;
00120        ssize_t l = (ssize_t) -1;
00121        dkim_alg_t sa = DKIM_SIGN_RSASHA1;
00122        dkim_canon_t bc = DKIM_CANON_SIMPLE;
00123        dkim_canon_t hc = DKIM_CANON_RELAXED;
00124        DKIM_LIB *lib;
00125        DKIM *dkim;
00126        char *p;
00127        const char *domain = NULL;
00128        const char *selector = NULL;
00129        const char *keyfile = NULL;
00130        char *keydata = NULL;
00131        char buf[BUFRSZ];
00132        char fn[BUFRSZ];
00133 
00134        progname = (p = strrchr(argv[0], '/')) == NULL ? argv[0] : p + 1;
00135 
00136        memset(fn, '\0', sizeof fn);
00137        strncpy(fn, TMPTEMPLATE, sizeof fn);
00138 
00139        while ((c = getopt(argc, argv, CMDLINEOPTS)) != -1)
00140        {
00141               switch (c)
00142               {
00143                 case 'C':
00144                      keepcrlf = TRUE;
00145                      break;
00146 
00147                 case 'd':
00148                      domain = optarg;
00149                      n++;
00150                      break;
00151 
00152                 case 'k':
00153                      keyfile = optarg;
00154                      n++;
00155                      break;
00156 
00157                 case 's':
00158                      selector = optarg;
00159                      n++;
00160                      break;
00161 
00162                 default:
00163                      return usage();
00164               }
00165        }
00166 
00167        if (n != 0 && n != 3)
00168               return usage();
00169 
00170        if (n == 3)
00171        {
00172               int fd;
00173               struct stat s;
00174 
00175               fd = open(keyfile, O_RDONLY);
00176               if (fd < 0)
00177               {
00178                      fprintf(stderr, "%s: %s: open(): %s\n", progname,
00179                              keyfile, strerror(errno));
00180                      return EX_OSERR;
00181               }
00182 
00183               if (fstat(fd, &s) != 0)
00184               {
00185                      fprintf(stderr, "%s: %s: fstat(): %s\n", progname,
00186                              keyfile, strerror(errno));
00187                      close(fd);
00188                      return EX_OSERR;
00189               }
00190 
00191               keydata = malloc(s.st_size + 1);
00192               if (keydata == NULL)
00193               {
00194                      fprintf(stderr, "%s: malloc(): %s\n", progname,
00195                              strerror(errno));
00196                      close(fd);
00197                      return EX_OSERR;
00198               }
00199 
00200               memset(keydata, '\0', s.st_size + 1);
00201               rlen = read(fd, keydata, s.st_size);
00202               if (rlen == -1)
00203               {
00204                      fprintf(stderr, "%s: %s: read(): %s\n", progname,
00205                              keyfile, strerror(errno));
00206                      close(fd);
00207                      free(keydata);
00208                      return EX_OSERR;
00209               }
00210               else if (rlen < s.st_size)
00211               {
00212                      fprintf(stderr,
00213                              "%s: %s: read() truncated (got %ud, expected %ud)\n",
00214                              progname, keyfile, rlen, s.st_size);
00215                      close(fd);
00216                      free(keydata);
00217                      return EX_DATAERR;
00218               }
00219 
00220               close(fd);
00221        }
00222 
00223        lib = dkim_init(NULL, NULL);
00224        if (lib == NULL)
00225        {
00226               fprintf(stderr, "%s: dkim_init() failed\n", progname);
00227               return EX_SOFTWARE;
00228        }
00229 
00230        if (n == 0)
00231        {
00232               dkim = dkim_verify(lib, progname, NULL, &status);
00233               if (dkim == NULL)
00234               {
00235                      fprintf(stderr, "%s: dkim_verify() failed: %s\n",
00236                              progname, dkim_getresultstr(status));
00237                      dkim_close(lib);
00238                      return EX_SOFTWARE;
00239               }
00240        }
00241        else
00242        {
00243               dkim = dkim_sign(lib, progname, NULL, keydata, selector,
00244                                domain, hc, bc, sa, l, &status);
00245               if (dkim == NULL)
00246               {
00247                      fprintf(stderr, "%s: dkim_sign() failed: %s\n",
00248                              progname, dkim_getresultstr(status));
00249                      if (keydata != NULL)
00250                             free(keydata);
00251                      dkim_close(lib);
00252                      return EX_SOFTWARE;
00253               }
00254        }
00255 
00256        /* set flags */
00257        flags = DKIM_LIBFLAGS_FIXCRLF;
00258        (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags,
00259                            sizeof flags);
00260 
00261        tfd = mkstemp(fn);
00262        if (tfd < 0)
00263        {
00264               fprintf(stderr, "%s: mkstemp(): %s\n",
00265                       progname, strerror(errno));
00266               if (keydata != NULL)
00267                      free(keydata);
00268               dkim_close(lib);
00269               return EX_SOFTWARE;
00270        }
00271 
00272        for (;;)
00273        {
00274               rlen = fread(buf, 1, sizeof buf, stdin);
00275               if (ferror(stdin))
00276               {
00277                      fprintf(stderr, "%s: fread(): %s\n",
00278                              progname, strerror(errno));
00279                      dkim_free(dkim);
00280                      dkim_close(lib);
00281                      close(tfd);
00282                      if (keydata != NULL)
00283                             free(keydata);
00284                      return EX_SOFTWARE;
00285               }
00286 
00287               wlen = write(tfd, buf, rlen);
00288               if (wlen == -1)
00289               {
00290                      fprintf(stderr, "%s: %s: write(): %s\n",
00291                              progname, fn, strerror(errno));
00292                      dkim_free(dkim);
00293                      dkim_close(lib);
00294                      close(tfd);
00295                      if (keydata != NULL)
00296                             free(keydata);
00297                      return EX_SOFTWARE;
00298               }
00299 
00300               status = dkim_chunk(dkim, buf, rlen);
00301               if (status != DKIM_STAT_OK)
00302               {
00303                      fprintf(stderr, "%s: dkim_chunk(): %s\n",
00304                              progname, dkim_getresultstr(status));
00305                      dkim_free(dkim);
00306                      dkim_close(lib);
00307                      close(tfd);
00308                      if (keydata != NULL)
00309                             free(keydata);
00310                      return EX_SOFTWARE;
00311               }
00312 
00313               if (feof(stdin))
00314                      break;
00315        }
00316 
00317        status = dkim_chunk(dkim, NULL, 0);
00318        if (status != DKIM_STAT_OK)
00319        {
00320               fprintf(stderr, "%s: dkim_chunk(): %s\n",
00321                       progname, dkim_getresultstr(status));
00322               dkim_free(dkim);
00323               dkim_close(lib);
00324               close(tfd);
00325               if (keydata != NULL)
00326                      free(keydata);
00327               return EX_SOFTWARE;
00328        }
00329 
00330        status = dkim_eom(dkim, &testkey);
00331        if (status != DKIM_STAT_OK)
00332        {
00333               fprintf(stderr, "%s: dkim_eom(): %s\n",
00334                       progname, dkim_getresultstr(status));
00335               dkim_free(dkim);
00336               dkim_close(lib);
00337               close(tfd);
00338               if (keydata != NULL)
00339                      free(keydata);
00340               return EX_SOFTWARE;
00341        }
00342 
00343        if (n == 0)
00344        {
00345               /* XXX -- do a policy query */
00346        }
00347        else
00348        {
00349               unsigned char *sighdr;
00350               size_t siglen;
00351 
00352               /* extract signature */
00353               status = dkim_getsighdr_d(dkim,
00354                                         strlen(DKIM_SIGNHEADER),
00355                                         &sighdr, &siglen);
00356               if (status != DKIM_STAT_OK)
00357               {
00358                      fprintf(stderr, "%s: dkim_getsighdr_d(): %s\n",
00359                              progname, dkim_getresultstr(status));
00360                      dkim_free(dkim);
00361                      dkim_close(lib);
00362                      close(tfd);
00363                      if (keydata != NULL)
00364                             free(keydata);
00365                      return EX_SOFTWARE;
00366               }
00367 
00368               /* print it and the message */
00369               if (!keepcrlf)
00370                      decr(sighdr);
00371               fprintf(stdout, "%s: %s%s\n", DKIM_SIGNHEADER, sighdr,
00372                       keepcrlf ? "\r" : "");
00373               (void) lseek(tfd, 0, SEEK_SET);
00374               for (;;)
00375               {
00376                      rlen = read(tfd, buf, sizeof buf);
00377                      (void) fwrite(buf, 1, rlen, stdout);
00378                      if (rlen < sizeof buf)
00379                             break;
00380               }
00381        }
00382 
00383        dkim_free(dkim);
00384        dkim_close(lib);
00385        close(tfd);
00386        if (keydata != NULL)
00387               free(keydata);
00388 
00389        return EX_OK;
00390 }