FreeBSD Bugzilla – Attachment 212184 Details for
Bug 244630
dma(8): Refresh from upstream
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
patch to import dma
2020-MAR-06.patch (text/plain), 41.52 KB, created by
Jan-Piet Mens
on 2020-03-06 12:24:04 UTC
(
hide
)
Description:
patch to import dma
Filename:
MIME Type:
Creator:
Jan-Piet Mens
Created:
2020-03-06 12:24:04 UTC
Size:
41.52 KB
patch
obsolete
>diff -c old/f/freebsd/contrib/dma/Makefile f/freebsd/contrib/dma/Makefile >*** old/f/freebsd/contrib/dma/Makefile Fri Mar 6 10:33:23 2020 >--- f/freebsd/contrib/dma/Makefile Fri Mar 6 10:30:13 2020 >*************** >*** 17,23 **** > CFLAGS?= -O -pipe > LDADD?= -lssl -lcrypto -lresolv > >! CFLAGS+= -Wall -DDMA_VERSION='"${version}"' -DLIBEXEC_PATH='"${LIBEXEC}"' -DCONF_PATH='"${CONFDIR}"' > > INSTALL?= install -p > CHGRP?= chgrp >--- 17,23 ---- > CFLAGS?= -O -pipe > LDADD?= -lssl -lcrypto -lresolv > >! CFLAGS+= -Wall -Wno-format-truncation -DDMA_VERSION='"${version}"' -DLIBEXEC_PATH='"${LIBEXEC}"' -DCONF_PATH='"${CONFDIR}"' > > INSTALL?= install -p > CHGRP?= chgrp >diff -c old/f/freebsd/contrib/dma/VERSION f/freebsd/contrib/dma/VERSION >*** old/f/freebsd/contrib/dma/VERSION Fri Mar 6 10:33:23 2020 >--- f/freebsd/contrib/dma/VERSION Fri Mar 6 10:30:13 2020 >*************** >*** 1 **** >! v0.11 >--- 1 ---- >! v0.13 >diff -c old/f/freebsd/contrib/dma/conf.c f/freebsd/contrib/dma/conf.c >*** old/f/freebsd/contrib/dma/conf.c Fri Mar 6 10:33:23 2020 >--- f/freebsd/contrib/dma/conf.c Fri Mar 6 10:30:13 2020 >*************** >*** 121,127 **** > > au = calloc(1, sizeof(*au)); > if (au == NULL) >! errlog(EX_OSERR, "calloc()"); > > data = strdup(line); > au->login = strsep(&data, "|"); >--- 121,127 ---- > > au = calloc(1, sizeof(*au)); > if (au == NULL) >! errlog(EX_OSERR, NULL); > > data = strdup(line); > au->login = strsep(&data, "|"); >*************** >*** 218,224 **** > config.masquerade_user = user; > } else if (strcmp(word, "STARTTLS") == 0 && data == NULL) > config.features |= STARTTLS; >! else if (strcmp(word, "OPPORTUNISTIC_TLS") == 0 && data == NULL) > config.features |= TLS_OPP; > else if (strcmp(word, "SECURETRANSFER") == 0 && data == NULL) > config.features |= SECURETRANS; >--- 218,239 ---- > config.masquerade_user = user; > } else if (strcmp(word, "STARTTLS") == 0 && data == NULL) > config.features |= STARTTLS; >! else if (strcmp(word, "FINGERPRINT") == 0) { >! if (strlen(data) != SHA256_DIGEST_LENGTH * 2) { >! errlogx(EX_CONFIG, "invalid sha256 fingerprint length"); >! } >! unsigned char *fingerprint = malloc(SHA256_DIGEST_LENGTH); >! if (fingerprint == NULL) { >! errlogx(EX_CONFIG, "fingerprint allocation failed"); >! } >! for (unsigned int i = 0; i < SHA256_DIGEST_LENGTH; i++) { >! if(sscanf(data + 2 * i, "%02hhx", &fingerprint[i]) != 1) { >! errlogx(EX_CONFIG, "failed to read fingerprint"); >! } >! } >! free(data); >! config.fingerprint = fingerprint; >! } else if (strcmp(word, "OPPORTUNISTIC_TLS") == 0 && data == NULL) > config.features |= TLS_OPP; > else if (strcmp(word, "SECURETRANSFER") == 0 && data == NULL) > config.features |= SECURETRANS; >diff -c old/f/freebsd/contrib/dma/crypto.c f/freebsd/contrib/dma/crypto.c >*** old/f/freebsd/contrib/dma/crypto.c Fri Mar 6 10:33:23 2020 >--- f/freebsd/contrib/dma/crypto.c Fri Mar 6 12:14:47 2020 >*************** >*** 40,50 **** >--- 40,53 ---- > #include <openssl/pem.h> > #include <openssl/rand.h> > >+ #include <strings.h> > #include <string.h> > #include <syslog.h> > > #include "dma.h" > >+ int verify_server_fingerprint(const X509 *cert); >+ > static int > init_cert_file(SSL_CTX *ctx, const char *path) > { >*************** >*** 78,85 **** > } > > int >! smtp_init_crypto(int fd, int feature) > { > SSL_CTX *ctx = NULL; > #if (OPENSSL_VERSION_NUMBER >= 0x00909000L) > const SSL_METHOD *meth = NULL; >--- 81,111 ---- > } > > int >! verify_server_fingerprint(const X509 *cert) > { >+ unsigned char fingerprint[EVP_MAX_MD_SIZE] = {0}; >+ unsigned int fingerprint_len = 0; >+ if(!X509_digest(cert, EVP_sha256(), fingerprint, &fingerprint_len)) { >+ syslog(LOG_WARNING, "failed to load fingerprint of server certicate: %s", >+ ssl_errstr()); >+ return (1); >+ } >+ if(fingerprint_len != SHA256_DIGEST_LENGTH) { >+ syslog(LOG_WARNING, "sha256 fingerprint has unexpected length of %d bytes", >+ fingerprint_len); >+ return (1); >+ } >+ if(memcmp(fingerprint, config.fingerprint, SHA256_DIGEST_LENGTH) != 0) { >+ syslog(LOG_WARNING, "fingerprints do not match"); >+ return (1); >+ } >+ syslog(LOG_DEBUG, "successfully verified server certificate fingerprint"); >+ return (0); >+ } >+ >+ int >+ smtp_init_crypto(int fd, int feature, struct smtp_features* features) >+ { > SSL_CTX *ctx = NULL; > #if (OPENSSL_VERSION_NUMBER >= 0x00909000L) > const SSL_METHOD *meth = NULL; >*************** >*** 124,131 **** > /* TLS init phase, disable SSL_write */ > config.features |= NOSSL; > >! send_remote_command(fd, "EHLO %s", hostname()); >! if (read_remote(fd, 0, NULL) == 2) { > send_remote_command(fd, "STARTTLS"); > if (read_remote(fd, 0, NULL) != 2) { > if ((feature & TLS_OPP) == 0) { >--- 150,156 ---- > /* TLS init phase, disable SSL_write */ > config.features |= NOSSL; > >! if (perform_server_greeting(fd, features) == 0) { > send_remote_command(fd, "STARTTLS"); > if (read_remote(fd, 0, NULL) != 2) { > if ((feature & TLS_OPP) == 0) { >*************** >*** 137,142 **** >--- 162,168 ---- > } > } > } >+ > /* End of TLS init phase, enable SSL_write/read */ > config.features &= ~NOSSL; > } >*************** >*** 161,167 **** > > /* Open SSL connection */ > error = SSL_connect(config.ssl); >! if (error < 0) { > syslog(LOG_ERR, "remote delivery deferred: SSL handshake failed fatally: %s", > ssl_errstr()); > return (1); >--- 187,193 ---- > > /* Open SSL connection */ > error = SSL_connect(config.ssl); >! if (error != 1) { > syslog(LOG_ERR, "remote delivery deferred: SSL handshake failed fatally: %s", > ssl_errstr()); > return (1); >*************** >*** 172,177 **** >--- 198,208 ---- > if (cert == NULL) { > syslog(LOG_WARNING, "remote delivery deferred: Peer did not provide certificate: %s", > ssl_errstr()); >+ return (1); >+ } >+ if(config.fingerprint != NULL && verify_server_fingerprint(cert)) { >+ X509_free(cert); >+ return (1); > } > X509_free(cert); > >diff -c old/f/freebsd/contrib/dma/dfcompat.c f/freebsd/contrib/dma/dfcompat.c >*** old/f/freebsd/contrib/dma/dfcompat.c Fri Mar 6 10:33:23 2020 >--- f/freebsd/contrib/dma/dfcompat.c Fri Mar 6 10:30:13 2020 >*************** >*** 16,22 **** > * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > * > * $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ >! * $FreeBSD$ > * $DragonFly: src/lib/libc/string/strlcpy.c,v 1.4 2005/09/18 16:32:34 asmodai Exp $ > */ > >--- 16,22 ---- > * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > * > * $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ >! * $FreeBSD: src/lib/libc/string/strlcpy.c,v 1.10 2008/10/19 10:11:35 delphij Exp $ > * $DragonFly: src/lib/libc/string/strlcpy.c,v 1.4 2005/09/18 16:32:34 asmodai Exp $ > */ > >*************** >*** 85,91 **** > * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > * SUCH DAMAGE. > * >! * $FreeBSD$ > * $DragonFly: src/lib/libc/stdlib/reallocf.c,v 1.2 2003/06/17 04:26:46 dillon Exp $ > */ > #include <stdlib.h> >--- 85,91 ---- > * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > * SUCH DAMAGE. > * >! * $FreeBSD: src/lib/libc/stdlib/reallocf.c,v 1.3 1999/08/28 00:01:37 peter Exp $ > * $DragonFly: src/lib/libc/stdlib/reallocf.c,v 1.2 2003/06/17 04:26:46 dillon Exp $ > */ > #include <stdlib.h> >diff -c old/f/freebsd/contrib/dma/dma-mbox-create.c f/freebsd/contrib/dma/dma-mbox-create.c >*** old/f/freebsd/contrib/dma/dma-mbox-create.c Fri Mar 6 10:33:23 2020 >--- f/freebsd/contrib/dma/dma-mbox-create.c Fri Mar 6 10:30:13 2020 >*************** >*** 38,55 **** > * user-supplied information. Keep the root window as small as possible. > */ > >- #ifdef __FreeBSD__ >- #define USE_CAPSICUM 1 >- #endif >- > #include <sys/param.h> >- #if USE_CAPSICUM >- #include <sys/capsicum.h> >- #endif > #include <sys/stat.h> > >- #include <capsicum_helpers.h> >- #include <err.h> > #include <errno.h> > #include <fcntl.h> > #include <grp.h> >--- 38,46 ---- >*************** >*** 94,102 **** > int > main(int argc, char **argv) > { >- #if USE_CAPSICUM >- cap_rights_t rights; >- #endif > const char *user; > struct passwd *pw; > struct group *gr; >--- 85,90 ---- >*************** >*** 104,113 **** > gid_t mail_gid; > int f, maildirfd; > >! /* >! * Open log fd now for capability sandbox. >! */ >! openlog("dma-mbox-create", LOG_NDELAY, LOG_MAIL); > > errno = 0; > gr = getgrnam(DMA_GROUP); >--- 92,98 ---- > gid_t mail_gid; > int f, maildirfd; > >! openlog("dma-mbox-create", 0, LOG_MAIL); > > errno = 0; > gr = getgrnam(DMA_GROUP); >*************** >*** 148,175 **** > maildirfd = open(_PATH_MAILDIR, O_RDONLY); > if (maildirfd < 0) > logfail(EX_NOINPUT, "cannot open maildir %s", _PATH_MAILDIR); >- >- /* >- * Cache NLS data, for strerror, for err(3), before entering capability >- * mode. >- */ >- caph_cache_catpages(); >- >- /* >- * Cache local time before entering Capsicum capability sandbox. >- */ >- caph_cache_tzdata(); >- >- #if USE_CAPSICUM >- cap_rights_init(&rights, CAP_CREATE, CAP_FCHMOD, CAP_FCHOWN, >- CAP_LOOKUP, CAP_READ); >- if (cap_rights_limit(maildirfd, &rights) < 0 && errno != ENOSYS) >- err(EX_OSERR, "can't limit maildirfd rights"); >- >- /* Enter Capsicum capability sandbox */ >- if (caph_enter() < 0) >- err(EX_OSERR, "cap_enter"); >- #endif > > user_uid = pw->pw_uid; > >--- 133,138 ---- >diff -c old/f/freebsd/contrib/dma/dma.8 f/freebsd/contrib/dma/dma.8 >*** old/f/freebsd/contrib/dma/dma.8 Fri Mar 6 10:33:23 2020 >--- f/freebsd/contrib/dma/dma.8 Fri Mar 6 10:30:13 2020 >*************** >*** 30,36 **** > .\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > .\" SUCH DAMAGE. > .\" >! .Dd May 20, 2017 > .Dt DMA 8 > .Os > .Sh NAME >--- 30,36 ---- > .\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > .\" SUCH DAMAGE. > .\" >! .Dd February 13, 2014 > .Dt DMA 8 > .Os > .Sh NAME >*************** >*** 74,80 **** > .It Fl bp > List all mails currently stored in the mail queue. > .It Fl bq >! Queue the mail, but do not attempt to deliver it. > See also the > .Sq DEFER > config file setting below. >--- 74,80 ---- > .It Fl bp > List all mails currently stored in the mail queue. > .It Fl bq >! Queue the mail, but don't attempt to deliver it. > See also the > .Sq DEFER > config file setting below. >*************** >*** 82,96 **** > .Pp > All other > .Ar mode Ns >! s are ignored. > .It Fl D >! Do not run in the background. > Useful for debugging. > .It Fl f Ar sender > Set sender address (envelope-from) to > .Ar sender . >! This overrides the value of the environment variable >! .Ev EMAIL . > .It Fl i > Ignore dots alone on lines by themselves in incoming messages. > This should be set if you are reading data from a file. >--- 82,99 ---- > .Pp > All other > .Ar mode Ns >! s are are ignored. > .It Fl D >! Don't run in the background. > Useful for debugging. > .It Fl f Ar sender > Set sender address (envelope-from) to > .Ar sender . >! This overrides the value of the >! .Ev EMAIL >! environment variable, but is overridden by the >! .Sq MASQUERADE >! config file setting. > .It Fl i > Ignore dots alone on lines by themselves in incoming messages. > This should be set if you are reading data from a file. >*************** >*** 198,204 **** > .Ql * > can be used to create a catch-all alias, which gets used if no other > matching alias is found. >! Use the catch-all alias only if you do not want any local mail to be > delivered. > .It Ic SPOOLDIR Xo > (string, default=/var/spool/dma) >--- 201,207 ---- > .Ql * > can be used to create a catch-all alias, which gets used if no other > matching alias is found. >! Use the catch-all alias only if you don't want any local mail to be > delivered. > .It Ic SPOOLDIR Xo > (string, default=/var/spool/dma) >*************** >*** 213,219 **** > Path to the > .Sq auth.conf > file. >! .It Ic SECURETRANSFER Xo > (boolean, default=commented) > .Xc > Uncomment if you want TLS/SSL secured transfer. >--- 216,222 ---- > Path to the > .Sq auth.conf > file. >! .It Ic SECURETRANS Xo > (boolean, default=commented) > .Xc > Uncomment if you want TLS/SSL secured transfer. >*************** >*** 222,228 **** > .Xc > Uncomment if you want to use STARTTLS. > Only useful together with >! .Sq SECURETRANSFER . > .It Ic OPPORTUNISTIC_TLS Xo > (boolean, default=commented) > .Xc >--- 225,234 ---- > .Xc > Uncomment if you want to use STARTTLS. > Only useful together with >! .Sq SECURETRANS . >! .It Ic FINGERPRINT Xo >! Pin the server certificate by specifying its SHA256 fingerprint. >! Only makes sense if you use a smarthost. > .It Ic OPPORTUNISTIC_TLS Xo > (boolean, default=commented) > .Xc >*************** >*** 234,240 **** > be encrypted if the remote server supports STARTTLS, but an unencrypted > delivery will still be made if the negotiation fails. > Only useful together with >! .Sq SECURETRANSFER > and > .Sq STARTTLS . > .It Ic CERTFILE Xo >--- 240,246 ---- > be encrypted if the remote server supports STARTTLS, but an unencrypted > delivery will still be made if the negotiation fails. > Only useful together with >! .Sq SECURETRANS > and > .Sq STARTTLS . > .It Ic CERTFILE Xo >*************** >*** 283,289 **** > Masquerade the envelope-from addresses with this address/hostname. > Use this setting if mails are not accepted by destination mail servers > because your sender domain is invalid. >! This setting is overridden by the > .Fl f > flag and the > .Ev EMAIL >--- 289,295 ---- > Masquerade the envelope-from addresses with this address/hostname. > Use this setting if mails are not accepted by destination mail servers > because your sender domain is invalid. >! This setting overrides the > .Fl f > flag and the > .Ev EMAIL >*************** >*** 305,312 **** > setting it to > .Ql percolator > will send all mails as >! .Sm off >! .Ql Va username @percolator . > .Sm on > .It Ic NULLCLIENT Xo > .Xc >--- 311,317 ---- > setting it to > .Ql percolator > will send all mails as >! .Ql Sm off Va username @percolator . > .Sm on > .It Ic NULLCLIENT Xo > .Xc >*************** >*** 329,334 **** >--- 334,341 ---- > Use a plain address, in the form of > .Li user@example.com . > This value will be overridden when the >+ .Sq MASQUERADE >+ config file setting or the > .Fl f > flag is used. > .El >diff -c old/f/freebsd/contrib/dma/dma.c f/freebsd/contrib/dma/dma.c >*** old/f/freebsd/contrib/dma/dma.c Fri Mar 6 10:33:23 2020 >--- f/freebsd/contrib/dma/dma.c Fri Mar 6 10:30:13 2020 >*************** >*** 85,90 **** >--- 85,91 ---- > .mailname = NULL, > .masquerade_host = NULL, > .masquerade_user = NULL, >+ .fingerprint = NULL, > }; > > >*************** >*** 100,114 **** > const char *addr; > char *sender; > >! if (osender) { > addr = osender; > } else if (getenv("EMAIL") != NULL) { > addr = getenv("EMAIL"); > } else { >! if (config.masquerade_user) >! addr = config.masquerade_user; >! else >! addr = username; > } > > if (!strchr(addr, '@')) { >--- 101,114 ---- > const char *addr; > char *sender; > >! if (config.masquerade_user) { >! addr = config.masquerade_user; >! } else if (osender) { > addr = osender; > } else if (getenv("EMAIL") != NULL) { > addr = getenv("EMAIL"); > } else { >! addr = username; > } > > if (!strchr(addr, '@')) { >*************** >*** 331,338 **** > > switch (error) { > case 0: >- syslog(LOG_INFO, "<%s> delivery successful", it->addr); > delqueue(it); > exit(EX_OK); > > case 1: >--- 331,338 ---- > > switch (error) { > case 0: > delqueue(it); >+ syslog(LOG_INFO, "<%s> delivery successful", it->addr); > exit(EX_OK); > > case 1: >*************** >*** 466,472 **** > goto skipopts; > } else if (strcmp(argv[0], "newaliases") == 0) { > logident_base = "dma"; >! setlogident("%s", logident_base); > > if (read_aliases() != 0) > errx(EX_SOFTWARE, "could not parse aliases file `%s'", config.aliases); >--- 466,472 ---- > goto skipopts; > } else if (strcmp(argv[0], "newaliases") == 0) { > logident_base = "dma"; >! setlogident(NULL); > > if (read_aliases() != 0) > errx(EX_SOFTWARE, "could not parse aliases file `%s'", config.aliases); >*************** >*** 565,571 **** > skipopts: > if (logident_base == NULL) > logident_base = "dma"; >! setlogident("%s", logident_base); > > act.sa_handler = sighup_handler; > act.sa_flags = 0; >--- 565,571 ---- > skipopts: > if (logident_base == NULL) > logident_base = "dma"; >! setlogident(NULL); > > act.sa_handler = sighup_handler; > act.sa_flags = 0; >*************** >*** 597,603 **** > errlog(EX_SOFTWARE, "could not parse aliases file `%s'", config.aliases); > > if ((sender = set_from(&queue, sender)) == NULL) >! errlog(EX_SOFTWARE, "set_from()"); > > if (newspoolf(&queue) != 0) > errlog(EX_CANTCREAT, "can not create temp file in `%s'", config.spooldir); >--- 597,603 ---- > errlog(EX_SOFTWARE, "could not parse aliases file `%s'", config.aliases); > > if ((sender = set_from(&queue, sender)) == NULL) >! errlog(EX_SOFTWARE, NULL); > > if (newspoolf(&queue) != 0) > errlog(EX_CANTCREAT, "can not create temp file in `%s'", config.spooldir); >diff -c old/f/freebsd/contrib/dma/dma.conf f/freebsd/contrib/dma/dma.conf >*** old/f/freebsd/contrib/dma/dma.conf Fri Mar 6 10:33:23 2020 >--- f/freebsd/contrib/dma/dma.conf Fri Mar 6 10:30:13 2020 >*************** >*** 18,29 **** > # SMTP authentication > #AUTHPATH /etc/dma/auth.conf > >! # Uncomment if yout want TLS/SSL support > #SECURETRANSFER > > # Uncomment if you want STARTTLS support (only used in combination with > # SECURETRANSFER) > #STARTTLS > > # Uncomment if you have specified STARTTLS above and it should be allowed > # to fail ("opportunistic TLS", use an encrypted connection when available >--- 18,33 ---- > # SMTP authentication > #AUTHPATH /etc/dma/auth.conf > >! # Uncomment if you want TLS/SSL support > #SECURETRANSFER > > # Uncomment if you want STARTTLS support (only used in combination with > # SECURETRANSFER) > #STARTTLS >+ >+ # Pin the server certificate by specifying its SHA256 fingerprint. >+ # Only makes sense if you use a smarthost. >+ #FINGERPRINT 1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF > > # Uncomment if you have specified STARTTLS above and it should be allowed > # to fail ("opportunistic TLS", use an encrypted connection when available >diff -c old/f/freebsd/contrib/dma/dma.h f/freebsd/contrib/dma/dma.h >*** old/f/freebsd/contrib/dma/dma.h Fri Mar 6 10:33:23 2020 >--- f/freebsd/contrib/dma/dma.h Fri Mar 6 10:30:13 2020 >*************** >*** 51,56 **** >--- 51,57 ---- > #define BUF_SIZE 2048 > #define ERRMSG_SIZE 1024 > #define USERNAME_SIZE 50 >+ #define EHLO_RESPONSE_SIZE BUF_SIZE > #define MIN_RETRY 300 /* 5 minutes */ > #define MAX_RETRY (3*60*60) /* retry at least every 3 hours */ > #define MAX_TIMEOUT (5*24*60*60) /* give up after 5 days */ >*************** >*** 137,142 **** >--- 138,144 ---- > const char *mailname; > const char *masquerade_host; > const char *masquerade_user; >+ const unsigned char *fingerprint; > > /* XXX does not belong into config */ > SSL *ssl; >*************** >*** 160,166 **** >--- 162,177 ---- > struct sockaddr_storage sa; > }; > >+ struct smtp_auth_mechanisms { >+ int cram_md5; >+ int login; >+ }; > >+ struct smtp_features { >+ struct smtp_auth_mechanisms auth; >+ int starttls; >+ }; >+ > /* global variables */ > extern struct aliases aliases; > extern struct config config; >*************** >*** 187,193 **** > /* crypto.c */ > void hmac_md5(unsigned char *, int, unsigned char *, int, unsigned char *); > int smtp_auth_md5(int, char *, char *); >! int smtp_init_crypto(int, int); > > /* dns.c */ > int dns_get_mx_list(const char *, int, struct mx_hostentry **, int); >--- 198,204 ---- > /* crypto.c */ > void hmac_md5(unsigned char *, int, unsigned char *, int, unsigned char *); > int smtp_auth_md5(int, char *, char *); >! int smtp_init_crypto(int, int, struct smtp_features*); > > /* dns.c */ > int dns_get_mx_list(const char *, int, struct mx_hostentry **, int); >*************** >*** 196,201 **** >--- 207,213 ---- > char *ssl_errstr(void); > int read_remote(int, int, char *); > ssize_t send_remote_command(int, const char*, ...) __attribute__((__nonnull__(2), __format__ (__printf__, 2, 3))); >+ int perform_server_greeting(int, struct smtp_features*); > int deliver_remote(struct qitem *); > > /* base64.c */ >diff -c old/f/freebsd/contrib/dma/local.c f/freebsd/contrib/dma/local.c >*** old/f/freebsd/contrib/dma/local.c Fri Mar 6 10:33:23 2020 >--- f/freebsd/contrib/dma/local.c Fri Mar 6 10:30:13 2020 >*************** >*** 44,49 **** >--- 44,50 ---- > #include <signal.h> > #include <stdint.h> > #include <stdio.h> >+ #include <strings.h> > #include <string.h> > #include <syslog.h> > #include <unistd.h> >*************** >*** 219,225 **** > /* > * mboxro processing: > * - escape lines that start with "From " with a > sign. >! * - be reversable by escaping lines that contain an arbitrary > * number of > signs, followed by "From ", i.e. />*From / in regexp. > * - strict mbox processing only requires escaping after empty lines, > * yet most MUAs seem to relax this requirement and will treat any >--- 220,226 ---- > /* > * mboxro processing: > * - escape lines that start with "From " with a > sign. >! * - be reversible by escaping lines that contain an arbitrary > * number of > signs, followed by "From ", i.e. />*From / in regexp. > * - strict mbox processing only requires escaping after empty lines, > * yet most MUAs seem to relax this requirement and will treat any >diff -c old/f/freebsd/contrib/dma/mail.c f/freebsd/contrib/dma/mail.c >*** old/f/freebsd/contrib/dma/mail.c Fri Mar 6 10:33:23 2020 >--- f/freebsd/contrib/dma/mail.c Fri Mar 6 10:30:13 2020 >*************** >*** 36,49 **** > #include <errno.h> > #include <inttypes.h> > #include <signal.h> > #include <string.h> > #include <syslog.h> > #include <unistd.h> > > #include "dma.h" > >- #define MAX_LINE_RFC822 1000 >- > void > bounce(struct qitem *it, const char *reason) > { >--- 36,48 ---- > #include <errno.h> > #include <inttypes.h> > #include <signal.h> >+ #include <strings.h> > #include <string.h> > #include <syslog.h> > #include <unistd.h> > > #include "dma.h" > > void > bounce(struct qitem *it, const char *reason) > { >*************** >*** 336,342 **** > ps->pos = 0; > addr = strdup(ps->addr); > if (addr == NULL) >! errlog(EX_SOFTWARE, "strdup"); > > if (add_recp(queue, addr, EXPAND_WILDCARD) != 0) > errlogx(EX_DATAERR, "invalid recipient `%s'", addr); >--- 335,341 ---- > ps->pos = 0; > addr = strdup(ps->addr); > if (addr == NULL) >! errlog(EX_SOFTWARE, NULL); > > if (add_recp(queue, addr, EXPAND_WILDCARD) != 0) > errlogx(EX_DATAERR, "invalid recipient `%s'", addr); >*************** >*** 344,390 **** > goto again; > } > >- static int >- writeline(struct queue *queue, const char *line, ssize_t linelen) >- { >- ssize_t len; >- >- while (linelen > 0) { >- len = linelen; >- if (linelen > MAX_LINE_RFC822) { >- len = MAX_LINE_RFC822 - 10; >- } >- >- if (fwrite(line, len, 1, queue->mailf) != 1) >- return (-1); >- >- if (linelen <= MAX_LINE_RFC822) >- break; >- >- if (fwrite("\n", 1, 1, queue->mailf) != 1) >- return (-1); >- >- line += MAX_LINE_RFC822 - 10; >- linelen = strlen(line); >- } >- return (0); >- } >- > int > readmail(struct queue *queue, int nodot, int recp_from_header) > { > struct parse_state parse_state; >! char *line = NULL; >! ssize_t linelen; >! size_t linecap = 0; >! char newline[MAX_LINE_RFC822]; > size_t error; > int had_headers = 0; > int had_from = 0; > int had_messagid = 0; > int had_date = 0; > int nocopy = 0; >- int ret = -1; > > parse_state.state = NONE; > >--- 343,362 ---- > goto again; > } > > int > readmail(struct queue *queue, int nodot, int recp_from_header) > { > struct parse_state parse_state; >! char line[1000]; /* by RFC2822 */ >! size_t linelen; > size_t error; > int had_headers = 0; > int had_from = 0; > int had_messagid = 0; > int had_date = 0; >+ int had_first_line = 0; >+ int had_last_line = 0; > int nocopy = 0; > > parse_state.state = NONE; > >*************** >*** 403,419 **** > return (-1); > > while (!feof(stdin)) { >! newline[0] = '\0'; >! if ((linelen = getline(&line, &linecap, stdin)) <= 0) > break; >! > if (!had_headers) { >- if (linelen > MAX_LINE_RFC822) { >- /* XXX also split headers */ >- errlogx(EX_DATAERR, "bad mail input format:" >- " from %s (uid %d) (envelope-from %s)", >- username, useruid, queue->sender); >- } > /* > * Unless this is a continuation, switch of > * the Bcc: nocopy flag. >--- 375,407 ---- > return (-1); > > while (!feof(stdin)) { >! if (fgets(line, sizeof(line) - 1, stdin) == NULL) > break; >! if (had_last_line) >! errlogx(EX_DATAERR, "bad mail input format:" >! " from %s (uid %d) (envelope-from %s)", >! username, useruid, queue->sender); >! linelen = strlen(line); >! if (linelen == 0 || line[linelen - 1] != '\n') { >! /* >! * This line did not end with a newline character. >! * If we fix it, it better be the last line of >! * the file. >! */ >! line[linelen] = '\n'; >! line[linelen + 1] = 0; >! had_last_line = 1; >! } >! if (!had_first_line) { >! /* >! * Ignore a leading RFC-976 From_ or >From_ line mistakenly >! * inserted by some programs. >! */ >! if (strprefixcmp(line, "From ") == 0 || strprefixcmp(line, ">From ") == 0) >! continue; >! had_first_line = 1; >! } > if (!had_headers) { > /* > * Unless this is a continuation, switch of > * the Bcc: nocopy flag. >*************** >*** 454,492 **** > while (!had_date || !had_messagid || !had_from) { > if (!had_date) { > had_date = 1; >! snprintf(newline, sizeof(newline), "Date: %s\n", rfc822date()); > } else if (!had_messagid) { > /* XXX msgid, assign earlier and log? */ > had_messagid = 1; >! snprintf(newline, sizeof(newline), "Message-Id: <%"PRIxMAX".%s.%"PRIxMAX"@%s>\n", > (uintmax_t)time(NULL), > queue->id, > (uintmax_t)random(), > hostname()); > } else if (!had_from) { > had_from = 1; >! snprintf(newline, sizeof(newline), "From: <%s>\n", queue->sender); > } >! if (fwrite(newline, strlen(newline), 1, queue->mailf) != 1) >! goto fail; > } >! strlcpy(newline, "\n", sizeof(newline)); > } > if (!nodot && linelen == 2 && line[0] == '.') > break; > if (!nocopy) { >! if (newline[0]) { >! if (fwrite(newline, strlen(newline), 1, queue->mailf) != 1) >! goto fail; >! } else { >! if (writeline(queue, line, linelen) != 0) >! goto fail; >! } > } > } > >! ret = 0; >! fail: >! free(line); >! return (ret); > } >--- 442,472 ---- > while (!had_date || !had_messagid || !had_from) { > if (!had_date) { > had_date = 1; >! snprintf(line, sizeof(line), "Date: %s\n", rfc822date()); > } else if (!had_messagid) { > /* XXX msgid, assign earlier and log? */ > had_messagid = 1; >! snprintf(line, sizeof(line), "Message-Id: <%"PRIxMAX".%s.%"PRIxMAX"@%s>\n", > (uintmax_t)time(NULL), > queue->id, > (uintmax_t)random(), > hostname()); > } else if (!had_from) { > had_from = 1; >! snprintf(line, sizeof(line), "From: <%s>\n", queue->sender); > } >! if (fwrite(line, strlen(line), 1, queue->mailf) != 1) >! return (-1); > } >! strcpy(line, "\n"); > } > if (!nodot && linelen == 2 && line[0] == '.') > break; > if (!nocopy) { >! if (fwrite(line, strlen(line), 1, queue->mailf) != 1) >! return (-1); > } > } > >! return (0); > } >diff -c old/f/freebsd/contrib/dma/net.c f/freebsd/contrib/dma/net.c >*** old/f/freebsd/contrib/dma/net.c Fri Mar 6 10:33:23 2020 >--- f/freebsd/contrib/dma/net.c Fri Mar 6 10:30:13 2020 >*************** >*** 53,58 **** >--- 53,59 ---- > #include <netdb.h> > #include <setjmp.h> > #include <signal.h> >+ #include <strings.h> > #include <string.h> > #include <syslog.h> > #include <unistd.h> >*************** >*** 100,106 **** > s = SSL_get_error(config.ssl, s); > if (s != SSL_ERROR_WANT_READ && > s != SSL_ERROR_WANT_WRITE) { >! strncpy(neterr, ssl_errstr(), sizeof(neterr)); > return (-1); > } > } >--- 101,107 ---- > s = SSL_get_error(config.ssl, s); > if (s != SSL_ERROR_WANT_READ && > s != SSL_ERROR_WANT_WRITE) { >! strlcpy(neterr, ssl_errstr(), sizeof(neterr)); > return (-1); > } > } >*************** >*** 150,161 **** > if (((config.features & SECURETRANS) != 0) && > (config.features & NOSSL) == 0) { > if ((rlen = SSL_read(config.ssl, buff + len, sizeof(buff) - len)) == -1) { >! strncpy(neterr, ssl_errstr(), sizeof(neterr)); > goto error; > } > } else { > if ((rlen = read(fd, buff + len, sizeof(buff) - len)) == -1) { >! strncpy(neterr, strerror(errno), sizeof(neterr)); > goto error; > } > } >--- 151,162 ---- > if (((config.features & SECURETRANS) != 0) && > (config.features & NOSSL) == 0) { > if ((rlen = SSL_read(config.ssl, buff + len, sizeof(buff) - len)) == -1) { >! strlcpy(neterr, ssl_errstr(), sizeof(neterr)); > goto error; > } > } else { > if ((rlen = read(fd, buff + len, sizeof(buff) - len)) == -1) { >! strlcpy(neterr, strerror(errno), sizeof(neterr)); > goto error; > } > } >*************** >*** 248,311 **** > * Handle SMTP authentication > */ > static int >! smtp_login(int fd, char *login, char* password) > { > char *temp; > int len, res = 0; > >! res = smtp_auth_md5(fd, login, password); >! if (res == 0) { >! return (0); >! } else if (res == -2) { >! /* >! * If the return code is -2, then then the login attempt failed, >! * do not try other login mechanisms >! */ >! return (1); >! } >! >! if ((config.features & INSECURE) != 0 || >! (config.features & SECURETRANS) != 0) { >! /* Send AUTH command according to RFC 2554 */ >! send_remote_command(fd, "AUTH LOGIN"); >! if (read_remote(fd, 0, NULL) != 3) { >! syslog(LOG_NOTICE, "remote delivery deferred:" >! " AUTH login not available: %s", >! neterr); > return (1); > } > >! len = base64_encode(login, strlen(login), &temp); >! if (len < 0) { > encerr: >! syslog(LOG_ERR, "can not encode auth reply: %m"); >! return (1); >! } > >! send_remote_command(fd, "%s", temp); >! free(temp); >! res = read_remote(fd, 0, NULL); >! if (res != 3) { >! syslog(LOG_NOTICE, "remote delivery %s: AUTH login failed: %s", >! res == 5 ? "failed" : "deferred", neterr); >! return (res == 5 ? -1 : 1); >! } > >! len = base64_encode(password, strlen(password), &temp); >! if (len < 0) >! goto encerr; > >! send_remote_command(fd, "%s", temp); >! free(temp); >! res = read_remote(fd, 0, NULL); >! if (res != 2) { >! syslog(LOG_NOTICE, "remote delivery %s: Authentication failed: %s", >! res == 5 ? "failed" : "deferred", neterr); >! return (res == 5 ? -1 : 1); > } >- } else { >- syslog(LOG_WARNING, "non-encrypted SMTP login is disabled in config, so skipping it. "); >- return (1); > } > > return (0); >--- 249,318 ---- > * Handle SMTP authentication > */ > static int >! smtp_login(int fd, char *login, char* password, const struct smtp_features* features) > { > char *temp; > int len, res = 0; > >! // CRAM-MD5 >! if (features->auth.cram_md5) { >! res = smtp_auth_md5(fd, login, password); >! if (res == 0) { >! return (0); >! } else if (res == -2) { >! /* >! * If the return code is -2, then then the login attempt failed, >! * do not try other login mechanisms >! */ > return (1); > } >+ } > >! // LOGIN >! if (features->auth.login) { >! if ((config.features & INSECURE) != 0 || >! (config.features & SECURETRANS) != 0) { >! /* Send AUTH command according to RFC 2554 */ >! send_remote_command(fd, "AUTH LOGIN"); >! if (read_remote(fd, 0, NULL) != 3) { >! syslog(LOG_NOTICE, "remote delivery deferred:" >! " AUTH login not available: %s", >! neterr); >! return (1); >! } >! >! len = base64_encode(login, strlen(login), &temp); >! if (len < 0) { > encerr: >! syslog(LOG_ERR, "can not encode auth reply: %m"); >! return (1); >! } > >! send_remote_command(fd, "%s", temp); >! free(temp); >! res = read_remote(fd, 0, NULL); >! if (res != 3) { >! syslog(LOG_NOTICE, "remote delivery %s: AUTH login failed: %s", >! res == 5 ? "failed" : "deferred", neterr); >! return (res == 5 ? -1 : 1); >! } > >! len = base64_encode(password, strlen(password), &temp); >! if (len < 0) >! goto encerr; > >! send_remote_command(fd, "%s", temp); >! free(temp); >! res = read_remote(fd, 0, NULL); >! if (res != 2) { >! syslog(LOG_NOTICE, "remote delivery %s: Authentication failed: %s", >! res == 5 ? "failed" : "deferred", neterr); >! return (res == 5 ? -1 : 1); >! } >! } else { >! syslog(LOG_WARNING, "non-encrypted SMTP login is disabled in config, so skipping it. "); >! return (1); > } > } > > return (0); >*************** >*** 349,359 **** > close(fd); > } > > static int > deliver_to_host(struct qitem *it, struct mx_hostentry *host) > { > struct authuser *a; >! char line[1000]; > size_t linelen; > int fd, error = 0, do_auth = 0, res = 0; > >--- 356,471 ---- > close(fd); > } > >+ static void parse_auth_line(char* line, struct smtp_auth_mechanisms* auth) { >+ // Skip the auth prefix >+ line += strlen("AUTH "); >+ >+ char* method = strtok(line, " "); >+ while (method) { >+ if (strcmp(method, "CRAM-MD5") == 0) >+ auth->cram_md5 = 1; >+ >+ else if (strcmp(method, "LOGIN") == 0) >+ auth->login = 1; >+ >+ method = strtok(NULL, " "); >+ } >+ } >+ >+ int perform_server_greeting(int fd, struct smtp_features* features) { >+ /* >+ Send EHLO >+ XXX allow HELO fallback >+ */ >+ send_remote_command(fd, "EHLO %s", hostname()); >+ >+ char buffer[EHLO_RESPONSE_SIZE]; >+ memset(buffer, 0, sizeof(buffer)); >+ >+ int res = read_remote(fd, sizeof(buffer) - 1, buffer); >+ >+ // Got an unexpected response >+ if (res != 2) >+ return -1; >+ >+ // Reset all features >+ memset(features, 0, sizeof(*features)); >+ >+ // Run through the buffer line by line >+ char linebuffer[EHLO_RESPONSE_SIZE]; >+ char* p = buffer; >+ >+ while (*p) { >+ char* line = linebuffer; >+ while (*p && *p != '\n') { >+ *line++ = *p++; >+ } >+ >+ // p should never point to NULL after the loop >+ // above unless we reached the end of the buffer. >+ // In that case we will raise an error. >+ if (!*p) { >+ return -1; >+ } >+ >+ // Otherwise p points to the newline character which >+ // we will skip. >+ p++; >+ >+ // Terminte the string (and remove the carriage-return character) >+ *--line = '\0'; >+ line = linebuffer; >+ >+ // End main loop for empty lines >+ if (*line == '\0') >+ break; >+ >+ // Process the line >+ // - Must start with 250, followed by dash or space >+ // - We won't check for the correct usage of space and dash because >+ // that is already done in read_remote(). >+ if ((strncmp(line, "250-", 4) != 0) && (strncmp(line, "250 ", 4) != 0)) { >+ syslog(LOG_ERR, "Invalid line: %s\n", line); >+ return -1; >+ } >+ >+ // Skip the prefix >+ line += 4; >+ >+ // Check for STARTTLS >+ if (strcmp(line, "STARTTLS") == 0) >+ features->starttls = 1; >+ >+ // Parse authentication mechanisms >+ else if (strncmp(line, "AUTH ", 5) == 0) >+ parse_auth_line(line, &features->auth); >+ } >+ >+ syslog(LOG_DEBUG, "Server greeting successfully completed"); >+ >+ // STARTTLS >+ if (features->starttls) >+ syslog(LOG_DEBUG, " Server supports STARTTLS"); >+ else >+ syslog(LOG_DEBUG, " Server does not support STARTTLS"); >+ >+ // Authentication >+ if (features->auth.cram_md5) { >+ syslog(LOG_DEBUG, " Server supports CRAM-MD5 authentication"); >+ } >+ if (features->auth.login) { >+ syslog(LOG_DEBUG, " Server supports LOGIN authentication"); >+ } >+ >+ return 0; >+ } >+ > static int > deliver_to_host(struct qitem *it, struct mx_hostentry *host) > { > struct authuser *a; >! struct smtp_features features; >! char line[1000], *addrtmp = NULL, *to_addr; > size_t linelen; > int fd, error = 0, do_auth = 0, res = 0; > >*************** >*** 366,386 **** > if (fd < 0) > return (1); > >! #define READ_REMOTE_CHECK(c, exp) \ >! res = read_remote(fd, 0, NULL); \ >! if (res == 5) { \ >! syslog(LOG_ERR, "remote delivery to %s [%s] failed after %s: %s", \ >! host->host, host->addr, c, neterr); \ >! snprintf(errmsg, sizeof(errmsg), "%s [%s] did not like our %s:\n%s", \ >! host->host, host->addr, c, neterr); \ >! error = -1; \ >! goto out; \ >! } else if (res != exp) { \ >! syslog(LOG_NOTICE, "remote delivery deferred: %s [%s] failed after %s: %s", \ >! host->host, host->addr, c, neterr); \ >! error = 1; \ >! goto out; \ >! } > > /* Check first reply from remote host */ > if ((config.features & SECURETRANS) == 0 || >--- 478,500 ---- > if (fd < 0) > return (1); > >! #define READ_REMOTE_CHECK(c, exp) \ >! do { \ >! res = read_remote(fd, 0, NULL); \ >! if (res == 5) { \ >! syslog(LOG_ERR, "remote delivery to %s [%s] failed after %s: %s", \ >! host->host, host->addr, c, neterr); \ >! snprintf(errmsg, sizeof(errmsg), "%s [%s] did not like our %s:\n%s", \ >! host->host, host->addr, c, neterr); \ >! error = -1; \ >! goto out; \ >! } else if (res != exp) { \ >! syslog(LOG_NOTICE, "remote delivery deferred: %s [%s] failed after %s: %s", \ >! host->host, host->addr, c, neterr); \ >! error = 1; \ >! goto out; \ >! } \ >! } while (0) > > /* Check first reply from remote host */ > if ((config.features & SECURETRANS) == 0 || >*************** >*** 392,398 **** > } > > if ((config.features & SECURETRANS) != 0) { >! error = smtp_init_crypto(fd, config.features); > if (error == 0) > syslog(LOG_DEBUG, "SSL initialization successful"); > else >--- 506,512 ---- > } > > if ((config.features & SECURETRANS) != 0) { >! error = smtp_init_crypto(fd, config.features, &features); > if (error == 0) > syslog(LOG_DEBUG, "SSL initialization successful"); > else >*************** >*** 402,411 **** > READ_REMOTE_CHECK("connect", 2); > } > >! /* XXX allow HELO fallback */ >! /* XXX record ESMTP keywords */ >! send_remote_command(fd, "EHLO %s", hostname()); >! READ_REMOTE_CHECK("EHLO", 2); > > /* > * Use SMTP authentication if the user defined an entry for the remote >--- 516,527 ---- > READ_REMOTE_CHECK("connect", 2); > } > >! // Say EHLO >! if (perform_server_greeting(fd, &features) != 0) { >! syslog(LOG_ERR, "Could not perform server greeting at %s [%s]: %s", >! host->host, host->addr, neterr); >! return -1; >! } > > /* > * Use SMTP authentication if the user defined an entry for the remote >*************** >*** 424,430 **** > * encryption. > */ > syslog(LOG_INFO, "using SMTP authentication for user %s", a->login); >! error = smtp_login(fd, a->login, a->password); > if (error < 0) { > syslog(LOG_ERR, "remote delivery failed:" > " SMTP login failed: %m"); >--- 540,546 ---- > * encryption. > */ > syslog(LOG_INFO, "using SMTP authentication for user %s", a->login); >! error = smtp_login(fd, a->login, a->password, &features); > if (error < 0) { > syslog(LOG_ERR, "remote delivery failed:" > " SMTP login failed: %m"); >*************** >*** 443,450 **** > READ_REMOTE_CHECK("MAIL FROM", 2); > > /* XXX send ESMTP ORCPT */ >! send_remote_command(fd, "RCPT TO:<%s>", it->addr); >! READ_REMOTE_CHECK("RCPT TO", 2); > > send_remote_command(fd, "DATA"); > READ_REMOTE_CHECK("DATA", 3); >--- 559,575 ---- > READ_REMOTE_CHECK("MAIL FROM", 2); > > /* XXX send ESMTP ORCPT */ >! if ((addrtmp = strdup(it->addr)) == NULL) { >! syslog(LOG_CRIT, "remote delivery deferred: unable to allocate memory"); >! error = 1; >! goto out; >! } >! to_addr = strtok(addrtmp, ","); >! while (to_addr != NULL) { >! send_remote_command(fd, "RCPT TO:<%s>", to_addr); >! READ_REMOTE_CHECK("RCPT TO", 2); >! to_addr = strtok(NULL, ","); >! } > > send_remote_command(fd, "DATA"); > READ_REMOTE_CHECK("DATA", 3); >*************** >*** 486,491 **** >--- 611,617 ---- > syslog(LOG_INFO, "remote delivery succeeded but QUIT failed: %s", neterr); > out: > >+ free(addrtmp); > close_connection(fd); > return (error); > } >diff -c old/f/freebsd/contrib/dma/spool.c f/freebsd/contrib/dma/spool.c >*** old/f/freebsd/contrib/dma/spool.c Fri Mar 6 10:33:23 2020 >--- f/freebsd/contrib/dma/spool.c Fri Mar 6 10:30:13 2020 >*************** >*** 37,42 **** >--- 37,43 ---- > > #include <sys/file.h> > #include <sys/stat.h> >+ #include <sys/time.h> > > #include <ctype.h> > #include <dirent.h> >*************** >*** 45,50 **** >--- 46,52 ---- > #include <fcntl.h> > #include <inttypes.h> > #include <unistd.h> >+ #include <strings.h> > #include <string.h> > #include <syslog.h> > >*************** >*** 417,423 **** > return (0); > > /* Did the flush file get touched within the last period seconds? */ >! if (st.st_mtim.tv_sec + (int)period >= now.tv_sec) > return (1); > else > return (0); >--- 419,425 ---- > return (0); > > /* Did the flush file get touched within the last period seconds? */ >! if (st.st_mtim.tv_sec + period >= now.tv_sec) > return (1); > else > return (0); >Common subdirectories: old/f/freebsd/contrib/dma/test and f/freebsd/contrib/dma/test >diff -c old/f/freebsd/contrib/dma/util.c f/freebsd/contrib/dma/util.c >*** old/f/freebsd/contrib/dma/util.c Fri Mar 6 10:33:23 2020 >--- f/freebsd/contrib/dma/util.c Fri Mar 6 10:30:13 2020 >*************** >*** 44,49 **** >--- 44,50 ---- > #include <setjmp.h> > #include <signal.h> > #include <stdio.h> >+ #include <strings.h> > #include <string.h> > #include <syslog.h> > #include <unistd.h>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 244630
: 212184