Logo Search packages:      
Sourcecode: heirloom-mailx version File versions  Download package

ssl.c

/*
 * Heirloom mailx - a mail user agent derived from Berkeley Mail.
 *
 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
 */
/*
 * Copyright (c) 2002
 *    Gunnar Ritter.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    This product includes software developed by Gunnar Ritter
 *    and his contributors.
 * 4. Neither the name of Gunnar Ritter nor the names of his contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY GUNNAR RITTER AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL GUNNAR RITTER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef lint
#ifdef      DOSCCS
static char sccsid[] = "@(#)ssl.c   1.39 (gritter) 6/12/06";
#endif
#endif /* not lint */

#include "config.h"

#ifdef      USE_SSL

#include "rcv.h"
#include "extern.h"

void 
ssl_set_vrfy_level(const char *uhp)
{
      char *cp;
      char *vrvar;

      ssl_vrfy_level = VRFY_ASK;
      vrvar = ac_alloc(strlen(uhp) + 12);
      strcpy(vrvar, "ssl-verify-");
      strcpy(&vrvar[11], uhp);
      if ((cp = value(vrvar)) == NULL)
            cp = value("ssl-verify");
      ac_free(vrvar);
      if (cp != NULL) {
            if (equal(cp, "strict"))
                  ssl_vrfy_level = VRFY_STRICT;
            else if (equal(cp, "ask"))
                  ssl_vrfy_level = VRFY_ASK;
            else if (equal(cp, "warn"))
                  ssl_vrfy_level = VRFY_WARN;
            else if (equal(cp, "ignore"))
                  ssl_vrfy_level = VRFY_IGNORE;
            else
                  fprintf(stderr, catgets(catd, CATSET, 265,
                              "invalid value of ssl-verify: %s\n"),
                              cp);
      }
}

enum okay 
ssl_vrfy_decide(void)
{
      enum okay ok = STOP;

      switch (ssl_vrfy_level) {
      case VRFY_STRICT:
            ok = STOP;
            break;
      case VRFY_ASK:
            {
                  char *line = NULL;
                  size_t linesize = 0;

                  fprintf(stderr, catgets(catd, CATSET, 264,
                              "Continue (y/n)? "));
                  if (readline(stdin, &line, &linesize) > 0 &&
                              *line == 'y')
                        ok = OKAY;
                  else
                        ok = STOP;
                  if (line)
                        free(line);
            }
            break;
      case VRFY_WARN:
      case VRFY_IGNORE:
            ok = OKAY;
      }
      return ok;
}

char *
ssl_method_string(const char *uhp)
{
      char *cp, *mtvar;

      mtvar = ac_alloc(strlen(uhp) + 12);
      strcpy(mtvar, "ssl-method-");
      strcpy(&mtvar[11], uhp);
      if ((cp = value(mtvar)) == NULL)
            cp = value("ssl-method");
      ac_free(mtvar);
      return cp;
}

