317 #include <sys/socket.h>
319 #include <netinet/in.h>
320 #include <arpa/inet.h>
322 #ifdef STRCASECMP_IN_STRINGS_H
350 #define STR(x) vstring_str(x)
377 #include <openssl/engine.h>
385 static int conn_tmout = 30;
386 static int smtp_tmout = 30;
388 #define HOST_FLAG_DNS (1<<0)
389 #define HOST_FLAG_NATIVE (1<<1)
391 #define MISC_FLAG_PREF_IPV6 (1<<0)
392 #define MISC_FLAG_PREF_IPV4 (1<<1)
394 static const NAME_MASK lookup_masks[] = {
400 static const NAME_CODE addr_pref_map[] = {
457 TLS_APPL_STATE *tls_ctx;
458 TLS_SESS_STATE *tls_context;
470 #define HNAME(addr) (addr->qname)
486 VSTREAM *stream = state->stream;
497 while (line && *line) {
498 char *nextline = strchr(line,
'\n');
502 if (verbose && !state->nochat)
526 if (rdata.
buf == 0) {
536 #define BUF ((char *) vstring_str(buf))
540 for (cp =
BUF; *cp != 0; cp++)
544 if (verbose && !state->
nochat)
548 rdata.
code = (cp -
BUF == 3 ? atoi(BUF) : 0);
549 if ((more = (*cp ==
'-')) != 0)
565 static char *exception_text(
int except)
569 return (
"lost connection");
573 msg_panic(
"exception_text: unknown exception %d", except);
579 static int greeting(
STATE *state)
590 msg_info(
"%s while reading server greeting", exception_text(except));
597 if (((resp = response(state, 1))->code / 100) != 2) {
610 volatile char *ehlo = state->
smtp ?
"EHLO" :
"LHLO";
615 verbose = (state->
pass == 1 && state->
nochat == 0);
624 msg_info(
"%s while sending %s", exception_text(except), ehlo);
629 resp = response(state, verbose);
630 if (resp->
code / 100 != 2) {
639 static void print_stack(
STATE *state, x509_stack_t *sk,
int trustout)
643 for (i = 0; i < sk_X509_num(sk); i++) {
644 X509 *cert = sk_X509_value(sk, i);
645 char buf[CCERT_BUFSIZ];
649 if ((xn = X509_get_subject_name(cert)) != 0) {
650 X509_NAME_oneline(xn, buf,
sizeof buf);
651 BIO_printf(state->tls_bio,
"%2d subject: %s\n", i, buf);
653 if ((xn = X509_get_issuer_name(cert)) != 0) {
654 X509_NAME_oneline(xn, buf,
sizeof buf);
655 BIO_printf(state->tls_bio,
" issuer: %s\n", buf);
657 digest = tls_cert_fprint(cert, state->mdalg);
658 BIO_printf(state->tls_bio,
" cert digest=%s\n", digest);
661 digest = tls_pkey_fprint(cert, state->mdalg);
662 BIO_printf(state->tls_bio,
" pkey digest=%s\n", digest);
666 PEM_write_bio_X509_AUX(state->tls_bio, cert);
668 PEM_write_bio_X509(state->tls_bio, cert);
672 static void print_trust_info(
STATE *state)
674 x509_stack_t *sk = SSL_get_peer_cert_chain(state->tls_context->con);
677 BIO_printf(state->tls_bio,
"\n---\nCertificate chain\n");
678 print_stack(state, sk, 0);
680 #ifdef dane_verify_debug
682 if ((sk = state->tls_context->untrusted) != 0) {
683 BIO_printf(state->tls_bio,
"\n---\nUntrusted chain\n");
684 print_stack(state, sk, 0);
687 if ((sk = state->tls_context->trusted) != 0) {
688 BIO_printf(state->tls_bio,
"\n---\nTrusted chain\n");
689 print_stack(state, sk, 1);
696 static int starttls(
STATE *state)
702 TLS_CLIENT_START_PROPS tls_props;
708 msg_fatal(
"%s while sending STARTTLS", exception_text(except));
711 command(state, state->
pass == 1,
"STARTTLS");
713 resp = response(state, state->
pass == 1);
714 if (resp->
code / 100 != 2) {
725 #define ADD_EXCLUDE(vstr, str) \
728 vstring_sprintf_append((vstr), "%s%s", \
729 VSTRING_LEN(vstr) ? " " : "", (str)); \
742 ADD_EXCLUDE(cipher_exclusions,
"aNULL");
744 ADD_EXCLUDE(cipher_exclusions,
"eNULL");
747 TLS_CLIENT_START(&tls_props,
748 ctx = state->tls_ctx,
750 timeout = smtp_tmout,
751 tls_level = state->
level,
756 helo = state->
helo ? state->
helo :
"",
757 protocols = state->protocols,
758 cipher_grade = state->grade,
761 matchargv = state->match,
762 mdalg = state->mdalg,
763 dane = state->ddane ? state->ddane : state->dane);
769 if (state->tls_context == 0) {
779 if (state->
pass == 1) {
781 if (!TLS_CERT_IS_PRESENT(state->tls_context))
783 else if (state->print_trust)
784 print_trust_info(state);
785 state->
log_mask &= ~(TLS_LOG_CERTMATCH | TLS_LOG_PEERCERT |
786 TLS_LOG_VERBOSE | TLS_LOG_UNTRUSTED);
787 state->
log_mask |= TLS_LOG_CACHE | TLS_LOG_SUMMARY;
788 tls_update_app_logmask(state->tls_ctx, state->
log_mask);
797 static int doproto(
STATE *state)
808 if (greeting(state) != 0)
810 if ((resp = ehlo(state)) == 0)
814 for (n = 0; (words =
mystrtok(&lines,
"\n")) != 0; ++n) {
815 if ((word =
mystrtok(&words,
" \t=")) != 0) {
834 msg_warn(
"%s while sending QUIT command", exception_text(except));
837 command(state, 1,
"QUIT");
838 (void) response(state, 1);
844 static VSTREAM *connect_sock(
int sock,
struct sockaddr *sa,
int salen,
845 const char *name,
const char *addr,
STATE *state)
852 if (conn_tmout > 0) {
863 dsb_simple(why,
"4.4.1",
"connect to %s[%s]:%d: %m",
864 name, addr, ntohs(state->
port));
866 dsb_simple(why,
"4.4.1",
"connect to %s[%s]: %m", name, addr);
875 name, addr, ntohs(state->
port)));
880 addr, ntohs(state->
port)));
885 if (sa->sa_family == AF_INET
887 || sa->sa_family == AF_INET6
897 static VSTREAM *connect_unix(
STATE *state,
const char *path)
899 static const char *myname =
"connect_unix";
901 struct sockaddr_un sock_un;
902 int len = strlen(path);
914 if (len >= (
int)
sizeof(sock_un.sun_path)) {
915 dsb_simple(why,
"4.3.5",
"unix-domain name too long: %s", path);
922 memset((
void *) &sock_un, 0,
sizeof(sock_un));
923 sock_un.sun_family = AF_UNIX;
925 sock_un.sun_len = len + 1;
927 memcpy(sock_un.sun_path, path, len + 1);
932 if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
939 msg_info(
"%s: trying: %s...", myname, path);
941 return (connect_sock(sock, (
struct sockaddr *) &sock_un,
sizeof(sock_un),
949 static const char *myname =
"connect_addr";
951 struct sockaddr_storage ss;
952 struct sockaddr *sa = (
struct sockaddr *) &ss;
963 msg_warn(
"%s: skip address type %s: %m",
965 dsb_simple(why,
"4.4.0",
"network address conversion failed: %m");
972 if ((sock = socket(sa->sa_family, SOCK_STREAM, 0)) < 0)
983 msg_info(
"%s: trying: %s[%s] port %d...",
986 return (connect_sock(sock, sa, salen,
HNAME(addr), hostaddr.
buf, state));
989 #define HAS_DSN(why) (STR((why)->status)[0] != 0)
990 #define HAS_SOFT_DSN(why) (STR((why)->status)[0] == '4')
991 #define HAS_HARD_DSN(why) (STR((why)->status)[0] == '5')
992 #define HAS_LOOP_DSN(why) \
993 (HAS_DSN(why) && strcmp(STR((why)->status) + 1, ".4.6") == 0)
995 #define SET_SOFT_DSN(why) (STR((why)->status)[0] = '4')
996 #define SET_HARD_DSN(why) (STR((why)->status)[0] = '5')
1001 int res_opt,
unsigned pref)
1003 static const char *myname =
"addr_one";
1008 struct addrinfo *res0;
1009 struct addrinfo *res;
1014 msg_info(
"%s: host %s", myname, host);
1020 && strchr((
char *) proto_info->
sa_family_list, res0->ai_family) != 0) {
1021 if ((addr =
dns_sa_to_rr(host, pref, res0->ai_addr)) == 0)
1022 msg_fatal(
"host %s: conversion error for address family %d: %m",
1023 host, ((
struct sockaddr *) (res0->ai_addr))->sa_family);
1040 for (rr = addr; rr; rr = rr->
next)
1066 #define RETRY_AI_ERROR(e) \
1067 ((e) == EAI_AGAIN || (e) == EAI_MEMORY || (e) == EAI_SYSTEM)
1069 #define DSN_NOHOST(e) \
1070 ((e) == EAI_AGAIN || (e) == EAI_NODATA || (e) == EAI_NONAME)
1072 #define DSN_NOHOST(e) \
1073 ((e) == EAI_AGAIN || (e) == EAI_NONAME)
1081 "unable to look up host %s: %s",
1084 for (found = 0, res = res0; res != 0; res = res->ai_next) {
1085 if (strchr((
char *) proto_info->
sa_family_list, res->ai_family) == 0) {
1086 msg_info(
"skipping address family %d for host %s",
1087 res->ai_family, host);
1091 if ((addr =
dns_sa_to_rr(host, pref, res->ai_addr)) == 0)
1092 msg_fatal(
"host %s: conversion error for address family %d: %m",
1093 host, ((
struct sockaddr *) (res0->ai_addr))->sa_family);
1099 "%s: host not found", host);
1115 static const char *myname =
"mx_addr_list";
1127 for (rr = mx_names; rr; rr = rr->
next) {
1128 if (rr->
type != T_MX)
1130 addr_list = addr_one(state, addr_list, (
char *) rr->
data, res_opt,
1138 static DNS_RR *domain_addr(
STATE *state,
char *domain)
1147 #if (RES_USE_DNSSEC != 0) && (RES_USE_EDNS0 != 0)
1156 msg_info(
"%s asciified to %s", domain, aname);
1177 addr_list = mx_addr_list(state, mx_names);
1180 if (addr_list == 0) {
1181 msg_warn(
"no MX host for %s has a valid address record", domain);
1184 #define COMPARE_ADDR(flags) \
1185 ((flags & MISC_FLAG_PREF_IPV6) ? dns_rr_compare_pref_ipv6 : \
1186 (flags & MISC_FLAG_PREF_IPV4) ? dns_rr_compare_pref_ipv4 : \
1187 dns_rr_compare_pref_any)
1188 if (addr_list && addr_list->
next) {
1194 addr_list = host_addr(state, domain);
1203 static DNS_RR *host_addr(
STATE *state,
const char *host)
1212 #if (RES_USE_DNSSEC != 0) && (RES_USE_EDNS0 != 0)
1221 msg_info(
"%s asciified to %s", host, ahost);
1227 addr_list = addr_one(state, (
DNS_RR *) 0, ahost, res_opt,
PREF0);
1228 if (addr_list && addr_list->
next) {
1238 static int dane_host_level(
STATE *state,
DNS_RR *addr)
1240 int level = state->
level;
1246 if (state->
log_mask & (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE))
1247 tls_dane_verbose(1);
1249 tls_dane_verbose(0);
1253 tls_dane_free(state->ddane);
1259 state->ddane = tls_dane_resolve(state->
port,
"tcp", addr,
1261 if (!state->ddane) {
1263 "TLSA lookup error for %s:%u",
1266 }
else if (tls_dane_notfound(state->ddane)
1267 || tls_dane_unusable(state->ddane)) {
1269 msg_info(
"no %sTLSA records found, "
1270 "resorting to \"secure\"",
1271 tls_dane_unusable(state->ddane) ?
1274 }
else if (!TLS_DANE_HASTA(state->ddane)
1275 && !TLS_DANE_HASEE(state->ddane)) {
1276 msg_panic(
"DANE activated with no TLSA records to match");
1279 msg_info(
"TLSA RRs found, MX RRset insecure: just encrypt");
1280 tls_dane_free(state->ddane);
1287 state->ddane->base_domain,
ARGV_END);
1290 msg_info(
"MX RRset insecure: log verified as trusted");
1302 msg_info(
"MX RRset is insecure: try to encrypt");
1315 static char *parse_destination(
char *destination,
char *def_service,
1316 char **hostp,
unsigned *portp)
1321 char *protocol =
"tcp";
1326 msg_info(
"parse_destination: %s %s", destination, def_service);
1332 if ((err =
host_port(buf, hostp, (
char *) 0, &service, def_service)) != 0)
1333 msg_fatal(
"%s in server description: %s", err, destination);
1339 if ((port = atoi(service)) >= 65536 || port == 0)
1340 msg_fatal(
"bad network port in destination: %s", destination);
1341 *portp = htons(port);
1343 if ((sp = getservbyname(service, protocol)) != 0)
1344 *portp = sp->s_port;
1345 else if (strcmp(service,
"smtp") == 0)
1348 msg_fatal(
"unknown service: %s/%s", service, protocol);
1355 static void connect_remote(
STATE *state,
char *dest)
1362 if (state->
addr == 0) {
1363 buf = parse_destination(dest, state->
smtp ?
"smtp" :
"24",
1364 &domain, &state->
port);
1367 if (state->
smtp == 0 || *dest ==
'[')
1368 state->
addr = host_addr(state, domain);
1370 state->
addr = domain_addr(state, domain);
1373 if (state->
addr == 0) {
1374 msg_info(
"Destination address lookup failed: %s",
1379 for (addr = state->
addr; addr; addr = addr->
next) {
1380 int level = dane_host_level(state, addr);
1383 || (state->
stream = connect_addr(state, addr)) == 0) {
1384 msg_info(
"Failed to establish session to %s via %s: %s",
1389 state->
level = level;
1402 static int connect_dest(
STATE *state)
1404 char *dest = state->
dest;
1410 if (state->
smtp == 0) {
1411 if (strncmp(dest,
"unix:", 5) == 0) {
1412 connect_unix(state, dest + 5);
1414 msg_info(
"Failed to establish session to %s: %s",
1418 if (strncmp(dest,
"inet:", 5) == 0)
1421 connect_remote(state, dest);
1423 return (state->
stream == 0);
1426 static void disconnect_dest(
STATE *state)
1429 if (state->tls_context)
1430 tls_client_stop(state->tls_ctx, state->
stream,
1431 smtp_tmout, 0, state->tls_context);
1432 state->tls_context = 0;
1434 tls_dane_free(state->ddane);
1471 static int finger(
STATE *state)
1483 if (!(err = connect_dest(state))) {
1486 err = doproto(state);
1488 disconnect_dest(state);
1500 if (cache_enabled && cache_count == 0) {
1501 msg_info(
"Server declined session caching. Done reconnecting.");
1503 }
else if (cache_hits > 0 && (state->
log_mask & TLS_LOG_CACHE) != 0) {
1504 msg_info(
"Found a previously used server. Done reconnecting.");
1507 msg_info(
"Maximum reconnect count reached.");
1516 #if defined(USE_TLS) && OPENSSL_VERSION_NUMBER < 0x10100000L
1520 static void ssl_cleanup(
void)
1522 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
1523 ERR_remove_thread_state(0);
1525 ERR_remove_state(0);
1528 CONF_modules_unload(1);
1531 CRYPTO_cleanup_all_ex_data();
1539 static int run(
STATE *state)
1543 if (finger(state) != 0)
1557 static void cleanup(
STATE *state)
1560 if (state->tls_ctx != 0)
1561 tls_free_app_context(state->tls_ctx);
1563 (void) BIO_free(state->tls_bio);
1579 tls_dane_free(state->dane);
1586 myfree(state->protocols);
1596 static void usage(
void)
1599 fprintf(stderr,
"usage: %s %s \\\n\t%s \\\n\t%s \\\n\t%s"
1601 "[-acCfSvw] [-t conn_tmout] [-T cmd_tmout] [-L logopts]",
1602 "[-h host_lookup] [-l level] [-d mdalg] [-g grade] [-p protocols]",
1603 "[-A tafile] [-F CAfile.pem] [-P CApath/] "
1604 "[-k certfile [-K keyfile]] [-m count] [-r delay]",
1607 fprintf(stderr,
"usage: %s [-acStTv] [-h host_lookup] [-o name=value] destination\n",
1615 static void tls_init(
STATE *state)
1618 TLS_CLIENT_INIT_PROPS props;
1624 TLS_CLIENT_INIT(&props,
1625 log_param =
"-L option",
1628 cache_type =
"memory",
1629 cert_file = state->certfile,
1630 key_file = state->keyfile,
1635 CAfile = state->CAfile,
1636 CApath = state->CApath,
1637 mdalg = state->mdalg);
1643 static void override(
const char *nameval)
1657 static void parse_options(
STATE *state,
int argc,
char *argv[])
1667 state->protocols =
mystrdup(
"!SSLv2");
1673 #define OPTS "a:ch:o:St:T:v"
1675 #define TLSOPTS "A:Cd:fF:g:k:K:l:L:m:M:p:P:r:w"
1713 conn_tmout = atoi(optarg);
1716 smtp_tmout = atoi(optarg);
1726 state->print_trust = 1;
1745 state->certfile =
mystrdup(optarg);
1746 if (!*state->keyfile) {
1754 if (!*state->certfile) {
1756 state->certfile =
mystrdup(optarg);
1779 msg_fatal(
"bad '-M' option value: %s", optarg);
1783 myfree(state->protocols);
1784 state->protocols =
mystrdup(optarg);
1828 switch (state->
level) {
1831 msg_fatal(
"SSL wrapper mode requires that TLS not be disabled");
1845 msg_warn(
"DANE TLS support is not available, resorting to \"secure\"");
1849 if (state->print_trust)
1850 state->tls_bio = BIO_new_fp(stdout, BIO_NOCLOSE);
1857 static void parse_match(
STATE *state,
int argc,
char *argv[])
1861 switch (state->
level) {
1866 if (state->match->argc == 0)
1873 if (state->match->argc == 0)
1877 state->dane = tls_dane_alloc();
1879 tls_dane_add_ee_digests((TLS_DANE *) state->dane,
1880 state->mdalg, *argv++,
"");
1893 static void parse_tas(
STATE *state)
1901 switch (state->
level) {
1906 state->dane = tls_dane_alloc();
1908 if (!tls_dane_load_trustfile((TLS_DANE *) state->dane, *file))
1912 msg_fatal(
"Failed to load trust anchor file: %s", *file);
1922 char *loopenv = getenv(
"VALGRINDLOOP");
1923 int loop = loopenv ? atoi(loopenv) : 1;
1927 signal(SIGPIPE, SIG_IGN);
1939 parse_options(&state, argc, argv);
1956 parse_match(&state, --argc, ++argv);
1969 #if defined(USE_TLS) && OPENSSL_VERSION_NUMBER < 0x10100000L
const char * dns_strtype(unsigned)
#define MISC_FLAG_PREF_IPV4
#define TLS_LEV_DANE_ONLY
void freeaddrinfo(struct addrinfo *ai)
DSN_BUF * dsb_create(void)
char * mystrdup(const char *str)
char * var_import_environ
#define TLS_LEV_HALF_DANE
void set_mail_conf_str(const char *, const char *)
ARGV * argv_free(ARGV *argvp)
#define VAR_IMPORT_ENVIRON
NORETURN msg_panic(const char *fmt,...)
void chroot_uid(const char *root_dir, const char *user_name)
int sane_connect(int sock, struct sockaddr *sa, SOCKADDR_SIZE len)
#define inet_proto_info()
#define TLS_DANE_BASED(l)
#define hostname_to_sockaddr(host, serv, sock, res)
#define DEF_SMTP_TLS_SCERT_VD
#define CA_VSTRING_CTL_MAXLEN(val)
void dsb_reset(DSN_BUF *dsb)
void dsb_free(DSN_BUF *dsb)
#define SOCKADDR_TO_HOSTADDR(sa, salen, host, port, sock)
void mail_conf_flush(void)
void argv_add(ARGV *argvp,...)
int smtp_get(VSTRING *vp, VSTREAM *stream, ssize_t bound, int flags)
int alldig(const char *string)
#define vstream_setjmp(stream)
char * mystrtok(char **src, const char *sep)
ARGV * argv_alloc(ssize_t len)
const char * split_nameval(char *buf, char **name, char **value)
void set_inet_windowsize(int sock, int windowsize)
void vstring_ctl(VSTRING *vp,...)
int hostaddr_to_sockaddr(const char *hostaddr, const char *service, int socktype, struct addrinfo **res)
void mail_conf_suck(void)
#define dns_lookup_v(name, rflags, list, fqdn, why, lflags, ltype)
#define VSTRING_TERMINATE(vp)
#define VSTRING_ADDCH(vp, ch)
char buf[MAI_HOSTADDR_STRSIZE]
VSTRING * vstring_vsprintf(VSTRING *vp, const char *format, va_list ap)
#define DEF_SMTP_TLS_EXCL_CIPH
ARGV * mail_parm_split(const char *name, const char *value)
int timed_connect(int sock, struct sockaddr *sa, int len, int timeout)
int dns_rr_to_sa(DNS_RR *, unsigned, struct sockaddr *, SOCKADDR_SIZE *)
#define VSTREAM_PURGE_READ
int vstream_fclose(VSTREAM *stream)
#define MISC_FLAG_PREF_IPV6
#define DEF_SMTP_TLS_MAND_EXCL
#define VSTRING_RESET(vp)
void tlsmgrmem_disable(void)
#define VSTREAM_PURGE_BOTH
void msg_warn(const char *fmt,...)
DNS_RR * dns_rr_shuffle(DNS_RR *)
void smtp_stream_setup(VSTREAM *stream, int maxtime, int enable_deadline)
VSTRING * vstring_alloc(ssize_t len)
DNS_RR * dns_rr_copy(DNS_RR *)
#define NAME_CODE_FLAG_NONE
unsigned char * sa_family_list
#define name_mask(tag, table, str)
DNS_RR * dns_sa_to_rr(const char *, unsigned, struct sockaddr *)
VSTRING * vstring_sprintf(VSTRING *vp, const char *format,...)
void smtp_printf(VSTREAM *stream, const char *fmt,...)
#define INET_PROTO_NAME_IPV6
DSN_BUF * dsb_simple(DSN_BUF *dsb, const char *status, const char *format,...)
int name_code(const NAME_CODE *table, int flags, const char *name)
#define RETRY_AI_ERROR(e)
NORETURN msg_fatal(const char *fmt,...)
int dns_rr_compare_pref_any(DNS_RR *, DNS_RR *)
DNS_RR * dns_rr_append(DNS_RR *, DNS_RR *)
void update_env(char **preserve_list)
int tls_level_lookup(const char *)
int main(int argc, char *argv[])
#define GETOPT(argc, argv, str)
int vstream_tweak_tcp(VSTREAM *)
DSN_BUF * dsb_status(DSN_BUF *dsb, const char *status)
int strcasecmp(const char *s1, const char *s2)
int non_blocking(int, int)
const char * host_port(char *buf, char **host, char *def_host, char **port, char *def_service)
const char * midna_domain_to_ascii(const char *name)
VSTRING * vstring_free(VSTRING *vp)
unsigned int dnssec_valid
ARGV * argv_split_append(ARGV *, const char *, const char *)
#define INET_PROTO_NAME_ANY
#define TLS_MUST_MATCH(l)
void msg_vstream_init(const char *name, VSTREAM *vp)
DNS_RR * dns_rr_sort(DNS_RR *, int(*)(DNS_RR *, DNS_RR *))
void tlsmgrmem_status(int *, int *, int *)
#define DNS_REQ_FLAG_NONE
#define SMTP_GET_FLAG_SKIP
int vstream_fpurge(VSTREAM *stream, int direction)
void mail_conf_update(const char *key, const char *value)
void dns_rr_free(DNS_RR *)
#define INET_PROTO_NAME_IPV4
#define HAS_SOFT_DSN(why)
#define dns_lookup(name, type, rflags, list, fqdn, why)
#define COMPARE_ADDR(flags)
void tlsmgrmem_flush(void)
VSTRING * vstring_strcat(VSTRING *vp, const char *src)
char * vstring_export(VSTRING *vp)
unsigned int * dns_atype_list
VSTREAM * vstream_fdopen(int fd, int flags)
void msg_info(const char *fmt,...)