dma: pass over the code and improve error handling
authorSimon Schubert <corecode@dragonflybsd.org>
Thu, 16 Jul 2009 13:18:29 +0000 (15:18 +0200)
committerSimon Schubert <corecode@dragonflybsd.org>
Thu, 16 Jul 2009 14:13:08 +0000 (16:13 +0200)
libexec/dma/conf.c
libexec/dma/crypto.c
libexec/dma/dma.c
libexec/dma/dma.h
libexec/dma/net.c

index e587c30..2b6cb0a 100644 (file)
@@ -36,6 +36,7 @@
  */
 
 #include <err.h>
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -138,6 +139,7 @@ add_smtp_auth_user(char *userstring, char *password)
        temp = strrchr(userstring, '|');
        if (temp == NULL)
                errx(1, "auth.conf file in wrong format");
+               /* XXX don't use errx */
 
        a->host = strdup(temp+1);
        a->login = strdup(strtok(userstring, "|"));
@@ -160,7 +162,7 @@ parse_authfile(const char *path)
 
        a = fopen(path, "r");
        if (a == NULL)
-               return (1);
+               return (-1);
 
        while (!feof(a)) {
                if (fgets(line, sizeof(line), a) == NULL)
@@ -256,6 +258,10 @@ parse_conf(const char *config_path, struct config *config)
                                config->features |= INSECURE;
                        else if (strcmp(word, "FULLBOUNCE") == 0)
                                config->features |= FULLBOUNCE;
+                       else {
+                               errno = EINVAL;
+                               return (-1);
+                       }
                }
        }
 
index 58094bc..8ef54a1 100644 (file)
@@ -56,16 +56,16 @@ init_cert_file(struct qitem *it, SSL_CTX *ctx, const char *path)
        /* Load certificate into ctx */
        error = SSL_CTX_use_certificate_chain_file(ctx, path);
        if (error < 1) {
-               syslog(LOG_ERR, "%s: SSL: Cannot load certificate: %s",
-                       it->queueid, path);
+               syslog(LOG_ERR, "%s: SSL: Cannot load certificate `%s': %s",
+                       it->queueid, path, ssl_errstr());
                return (-1);
        }
 
        /* Add private key to ctx */
        error = SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM);
        if (error < 1) {
-               syslog(LOG_ERR, "%s: SSL: Cannot load private key: %s",
-                       it->queueid, path);
+               syslog(LOG_ERR, "%s: SSL: Cannot load private key `%s': %s",
+                       it->queueid, path, ssl_errstr());
                return (-1);
        }
 
@@ -76,7 +76,7 @@ init_cert_file(struct qitem *it, SSL_CTX *ctx, const char *path)
        error = SSL_CTX_check_private_key(ctx);
        if (error < 1) {
                syslog(LOG_ERR, "%s: SSL: Cannot check private key: %s",
-                       it->queueid, path);
+                       it->queueid, ssl_errstr());
                return (-1);
        }
 
@@ -94,19 +94,25 @@ smtp_init_crypto(struct qitem *it, int fd, int feature)
        /* XXX clean up on error/close */
        /* Init SSL library */
        SSL_library_init();
+       SSL_load_error_strings();
 
        meth = TLSv1_client_method();
 
        ctx = SSL_CTX_new(meth);
        if (ctx == NULL) {
-               syslog(LOG_WARNING, "%s: remote delivery deferred:"
-                      " SSL init failed: %m", it->queueid);
-               return (2);
+               syslog(LOG_WARNING, "%s: remote delivery deferred: SSL init failed: %s",
+                      it->queueid, ssl_errstr());
+               return (1);
        }
 
        /* User supplied a certificate */