enum okay
smime_split(FILE *ip, FILE **hp, FILE **bp, long xcount, int keep)
{
      char  *buf, *hn, *bn;
      char  *savedfields = NULL;
      size_t      bufsize, buflen, count, savedsize = 0;
      int   c;

      if ((*hp = Ftemp(&hn, "Rh", "w+", 0600, 1)) == NULL ||
                  (*bp = Ftemp(&bn, "Rb", "w+", 0600, 1)) == NULL) {
            perror("tempfile");
            return STOP;
      }
      rm(hn);
      rm(bn);
      Ftfree(&hn);
      Ftfree(&bn);
      buf = smalloc(bufsize = LINESIZE);
      savedfields = smalloc(savedsize = 1);
      *savedfields = '\0';
      if (xcount < 0)
            count = fsize(ip);
      else
            count = xcount;
      while (fgetline(&buf, &bufsize, &count, &buflen, ip, 0) != NULL &&
                  *buf != '\n') {
            if (ascncasecmp(buf, "content-", 8) == 0) {
                  if (keep)
                        fputs("X-Encoded-", *hp);
                  for (;;) {
                        savedsize += buflen;
                        savedfields = srealloc(savedfields, savedsize);
                        strcat(savedfields, buf);
                        if (keep)
                              fwrite(buf, sizeof *buf, buflen, *hp);
                        c = getc(ip);
                        ungetc(c, ip);
                        if (!blankchar(c))
                              break;
                        fgetline(&buf, &bufsize, &count, &buflen,
                                    ip, 0);
                  }
                  continue;
            }
            fwrite(buf, sizeof *buf, buflen, *hp);
      }
      fflush(*hp);
      rewind(*hp);
      fputs(savedfields, *bp);
      putc('\n', *bp);
      while (fgetline(&buf, &bufsize, &count, &buflen, ip, 0) != NULL)
            fwrite(buf, sizeof *buf, buflen, *bp);
      fflush(*bp);
      rewind(*bp);
      free(buf);
      return OKAY;
}

FILE *
smime_sign_assemble(FILE *hp, FILE *bp, FILE *sp)
{
      char  *boundary, *cp;
      FILE  *op;
      int   c, lastc = EOF;

      if ((op = Ftemp(&cp, "Rs", "w+", 0600, 1)) == NULL) {
            perror("tempfile");
            return NULL;
      }
      rm(cp);
      Ftfree(&cp);
      boundary = makeboundary();
      while ((c = getc(hp)) != EOF) {
            if (c == '\n' && lastc == '\n')
                  break;
            putc(c, op);
            lastc = c;
      }
      fprintf(op, "Content-Type: multipart/signed;\n"
            " protocol=\"application/x-pkcs7-signature\"; micalg=sha1;\n"
            " boundary=\"%s\"\n\n", boundary);
      fprintf(op, "This is an S/MIME signed message.\n\n--%s\n",
                  boundary);
      while ((c = getc(bp)) != EOF)
            putc(c, op);
      fprintf(op, "\n--%s\n", boundary);
      fputs("Content-Type: application/x-pkcs7-signature; "
                  "name=\"smime.p7s\"\n"
            "Content-Transfer-Encoding: base64\n"
            "Content-Disposition: attachment; filename=\"smime.p7s\"\n\n",
            op);
      while ((c = getc(sp)) != EOF) {
            if (c == '-') {
                  while ((c = getc(sp)) != EOF && c != '\n');
                  continue;
            }
            putc(c, op);
      }
      fprintf(op, "\n--%s--\n", boundary);
      Fclose(hp);
      Fclose(bp);
      Fclose(sp);
      fflush(op);
      if (ferror(op)) {
            perror("signed output data");
            Fclose(op);
            return NULL;
      }
      rewind(op);
      return op;
}

FILE *
smime_encrypt_assemble(FILE *hp, FILE *yp)
{
      char  *cp;
      FILE  *op;
      int   c, lastc = EOF;

      if ((op = Ftemp(&cp, "Rs", "w+", 0600, 1)) == NULL) {
            perror("tempfile");
            return NULL;
      }
      rm(cp);
      Ftfree(&cp);
      while ((c = getc(hp)) != EOF) {
            if (c == '\n' && lastc == '\n')
                  break;
            putc(c, op);
            lastc = c;
      }
      fprintf(op, "Content-Type: application/x-pkcs7-mime; "
                  "name=\"smime.p7m\"\n"
            "Content-Transfer-Encoding: base64\n"
            "Content-Disposition: attachment; "
                  "filename=\"smime.p7m\"\n\n");
      while ((c = getc(yp)) != EOF) {
            if (c == '-') {
                  while ((c = getc(yp)) != EOF && c != '\n');
                  continue;
            }
            putc(c, op);
      }
      Fclose(hp);
      Fclose(yp);
      fflush(op);
      if (ferror(op)) {
            perror("encrypted output data");
            Fclose(op);
            return NULL;
      }
      rewind(op);
      return op;
}

