"Fossies" - the Fresh Open Source Software Archive

Member "s-nail-14.9.10/ssl.c" (25 Mar 2018, 11232 Bytes) of package /linux/misc/s-nail-14.9.10.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ssl.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 14.9.6_vs_14.9.7.

    1 /*@ S-nail - a mail user agent derived from Berkeley Mail.
    2  *@ Generic SSL / S/MIME commands.
    3  *
    4  * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
    5  * Copyright (c) 2012 - 2018 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
    6  */
    7 /*
    8  * Copyright (c) 2002
    9  * Gunnar Ritter.  All rights reserved.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. All advertising materials mentioning features or use of this software
   20  *    must display the following acknowledgement:
   21  * This product includes software developed by Gunnar Ritter
   22  * and his contributors.
   23  * 4. Neither the name of Gunnar Ritter nor the names of his contributors
   24  *    may be used to endorse or promote products derived from this software
   25  *    without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY GUNNAR RITTER AND CONTRIBUTORS ``AS IS'' AND
   28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   30  * ARE DISCLAIMED.  IN NO EVENT SHALL GUNNAR RITTER OR CONTRIBUTORS BE LIABLE
   31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   37  * SUCH DAMAGE.
   38  */
   39 #undef n_FILE
   40 #define n_FILE ssl
   41 
   42 #ifndef HAVE_AMALGAMATION
   43 # include "nail.h"
   44 #endif
   45 
   46 EMPTY_FILE()
   47 #ifdef HAVE_SSL
   48 struct ssl_verify_levels {
   49    char const              sv_name[8];
   50    enum ssl_verify_level   sv_level;
   51 };
   52 
   53 /* Supported SSL/TLS verification methods: update manual on change! */
   54 static struct ssl_verify_levels const  _ssl_verify_levels[] = {
   55    {"strict", SSL_VERIFY_STRICT},
   56    {"ask", SSL_VERIFY_ASK},
   57    {"warn", SSL_VERIFY_WARN},
   58    {"ignore", SSL_VERIFY_IGNORE}
   59 };
   60 
   61 FL void
   62 ssl_set_verify_level(struct url const *urlp)
   63 {
   64    size_t i;
   65    char *cp;
   66    NYD_ENTER;
   67 
   68    ssl_verify_level = SSL_VERIFY_ASK;
   69    cp = xok_vlook(ssl_verify, urlp, OXM_ALL);
   70 
   71    if (cp != NULL) {
   72       for (i = 0; i < n_NELEM(_ssl_verify_levels); ++i)
   73          if (!asccasecmp(_ssl_verify_levels[i].sv_name, cp)) {
   74             ssl_verify_level = _ssl_verify_levels[i].sv_level;
   75             goto jleave;
   76          }
   77       n_err(_("Invalid value of *ssl-verify*: %s\n"), cp);
   78    }
   79 jleave:
   80    NYD_LEAVE;
   81 }
   82 
   83 FL enum okay
   84 ssl_verify_decide(void)
   85 {
   86    enum okay rv = STOP;
   87    NYD_ENTER;
   88 
   89    switch (ssl_verify_level) {
   90    case SSL_VERIFY_STRICT:
   91       rv = STOP;
   92       break;
   93    case SSL_VERIFY_ASK:
   94       rv = getapproval(NULL, FAL0) ? OKAY : STOP;
   95       break;
   96    case SSL_VERIFY_WARN:
   97    case SSL_VERIFY_IGNORE:
   98       rv = OKAY;
   99       break;
  100    }
  101    NYD_LEAVE;
  102    return rv;
  103 }
  104 
  105 FL enum okay
  106 smime_split(FILE *ip, FILE **hp, FILE **bp, long xcount, int keep)
  107 {
  108    struct myline {
  109       struct myline  *ml_next;
  110       size_t         ml_len;
  111       char           ml_buf[n_VFIELD_SIZE(0)];
  112    } *head, *tail;
  113    char *buf;
  114    size_t bufsize, buflen, cnt;
  115    int c;
  116    enum okay rv = STOP;
  117    NYD_ENTER;
  118 
  119    if ((*hp = Ftmp(NULL, "smimeh", OF_RDWR | OF_UNLINK | OF_REGISTER)) == NULL)
  120       goto jetmp;
  121    if ((*bp = Ftmp(NULL, "smimeb", OF_RDWR | OF_UNLINK | OF_REGISTER)) ==NULL) {
  122       Fclose(*hp);
  123 jetmp:
  124       n_perr(_("tempfile"), 0);
  125       goto jleave;
  126    }
  127 
  128    head = tail = NULL;
  129    buf = smalloc(bufsize = LINESIZE);
  130    cnt = (xcount < 0) ? fsize(ip) : xcount;
  131 
  132    while (fgetline(&buf, &bufsize, &cnt, &buflen, ip, 0) != NULL &&
  133          *buf != '\n') {
  134       if (!ascncasecmp(buf, "content-", 8)) {
  135          if (keep)
  136             fputs("X-Encoded-", *hp);
  137          for (;;) {
  138             struct myline *ml = smalloc(n_VSTRUCT_SIZEOF(struct myline, ml_buf
  139                   ) + buflen +1);
  140             if (tail != NULL)
  141                tail->ml_next = ml;
  142             else
  143                head = ml;
  144             tail = ml;
  145             ml->ml_next = NULL;
  146             ml->ml_len = buflen;
  147             memcpy(ml->ml_buf, buf, buflen +1);
  148             if (keep)
  149                fwrite(buf, sizeof *buf, buflen, *hp);
  150             c = getc(ip);
  151             ungetc(c, ip);
  152             if (!blankchar(c))
  153                break;
  154             fgetline(&buf, &bufsize, &cnt, &buflen, ip, 0);
  155          }
  156          continue;
  157       }
  158       fwrite(buf, sizeof *buf, buflen, *hp);
  159    }
  160    fflush_rewind(*hp);
  161 
  162    while (head != NULL) {
  163       fwrite(head->ml_buf, sizeof *head->ml_buf, head->ml_len, *bp);
  164       tail = head;
  165       head = head->ml_next;
  166       free(tail);
  167    }
  168    putc('\n', *bp);
  169    while (fgetline(&buf, &bufsize, &cnt, &buflen, ip, 0) != NULL)
  170       fwrite(buf, sizeof *buf, buflen, *bp);
  171    fflush_rewind(*bp);
  172 
  173    free(buf);
  174    rv = OKAY;
  175 jleave:
  176    NYD_LEAVE;
  177    return rv;
  178 }
  179 
  180 FL FILE *
  181 smime_sign_assemble(FILE *hp, FILE *bp, FILE *sp, char const *message_digest)
  182 {
  183    char *boundary;
  184    int c, lastc = EOF;
  185    FILE *op;
  186    NYD_ENTER;
  187 
  188    if ((op = Ftmp(NULL, "smimea", OF_RDWR | OF_UNLINK | OF_REGISTER)) == NULL) {
  189       n_perr(_("tempfile"), 0);
  190       goto jleave;
  191    }
  192 
  193    while ((c = getc(hp)) != EOF) {
  194       if (c == '\n' && lastc == '\n')
  195          break;
  196       putc(c, op);
  197       lastc = c;
  198    }
  199 
  200    boundary = mime_param_boundary_create();
  201    fprintf(op, "Content-Type: multipart/signed;\n"
  202       " protocol=\"application/pkcs7-signature\"; micalg=%s;\n"
  203       " boundary=\"%s\"\n\n", message_digest, boundary);
  204    fprintf(op, "This is a S/MIME signed message.\n\n--%s\n", boundary);
  205    while ((c = getc(bp)) != EOF)
  206       putc(c, op);
  207 
  208    fprintf(op, "\n--%s\n", boundary);
  209    fputs("Content-Type: application/pkcs7-signature; name=\"smime.p7s\"\n"
  210       "Content-Transfer-Encoding: base64\n"
  211       "Content-Disposition: attachment; filename=\"smime.p7s\"\n"
  212       "Content-Description: S/MIME digital signature\n\n", op);
  213    while ((c = getc(sp)) != EOF) {
  214       if (c == '-') {
  215          while ((c = getc(sp)) != EOF && c != '\n');
  216          continue;
  217       }
  218       putc(c, op);
  219    }
  220 
  221    fprintf(op, "\n--%s--\n", boundary);
  222 
  223    Fclose(hp);
  224    Fclose(bp);
  225    Fclose(sp);
  226 
  227    fflush(op);
  228    if (ferror(op)) {
  229       n_perr(_("signed output data"), 0);
  230       Fclose(op);
  231       op = NULL;
  232       goto jleave;
  233    }
  234    rewind(op);
  235 jleave:
  236    NYD_LEAVE;
  237    return op;
  238 }
  239 
  240 FL FILE *
  241 smime_encrypt_assemble(FILE *hp, FILE *yp)
  242 {
  243    FILE *op;
  244    int c, lastc = EOF;
  245    NYD_ENTER;
  246 
  247    if ((op = Ftmp(NULL, "smimee", OF_RDWR | OF_UNLINK | OF_REGISTER)) == NULL) {
  248       n_perr(_("tempfile"), 0);
  249       goto jleave;
  250    }
  251 
  252    while ((c = getc(hp)) != EOF) {
  253       if (c == '\n' && lastc == '\n')
  254          break;
  255       putc(c, op);
  256       lastc = c;
  257    }
  258 
  259    fputs("Content-Type: application/pkcs7-mime; name=\"smime.p7m\"\n"
  260       "Content-Transfer-Encoding: base64\n"
  261       "Content-Disposition: attachment; filename=\"smime.p7m\"\n"
  262       "Content-Description: S/MIME encrypted message\n\n", op);
  263    while ((c = getc(yp)) != EOF) {
  264       if (c == '-') {
  265          while ((c = getc(yp)) != EOF && c != '\n');
  266          continue;
  267       }
  268       putc(c, op);
  269    }
  270 
  271    Fclose(hp);
  272    Fclose(yp);
  273 
  274    fflush(op);
  275    if (ferror(op)) {
  276       n_perr(_("encrypted output data"), 0);
  277       Fclose(op);
  278       op = NULL;
  279       goto jleave;
  280    }
  281    rewind(op);
  282 jleave:
  283    NYD_LEAVE;
  284    return op;
  285 }
  286 
  287 FL struct message *
  288 smime_decrypt_assemble(struct message *m, FILE *hp, FILE *bp)
  289 {
  290    ui32_t lastnl = 0;
  291    int binary = 0;
  292    char *buf = NULL;
  293    size_t bufsize = 0, buflen, cnt;
  294    long lines = 0, octets = 0;
  295    struct message *x;
  296    off_t offset;
  297    NYD_ENTER;
  298 
  299    x = salloc(sizeof *x);
  300    *x = *m;
  301    fflush(mb.mb_otf);
  302    fseek(mb.mb_otf, 0L, SEEK_END);
  303    offset = ftell(mb.mb_otf);
  304 
  305    cnt = fsize(hp);
  306    while (fgetline(&buf, &bufsize, &cnt, &buflen, hp, 0) != NULL) {
  307       char const *cp;
  308       if (buf[0] == '\n')
  309          break;
  310       if ((cp = thisfield(buf, "content-transfer-encoding")) != NULL)
  311          if (!ascncasecmp(cp, "binary", 7))
  312             binary = 1;
  313       fwrite(buf, sizeof *buf, buflen, mb.mb_otf);
  314       octets += buflen;
  315       ++lines;
  316    }
  317 
  318    {  struct time_current save = time_current;
  319       time_current_update(&time_current, TRU1);
  320       octets += mkdate(mb.mb_otf, "X-Decoding-Date");
  321       time_current = save;
  322    }
  323    ++lines;
  324 
  325    cnt = fsize(bp);
  326    while (fgetline(&buf, &bufsize, &cnt, &buflen, bp, 0) != NULL) {
  327       lines++;
  328       if (!binary && buf[buflen - 1] == '\n' && buf[buflen - 2] == '\r')
  329          buf[--buflen - 1] = '\n';
  330       fwrite(buf, sizeof *buf, buflen, mb.mb_otf);
  331       octets += buflen;
  332       if (buf[0] == '\n')
  333          ++lastnl;
  334       else if (buf[buflen - 1] == '\n')
  335          lastnl = 1;
  336       else
  337          lastnl = 0;
  338    }
  339 
  340    while (!binary && lastnl < 2) {
  341       putc('\n', mb.mb_otf);
  342       ++lines;
  343       ++octets;
  344       ++lastnl;
  345    }
  346 
  347    Fclose(hp);
  348    Fclose(bp);
  349    free(buf);
  350 
  351    fflush(mb.mb_otf);
  352    if (ferror(mb.mb_otf)) {
  353       n_perr(_("decrypted output data"), 0);
  354       x = NULL;
  355    }else{
  356       x->m_size = x->m_xsize = octets;
  357       x->m_lines = x->m_xlines = lines;
  358       x->m_block = mailx_blockof(offset);
  359       x->m_offset = mailx_offsetof(offset);
  360    }
  361    NYD_LEAVE;
  362    return x;
  363 }
  364 
  365 FL int
  366 c_certsave(void *v)
  367 {
  368    int *ip, *msgvec, val;
  369    char *file = NULL, *str = v;
  370    FILE *fp;
  371    bool_t f;
  372    NYD_ENTER;
  373 
  374    msgvec = salloc((msgCount + 2) * sizeof *msgvec);
  375    val = 1;
  376 
  377    if ((file = laststring(str, &f, TRU1)) == NULL ||
  378          (file = fexpand(file, FEXP_LOCAL | FEXP_NOPROTO)) == NULL) {
  379       n_err(_("No file to save certificate given\n"));
  380       goto jleave;
  381    }
  382 
  383    if (!f) {
  384       msgvec[1] = 0;
  385       *msgvec = first(0, MMNORM);
  386    } else if (getmsglist(str, msgvec, 0) < 0)
  387       goto jleave;
  388    if (*msgvec == 0) {
  389       if (n_pstate & (n_PS_HOOK_MASK | n_PS_ROBOT))
  390          val = 0;
  391       else
  392          n_err(_("No applicable messages\n"));
  393       goto jleave;
  394    }
  395 
  396    if ((fp = Fopen(file, "a")) == NULL) {
  397       n_perr(file, 0);
  398       goto jleave;
  399    }
  400    for (val = 0, ip = msgvec;
  401          *ip != 0 && UICMP(z, PTR2SIZE(ip - msgvec), <, msgCount); ++ip)
  402       if (smime_certsave(&message[*ip - 1], *ip, fp) != OKAY)
  403          val = 1;
  404    Fclose(fp);
  405 
  406    if (val == 0)
  407       fprintf(n_stdout, "Certificate(s) saved\n");
  408 jleave:
  409    NYD_LEAVE;
  410    return val;
  411 }
  412 
  413 FL enum okay
  414 rfc2595_hostname_match(char const *host, char const *pattern)
  415 {
  416    enum okay rv;
  417    NYD_ENTER;
  418 
  419    if (pattern[0] == '*' && pattern[1] == '.') {
  420       ++pattern;
  421       while (*host && *host != '.')
  422          ++host;
  423    }
  424    rv = !asccasecmp(host, pattern) ? OKAY : STOP;
  425    NYD_LEAVE;
  426    return rv;
  427 }
  428 #endif /* HAVE_SSL */
  429 
  430 /* s-it-mode */