-       if (config->certfile != NULL)
-               init_cert_file(it, ctx, config->certfile);
+       if (config->certfile != NULL) {
+               error = init_cert_file(it, ctx, config->certfile);
+               if (error) {
+                       syslog(LOG_WARNING, "%s: remote delivery deferred", it->queueid);
+                       return (1);
+               }
+       }
 
        /*
         * If the user wants STARTTLS, we have to send EHLO here
@@ -120,11 +126,11 @@ smtp_init_crypto(struct qitem *it, int fd, int feature)
                if (read_remote(fd, 0, NULL) == 2) {
                        send_remote_command(fd, "STARTTLS");
                        if (read_remote(fd, 0, NULL) != 2) {
-                               syslog(LOG_ERR, "%s: remote delivery failed:"
+                               syslog(LOG_ERR, "%s: remote delivery deferred:"
                                  " STARTTLS not available: %s", it->queueid,
                                  neterr);
                                config->features &= ~NOSSL;
-                               return (-1);
+                               return (1);
                        }
                }
                /* End of TLS init phase, enable SSL_write/read */
@@ -133,9 +139,9 @@ smtp_init_crypto(struct qitem *it, int fd, int feature)
 
        config->ssl = SSL_new(ctx);
        if (config->ssl == NULL) {
-               syslog(LOG_NOTICE, "%s: remote delivery deferred:"
-                      " SSL struct creation failed:", it->queueid);
-               return (2);
+               syslog(LOG_NOTICE, "%s: remote delivery deferred: SSL struct creation failed: %s",
+                      it->queueid, ssl_errstr());
+               return (1);
        }
 
        /* Set ssl to work in client mode */
@@ -144,25 +150,24 @@ smtp_init_crypto(struct qitem *it, int fd, int feature)
        /* Set fd for SSL in/output */
        error = SSL_set_fd(config->ssl, fd);
        if (error == 0) {
-               error = SSL_get_error(config->ssl, error);
-               syslog(LOG_NOTICE, "%s: remote delivery deferred:"
-                      " SSL set fd failed (%d): %m", it->queueid, error);
-               return (2);
+               syslog(LOG_NOTICE, "%s: remote delivery deferred: SSL set fd failed: %s",
+                      it->queueid, ssl_errstr());
+               return (1);
        }
 
        /* Open SSL connection */
        error = SSL_connect(config->ssl);
        if (error < 0) {
-               syslog(LOG_ERR, "%s: remote delivery failed:"
-                      " SSL handshake failed fatally: %m", it->queueid);
-               return (-1);
+               syslog(LOG_ERR, "%s: remote delivery deferred: SSL handshake failed fatally: %s",
+                      it->queueid, ssl_errstr());
+               return (1);
        }
 
        /* Get peer certificate */
        cert = SSL_get_peer_certificate(config->ssl);
        if (cert == NULL) {
-               syslog(LOG_WARNING, "%s: remote delivery deferred:"
-                      " Peer did not provide certificate: %m", it->queueid);
+               syslog(LOG_WARNING, "%s: remote delivery deferred: Peer did not provide certificate: %s",
+                      it->queueid, ssl_errstr());
        }
        X509_free(cert);
 
index bd29be9..2296f2e 100644 (file)
@@ -1107,21 +1107,21 @@ skipopts:
 
        config = malloc(sizeof(struct config));
        if (config == NULL)
-               errx(1, "Cannot allocate enough memory");
+               err(1, NULL);
 
        memset(config, 0, sizeof(struct config));
        if (parse_conf(CONF_PATH, config) < 0) {
                free(config);
-               errx(1, "reading config file");
+               err(1, "can not read config file");
        }
 
        if (config->features & VIRTUAL)
                if (parse_virtuser(config->virtualpath) < 0)