struct message *
smime_decrypt_assemble(struct message *m, FILE *hp, FILE *bp)
{
      int   binary = 0, lastnl = 0;
      char  *buf = NULL, *cp;
      size_t      bufsize = 0, buflen, count;
      long  lines = 0, octets = 0;
      struct message    *x;
      off_t offset;

      x = salloc(sizeof *x);
      *x = *m;
      fflush(mb.mb_otf);
      fseek(mb.mb_otf, 0L, SEEK_END);
      offset = ftell(mb.mb_otf);
      count = fsize(hp);
      while (fgetline(&buf, &bufsize, &count, &buflen, hp, 0) != NULL) {
            if (buf[0] == '\n')
                  break;
            if ((cp = thisfield(buf, "content-transfer-encoding")) != NULL)
                  if (ascncasecmp(cp, "binary", 7) == 0)
                        binary = 1;
            fwrite(buf, sizeof *buf, buflen, mb.mb_otf);
            octets += buflen;
            lines++;
      }
      octets += mkdate(mb.mb_otf, "X-Decoding-Date");
      lines++;
      count = fsize(bp);
      while (fgetline(&buf, &bufsize, &count, &buflen, bp, 0) != NULL) {
            lines++;
            if (!binary && buf[buflen-1] == '\n' && buf[buflen-2] == '\r')
                  buf[--buflen-1] = '\n';
            fwrite(buf, sizeof *buf, buflen, mb.mb_otf);
            octets += buflen;
            if (buf[0] == '\n')
                  lastnl++;
            else if (buf[buflen-1] == '\n')
                  lastnl = 1;
            else
                  lastnl = 0;
      }
      while (!binary && lastnl < 2) {
            putc('\n', mb.mb_otf);
            lines++;
            octets++;
            lastnl++;
      }
      Fclose(hp);
      Fclose(bp);
      free(buf);
      fflush(mb.mb_otf);
      if (ferror(mb.mb_otf)) {
            perror("decrypted output data");
            return NULL;
      }
      x->m_size = x->m_xsize = octets;
      x->m_lines = x->m_xlines = lines;
      x->m_block = mailx_blockof(offset);
      x->m_offset = mailx_offsetof(offset);
      return x;
}

int 
ccertsave(void *v)
{
      int   *ip;
      int   f, *msgvec;
      char  *file = NULL, *str = v;
      int   val = 0;
      FILE  *fp;

      msgvec = salloc((msgCount + 2) * sizeof *msgvec);
      if ((file = laststring(str, &f, 1)) == NULL) {
            fprintf(stderr, "No file to save certificate given.\n");
            return 1;
      }
      if (!f) {
            *msgvec = first(0, MMNORM);
            if (*msgvec == 0) {
                  if (inhook)
                        return 0;
                  fprintf(stderr,
                        "No messages to get certificates from.\n");
                  return 1;
            }
            msgvec[1] = 0;
      } else if (getmsglist(str, msgvec, 0) < 0)
            return 1;
      if (*msgvec == 0) {
            if (inhook)
                  return 0;
            fprintf(stderr, "No applicable messages.\n");
            return 1;
      }
      if ((fp = Fopen(file, "a")) == NULL) {
            perror(file);
            return 1;
      }
      for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++)
            if (smime_certsave(&message[*ip-1], *ip, fp) != OKAY)
                  val = 1;
      Fclose(fp);
      if (val == 0)
            printf("Certificate(s) saved.\n");
      return val;
}
enum okay
rfc2595_hostname_match(const char *host, const char *pattern)
{
      if (pattern[0] == '*' && pattern[1] == '.') {
            pattern++;
            while (*host && *host != '.')
                  host++;
      }
      return asccasecmp(host, pattern) == 0 ? OKAY : STOP;
}
#endif      /* USE_SSL */

Generated by  Doxygen 1.6.0   Back to index