/[imapfilter]/imapfilter/file.c
ViewVC logotype

Diff of /imapfilter/file.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.49 by lefcha, Sat Mar 15 18:50:23 2003 UTC revision 1.50 by lefcha, Sat Mar 22 15:09:33 2003 UTC
# Line 5  Line 5 
5  #include <regex.h>  #include <regex.h>
6  #include <string.h>  #include <string.h>
7  #include <stdlib.h>  #include <stdlib.h>
8    #include <ctype.h>
9  #include <limits.h>  #include <limits.h>
10  #include <sys/stat.h>  #include <sys/stat.h>
11  #include <fcntl.h>  #include <fcntl.h>
# Line 14  Line 15 
15  #include "imapfilter.h"  #include "imapfilter.h"
16  #include "data.h"  #include "data.h"
17    
18    #ifdef SSL_TLS
19    #include <openssl/ssl.h>
20    #include <openssl/x509.h>
21    #include <openssl/pem.h>
22    #endif
23    
24    
25  extern char logfile[PATH_MAX];  extern char logfile[PATH_MAX];
26  extern unsigned int options;  extern unsigned int options;
# Line 546  check_dir_perms(char *dname, mode_t mode Line 553  check_dir_perms(char *dname, mode_t mode
553          }          }
554          if ((ds.st_mode & 00777) != mode) {          if ((ds.st_mode & 00777) != mode) {
555                  error("warning: improper dir %s permissions\n", dname);                  error("warning: improper dir %s permissions\n", dname);
556                  error("warning: file's mode should be %o not %o\n", mode,                  error("warning: dir's mode should be %o not %o\n", mode,
557                      ds.st_mode & 00777);                      ds.st_mode & 00777);
558                  return ERROR_TRIVIAL;                  return ERROR_TRIVIAL;
559          }          }
# Line 554  check_dir_perms(char *dname, mode_t mode Line 561  check_dir_perms(char *dname, mode_t mode
561  }  }
562    
563  #endif                          /* CHECK_PERMISSIONS */  #endif                          /* CHECK_PERMISSIONS */
564    
565    
566    #ifdef SSL_TLS
567    /*
568     * Get SSL/TLS certificate check it, maybe ask user about it and act
569     * accordingly.
570     */
571    int
572    imf_ssl_cert(SSL * ssl)
573    {
574            X509 *cert;
575            unsigned char md[EVP_MAX_MD_SIZE];
576            unsigned int mdlen;
577    
578            mdlen = 0;
579    
580            if (!(cert = SSL_get_peer_certificate(ssl)))
581                    return ERROR_SSL;
582    
583            if (!(X509_digest(cert, EVP_md5(), md, &mdlen)))
584                    return ERROR_SSL;
585    
586            switch (imf_ssl_check_cert(cert, md, &mdlen)) {
587            case SSL_CERT_NONEXISTENT:
588                    imf_ssl_print_cert(cert, md, &mdlen);
589                    if (imf_ssl_new_cert(cert) == SSL_CERT_ACTION_REJECT)
590                            goto abort;
591                    break;
592            case SSL_CERT_MISMATCH:
593                    imf_ssl_print_cert(cert, md, &mdlen);
594                    if (imf_ssl_cert_mismatch() == SSL_CERT_ACTION_ABORT)
595                            goto abort;
596                    break;
597            case SSL_CERT_OK:
598                    if (options & OPTION_DETAILS_VERBOSE)
599                            imf_ssl_print_cert(cert, md, &mdlen);
600            }
601    
602            X509_free(cert);
603            return 0;
604    
605    abort:
606            X509_free(cert);
607            return ERROR_SSL;
608    }
609    
610    
611    /*
612     * Check if the SSL/TLS certificate exists in the certificates file.
613     */
614    int
615    imf_ssl_check_cert(X509 * pcert, unsigned char *pmd, unsigned int *pmdlen)
616    {
617            int r;
618            FILE *fd;
619            X509 *cert;
620            unsigned char md[EVP_MAX_MD_SIZE];
621            unsigned int mdlen;
622            char *cfn;
623    
624            r = SSL_CERT_NONEXISTENT;
625            cert = NULL;
626            cfn = ".imapfilter/certificates";
627    
628            if (!exists_file(cfn))
629                    return SSL_CERT_NONEXISTENT;
630    
631            fd = fopen(cfn, "r");
632            if (fd == NULL)
633                    return ERROR_FILE_OPEN;
634    
635            while ((cert = PEM_read_X509(fd, &cert, NULL, NULL)) != NULL) {
636                    if (X509_subject_name_cmp(cert, pcert) != 0 ||
637                        X509_issuer_name_cmp(cert, pcert) != 0)
638                            continue;
639    
640                    if (!X509_digest(cert, EVP_md5(), md, &mdlen) ||
641                        *pmdlen != mdlen)
642                            continue;
643    
644                    if (memcmp(pmd, md, mdlen) != 0) {
645                            r = SSL_CERT_MISMATCH;
646                            break;
647                    }
648                    r = SSL_CERT_OK;
649                    break;
650            }
651    
652            fclose(fd);
653            X509_free(cert);
654    
655            return r;
656    }
657    
658    
659    /*
660     * Print information about the SSL/TLS certificate.
661     */
662    void
663    imf_ssl_print_cert(X509 * cert, unsigned char *md, unsigned int *mdlen)
664    {
665            unsigned int i;
666            char *c;
667    
668            c = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
669            printf("Server certificate subject: %s\n", c);
670            xfree(c);
671    
672            c = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
673            printf("Server certificate issuer: %s\n", c);
674            xfree(c);
675    
676            printf("Server key fingerprint: ");
677            for (i = 0; i < *mdlen; i++)
678                    printf(i != *mdlen - 1 ? "%02X:" : "%02X\n", md[i]);
679    }
680    
681    
682    /*
683     * Ask the user to reject/accept the SSL/TLS certificate.
684     */
685    int
686    imf_ssl_new_cert(X509 * cert)
687    {
688            FILE *fd;
689            char c, *cfn, buf[LINE_MAX];
690    
691            do {
692                    printf("(R)eject, accept (t)emporarily or "
693                        "accept (p)ermanently? ");
694                    fgets(buf, LINE_MAX, stdin);
695                    c = tolower(*buf);
696            } while (c != 'r' && c != 't' && c != 'p');
697    
698            if (c == 'r')
699                    return SSL_CERT_ACTION_REJECT;
700            else if (c == 't')
701                    return SSL_CERT_ACTION_ACCEPT;
702    
703            cfn = ".imapfilter/certificates";
704    
705            create_file(cfn, S_IRUSR | S_IWUSR);
706    
707            fd = fopen(cfn, "a");
708            if (fd == NULL)
709                    return SSL_CERT_ACTION_REJECT;
710    
711            PEM_write_X509(fd, cert);
712    
713            fclose(fd);
714    
715            return SSL_CERT_ACTION_ACCEPT;
716    }
717    
718    
719    /*
720     * Ask user to proceed, while a fingerprint mismatch in the SSL/TLS
721     * certificate was found.
722     */
723    int
724    imf_ssl_cert_mismatch(void)
725    {
726            char c, buf[LINE_MAX];
727    
728            do {
729                    printf("WARNING: SSL/TLS certificate fingerprint mismatch.\n"
730                        "Proceed with the connection (y/n)? ");
731                    fgets(buf, LINE_MAX, stdin);
732                    c = tolower(*buf);
733            } while (c != 'y' && c != 'n');
734    
735            if (c == 'y')
736                    return SSL_CERT_ACTION_CONTINUE;
737            else
738                    return SSL_CERT_ACTION_ABORT;
739    }
740    
741    #endif                          /* SSL_TLS */

Legend:
Removed from v.1.49  
changed lines
  Added in v.1.50

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26