-                       errx(1, "error reading virtual user file: %s",
+                       err(1, "can not read virtual user file `%s'",
                                config->virtualpath);
 
        if (parse_authfile(config->authpath) < 0)
-               err(1, "reading SMTP authentication file");
+               err(1, "can not read SMTP authentication file");
 
        if (showq) {
                if (argc != 0)
@@ -1141,30 +1141,30 @@ skipopts:
        }
 
        if (read_aliases() != 0)
-               err(1, "reading aliases");
+               err(1, "can not read aliases file `%s'", config->aliases);
 
        if ((sender = set_from(sender)) == NULL)
-               err(1, "setting from address");
+               err(1, NULL);
 
        for (i = 0; i < argc; i++) {
                if (add_recp(&queue, argv[i], sender, 1) != 0)
-                       errx(1, "invalid recipient `%s'\n", argv[i]);
+                       errx(1, "invalid recipient `%s'", argv[i]);
        }
 
        if (LIST_EMPTY(&queue.queue))
                errx(1, "no recipients");
 
        if (gentempf(&queue) != 0)
-               err(1, "create temp file");
+               err(1, "can not create temp file");
 
        if (preparespool(&queue, sender) != 0)
-               err(1, "creating spools (1)");
+               err(1, "can not create spools (1)");
 
        if (readmail(&queue, sender, nodot) != 0)
-               err(1, "reading mail");
+               err(1, "can not read mail");
 
        if (linkspool(&queue) != 0)
-               err(1, "creating spools (2)");
+               err(1, "can not create spools (2)");
 
        /* From here on the mail is safe. */
 
index dc9a39b..d953220 100644 (file)
@@ -157,6 +157,7 @@ extern int smtp_auth_md5(struct qitem *, int, char *, char *);
 extern int smtp_init_crypto(struct qitem *, int, int);
 
 /* net.c */
+extern char *ssl_errstr(void);
 extern int read_remote(int, int, char *);
 extern ssize_t send_remote_command(int, const char*, ...);
 extern int deliver_remote(struct qitem *, const char **);
index 649e35c..a058f16 100644 (file)
@@ -44,6 +44,7 @@
 #include <arpa/inet.h>
 
 #include <openssl/ssl.h>
+#include <openssl/err.h>
 
 #include <err.h>
 #include <errno.h>
@@ -60,6 +61,18 @@ extern struct authusers authusers;
 static jmp_buf timeout_alarm;
 char neterr[BUF_SIZE];
 
+char *
+ssl_errstr(void)
+{
+       long oerr, nerr;
+
+       oerr = 0;
+       while ((nerr = ERR_get_error()) != 0)
+               oerr = nerr;
+
+       return (ERR_error_string(oerr, NULL));
+}
+
 static void
 sig_alarm(int signo __unused)
 {
@@ -78,8 +91,11 @@ send_remote_command(int fd, const char* fmt, ...)
        va_start(va, fmt);
        s = vsnprintf(cmd, sizeof(cmd) - 2, fmt, va);
        va_end(va);
-       if (s == sizeof(cmd) - 2 || s < 0)
-               errx(1, "Internal error: oversized command string");
+       if (s == sizeof(cmd) - 2 || s < 0) {
+               strcpy(neterr, "Internal error: oversized command string");
+               return (-1);
+       }
+
        /* We *know* there are at least two more bytes available */
        strcat(cmd, "\r\n");
        len = strlen(cmd);
@@ -89,8 +105,10 @@ send_remote_command(int fd, const char* fmt, ...)
                while ((s = SSL_write(config->ssl, (const char*)cmd, len)) <= 0) {
                        s = SSL_get_error(config->ssl, s);
                        if (s != SSL_ERROR_WANT_READ &&
-                           s != SSL_ERROR_WANT_WRITE)
+                           s != SSL_ERROR_WANT_WRITE) {
+                               strncpy(neterr, ssl_errstr(), sizeof(neterr));
                                return (-1);
+                       }
                }
        }
        else {
@@ -117,11 +135,11 @@ read_remote(int fd, int extbufsize, char *extbuf)
        if (signal(SIGALRM, sig_alarm) == SIG_ERR) {
                snprintf(neterr, sizeof(neterr), "SIGALRM error: %s",
                    strerror(errno));
-               return (1);
+               return (-1);
        }
        if (setjmp(timeout_alarm) != 0) {
                snprintf(neterr, sizeof(neterr), "Timeout reached");
-               return (1);
+               return (-1);
        }
        alarm(CON_TIMEOUT);
 
@@ -139,12 +157,15 @@ read_remote(int fd, int extbufsize, char *extbuf)
                        if (((config->features & SECURETRANS) != 0) &&
                            (config->features & NOSSL) == 0) {
                                if ((rlen = SSL_read(config->ssl, buff + len,
-                                   sizeof(buff) - len)) == -1)
-                                       err(1, "read");
+                                   sizeof(buff) - len)) == -1) {
+                                       strncpy(neterr, ssl_errstr(), sizeof(neterr));
+                                       return (-1);
+                               }
                        } else {
-                               if ((rlen = read(fd, buff + len,
-                                   sizeof(buff) - len)) == -1)
-                                       err(1, "read");
+                               if ((rlen = read(fd, buff + len, sizeof(buff) - len)) == -1) {
+                                       strncpy(neterr, strerror(errno), sizeof(neterr));
+                                       return (-1);
+                               }
                        }
                        len += rlen;
                }
