commit efc5c202ae4f6c024cb91a6e4d52cbc03df1f621 from: Omar Polo via: Thomas Adam date: Sat Mar 30 17:20:05 2024 UTC got-notify-email: split dial() out of send_email() This allows to reduce the set of pledge(2) promises needed at runtime down to only "stdio" which will also help sandboxing -portable. ok stsp commit - a806a88322a11af5b725b9ea9269cc6b9b3a482c commit + efc5c202ae4f6c024cb91a6e4d52cbc03df1f621 blob - 9833a0857ba9b87efa1af070690a51b09c9f68b6 blob + 94e40c2386175a1061eac29534189952427564cb --- gotd/libexec/got-notify-email/got-notify-email.c +++ gotd/libexec/got-notify-email/got-notify-email.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -43,6 +44,48 @@ usage(void) exit(1); } +static int +dial(const char *host, const char *port) +{ + struct addrinfo hints, *res, *res0; + const char *cause = NULL; + int s, error, save_errno; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + error = getaddrinfo(host, port, &hints, &res0); + if (error) + errx(1, "failed to resolve %s:%s: %s", host, port, + gai_strerror(error)); + + s = -1; + for (res = res0; res; res = res->ai_next) { + s = socket(res->ai_family, res->ai_socktype, + res->ai_protocol); + if (s == -1) { + cause = "socket"; + continue; + } + + if (connect(s, res->ai_addr, res->ai_addrlen) == -1) { + cause = "connect"; + save_errno = errno; + close(s); + errno = save_errno; + s = -1; + continue; + } + + break; + } + + freeaddrinfo(res0); + if (s == -1) + err(1, "%s", cause); + return s; +} + static char * set_default_fromaddr(void) { @@ -157,38 +200,21 @@ get_datestr(time_t *time, char *datebuf) } static void -send_email(const char *myfromaddr, const char *fromaddr, +send_email(int s, const char *myfromaddr, const char *fromaddr, const char *recipient, const char *replytoaddr, - const char *subject, const char *hostname, const char *port) + const char *subject) { const struct got_error *error; char *line = NULL; size_t linesize = 0; ssize_t linelen; - struct addrinfo hints, *res = NULL; - int s = -1, ret; time_t now; char datebuf[26]; char *datestr; now = time(NULL); datestr = get_datestr(&now, datebuf); - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - - ret = getaddrinfo(hostname, port, &hints, &res); - if (ret) - errx(1, "getaddrinfo: %s", gai_strerror(ret)); - - s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - if (s == -1) - err(1, "socket"); - if (connect(s, res->ai_addr, res->ai_addrlen) == -1) - err(1, "connect %s:%s", hostname, port); - if (read_smtp_code(s, "220")) errx(1, "unexpected SMTP greeting received"); if (skip_to_crlf(s)) @@ -267,8 +293,6 @@ send_email(const char *myfromaddr, const char *fromadd close(s); free(line); - if (res) - freeaddrinfo(res); } int @@ -281,7 +305,7 @@ main(int argc, char *argv[]) const char *port = "25"; const char *errstr; char *timeoutstr; - int ch; + int ch, s; while ((ch = getopt(argc, argv, "f:r:s:h:p:")) != -1) { switch (ch) { @@ -337,9 +361,16 @@ main(int argc, char *argv[]) if (fromaddr == NULL) fromaddr = default_fromaddr; - send_email(default_fromaddr, fromaddr, recipient, replytoaddr, - subject, hostname, port); + s = dial(hostname, port); +#ifndef PROFILE + if (pledge("stdio", NULL) == -1) + err(1, "pledge"); +#endif + + send_email(s, default_fromaddr, fromaddr, recipient, replytoaddr, + subject); + free(default_fromaddr); return 0; }