@@ -169,10 +190,12 @@ read_remote(int fd, int extbufsize, char *extbuf)
                if (pos == len)
                        return (0);
 
-               if (buff[pos] == ' ')
+               if (buff[pos] == ' ') {
                        done = 1;
-               else if (buff[pos] != '-')
-                       syslog(LOG_ERR, "invalid syntax in reply from server");
+               } else if (buff[pos] != '-') {
+                       strcpy(neterr, "invalid syntax in reply from server");
+                       return (-1);
+               }
 
                /* skip up to \n */
                for (; pos < len && buff[pos - 1] != '\n'; pos++)
@@ -230,11 +253,11 @@ encerr:
 
                send_remote_command(fd, "%s", temp);
                free(temp);
-               if (read_remote(fd, 0, NULL) != 3) {
-                       syslog(LOG_NOTICE, "%s: remote delivery deferred:"
-                                       " AUTH login failed: %s", it->queueid,
-                                       neterr);
-                       return (-1);
+               res = read_remote(fd, 0, NULL);
+               if (res != 3) {
+                       syslog(LOG_NOTICE, "%s: remote delivery %s: AUTH login failed: %s",
+                              it->queueid, res == 5 ? "failed" : "deferred", neterr);
+                       return (res == 5 ? -1 : 1);
                }
 
                len = base64_encode(password, strlen(password), &temp);
@@ -244,16 +267,10 @@ encerr:
                send_remote_command(fd, "%s", temp);
                free(temp);
                res = read_remote(fd, 0, NULL);
-               if (res == 5) {
-                       syslog(LOG_NOTICE, "%s: remote delivery failed:"
-                                       " Authentication failed: %s",
-                                       it->queueid, neterr);
-                       return (-1);
-               } else if (res != 2) {
-                       syslog(LOG_NOTICE, "%s: remote delivery failed:"
-                                       " AUTH password failed: %s",
-                                       it->queueid, neterr);
-                       return (-1);
+               if (res != 2) {
+                       syslog(LOG_NOTICE, "%s: remote delivery %s: Authentication failed: %s",
+                                       it->queueid, res == 5 ? "failed" : "deferred", neterr);
+                       return (res == 5 ? -1 : 1);
                }
        } else {
                syslog(LOG_WARNING, "%s: non-encrypted SMTP login is disabled in config, so skipping it. ",
@@ -374,7 +391,7 @@ deliver_remote(struct qitem *it, const char **errmsg)
        if ((config->features & SECURETRANS) != 0) {
                error = smtp_init_crypto(it, fd, config->features);
                if (error >= 0)
-                       syslog(LOG_INFO, "%s: SSL initialization successful",
+                       syslog(LOG_DEBUG, "%s: SSL initialization successful",
                                it->queueid);
                else
                        goto out;