X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/1ff43c7e4735e2dd95003570f96b10d7e0f88b7d..efa36b8cb2aae4cf57dde5118888ae2d4f78e2cd:/uip/post.c?ds=sidebyside diff --git a/uip/post.c b/uip/post.c index aadc6271..0fee356b 100644 --- a/uip/post.c +++ b/uip/post.c @@ -1,4 +1,3 @@ - /* * post.c -- enter messages into the mail transport system * @@ -37,6 +36,12 @@ # define TLSminc(a) 0 #endif /* TLS_SUPPORT */ +#ifndef OAUTH_SUPPORT +# define OAUTHminc(a) (a) +#else /* OAUTH_SUPPORT */ +# define OAUTHminc(a) 0 +#endif /* OAUTH_SUPPORT */ + #define FCCS 10 /* max number of fccs allowed */ /* In the following array of structures, the numeric second field of the @@ -76,21 +81,29 @@ X("server host", 6, SERVSW) /* specify alternate SMTP server */ \ X("snoop", -5, SNOOPSW) /* snoop the SMTP transaction */ \ X("partno", -6, PARTSW) \ - X("queued", -6, QUEUESW) \ - X("sasl", SASLminc(-4), SASLSW) \ - X("nosasl", SASLminc(-6), NOSASLSW) \ - X("saslmaxssf", SASLminc(-10), SASLMXSSFSW) \ - X("saslmech", SASLminc(-5), SASLMECHSW) \ + X("sasl", SASLminc(4), SASLSW) \ + X("nosasl", SASLminc(6), NOSASLSW) \ + X("saslmaxssf", SASLminc(10), SASLMXSSFSW) \ + X("saslmech", SASLminc(5), SASLMECHSW) \ X("user", SASLminc(-4), USERSW) \ - X("port server port name/number", 4, PORTSW) \ + X("port server submission port name/number", 4, PORTSW) \ X("tls", TLSminc(-3), TLSSW) \ X("initialtls", TLSminc(-10), INITTLSSW) \ X("notls", TLSminc(-5), NTLSSW) \ X("fileproc", -4, FILEPROCSW) \ X("mhlproc", -3, MHLPROCSW) \ + X("sendmail program", 0, MTSSM) \ X("mts smtp|sendmail/smtp|sendmail/pipe", 2, MTSSW) \ X("credentials legacy|file:filename", 0, CREDENTIALSSW) \ X("messageid localname|random", 2, MESSAGEIDSW) \ + X("authservice auth-service-name", OAUTHminc(-11), AUTHSERVICESW) \ + X("oauthcredfile credential-file", OAUTHminc(-7), OAUTHCREDFILESW) \ + X("oauthclientid client-id", OAUTHminc(-12), OAUTHCLIDSW) \ + X("oauthclientsecret client-secret", OAUTHminc(-12), OAUTHCLSECSW) \ + X("oauthauthendpoint authentication-endpoint", OAUTHminc(-6), OAUTHAUTHENDSW) \ + X("oauthredirect redirect-uri", OAUTHminc(-6), OAUTHREDIRSW) \ + X("oauthtokenendpoint token-endpoint", OAUTHminc(-6), OAUTHTOKENDSW) \ + X("oauthscope scope", OAUTHminc(-6), OAUTHSCOPESW) \ #define X(sw, minchars, id) id, DEFINE_SWITCH_ENUM(POST); @@ -101,6 +114,26 @@ DEFINE_SWITCH_ARRAY(POST, switches); #undef X +/* + * Mapping between command-line switches and profile entries, communicated + * from 'send'. We use a service name of 'post' internally. + */ + +static struct oauth_profile { + const char *profname; + int switchnum; + const char *value; +} oauthswitches[] = { + { "oauth-%s-credential-file", OAUTHCREDFILESW, NULL }, + { "oauth-%s-client_id", OAUTHCLIDSW, NULL }, + { "oauth-%s-client_secret", OAUTHCLSECSW, NULL }, + { "oauth-%s-auth_endpoint", OAUTHAUTHENDSW, NULL }, + { "oauth-%s-redirect_uri", OAUTHREDIRSW, NULL }, + { "oauth-%s-token_endpoint", OAUTHTOKENDSW, NULL }, + { "oauth-%s-scope", OAUTHSCOPESW, NULL }, + { NULL, 0, NULL } +}; + struct headers { char *value; unsigned int flags; @@ -201,8 +234,8 @@ static int sasl=0; /* Use SASL auth for SMTP */ static int saslssf=-1; /* Our maximum SSF for SASL */ static char *saslmech=NULL; /* Force use of particular SASL mech */ static char *user=NULL; /* Authenticate as this user */ -static char *port="smtp"; /* Name of server port for SMTP */ -static int tls=0; /* Use TLS for encryption */ +static char *port="submission"; /* Name of server port for SMTP submission */ +static int tls=-1; /* Use TLS for encryption */ static int fromcount=0; /* Count of addresses on From: header */ static int seensender=0; /* Have we seen a Sender: header? */ @@ -223,7 +256,6 @@ static char from[BUFSIZ]; /* my network address */ static char sender[BUFSIZ]; /* my Sender: header */ static char efrom[BUFSIZ]; /* my Envelope-From: header */ static char fullfrom[BUFSIZ]; /* full contents of From header */ -static char signature[BUFSIZ]; /* my signature */ static char *filter = NULL; /* the filter for BCC'ing */ static char *subject = NULL; /* the subject field for BCC'ing */ static char *fccfold[FCCS]; /* foldernames for FCC'ing */ @@ -239,12 +271,9 @@ static int snoop = 0; static char *clientsw = NULL; static char *serversw = NULL; -extern struct smtp sm_reply; - static char prefix[] = "----- =_aaaaaaaaaa"; static char *partno = NULL; -static int queued = 0; /* * static prototypes @@ -261,14 +290,14 @@ static void anno (void); static int annoaux (struct mailname *); static void insert_fcc (struct headers *, char *); static void make_bcc_file (int); -static void verify_all_addresses (int, char *); +static void verify_all_addresses (int, char *, int, char *); static void chkadr (void); static void sigon (void); static void sigoff (void); static void p_refile (char *); static void fcc (char *, char *); static void die (char *, char *, ...); -static void post (char *, int, int, char *); +static void post (char *, int, int, char *, int, char *); static void do_text (char *file, int fd); static void do_an_address (struct mailname *, int); static void do_addresses (int, int); @@ -278,28 +307,21 @@ static int find_prefix (void); int main (int argc, char **argv) { - int state, compnum, dashstuff = 0; + int state, compnum, dashstuff = 0, swnum, oauth_flag = 0; char *cp, *msg = NULL, **argp, **arguments, *envelope; - char buf[BUFSIZ], name[NAMESZ]; + char buf[BUFSIZ], name[NAMESZ], *auth_svc = NULL; FILE *in, *out; m_getfld_state_t gstate = 0; -#ifdef LOCALE - setlocale(LC_ALL, ""); -#endif - invo_name = r1bindex (argv[0], '/'); - - /* foil search of user profile/context */ - if (context_foil (NULL) == -1) - done (1); + if (nmh_init(argv[0], 0 /* use context_foil() */)) { return 1; } - mts_init (invo_name); + mts_init (); arguments = getarguments (invo_name, argc, argv, 0); argp = arguments; while ((cp = *argp++)) { if (*cp == '-') { - switch (smatch (++cp, switches)) { + switch ((swnum = smatch (++cp, switches))) { case AMBIGSW: ambigsw (cp, switches); done (1); @@ -432,10 +454,6 @@ main (int argc, char **argv) adios (NULL, "missing argument to %s", argp[-2]); continue; - case QUEUESW: - queued++; - continue; - case SASLSW: sasl++; continue; @@ -454,7 +472,41 @@ main (int argc, char **argv) if (!(saslmech = *argp++) || *saslmech == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; - + + case AUTHSERVICESW: + if (!(auth_svc = *argp++) || *auth_svc == '-') + adios (NULL, "missing argument to %s", argp[-2]); + oauth_flag++; + continue; + + case OAUTHCREDFILESW: + case OAUTHCLIDSW: + case OAUTHCLSECSW: + case OAUTHAUTHENDSW: + case OAUTHREDIRSW: + case OAUTHTOKENDSW: + case OAUTHSCOPESW: + { + int i; + + if (!(cp = *argp++) || *cp == '-') + adios (NULL, "missing argument to %s", argp[-2]); + + for (i = 0; oauthswitches[i].profname != NULL; i++) { + if (oauthswitches[i].switchnum == swnum) { + oauthswitches[i].value = cp; + break; + } + } + + if (oauthswitches[i].profname == NULL) + adios (NULL, "internal error: cannot map switch %s " + "to profile entry", argp[-2]); + + oauth_flag++; + continue; + } + case USERSW: if (!(user = *argp++) || *user == '-') adios (NULL, "missing argument to %s", argp[-2]); @@ -489,6 +541,12 @@ main (int argc, char **argv) mhlproc = cp; continue; + case MTSSM: + if (!(cp = *argp++) || *cp == '-') + adios (NULL, "missing argument to %s", argp[-2]); + sendmail = cp; + continue; + case MTSSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); @@ -536,15 +594,12 @@ main (int argc, char **argv) if ((out = fopen ("/dev/null", "w")) == NULL) adios ("/dev/null", "unable to open"); } else { - char *cp = m_mktemp(m_maildir(invo_name), NULL, &out); - if (cp == NULL) { - cp = m_mktemp2(NULL, invo_name, NULL, &out); - if (cp == NULL) { - adios ("post", "unable to create temporary file"); - } - } + char *cp = m_mktemp2(NULL, invo_name, NULL, &out); + if (cp == NULL) { + adios(NULL, "unable to create temporary file in %s", + get_temp_dir()); + } strncpy(tmpfil, cp, sizeof(tmpfil)); - chmod (tmpfil, 0600); } } @@ -621,10 +676,50 @@ main (int argc, char **argv) envelope = from; } + if (tls == -1) { +#ifdef TLS_SUPPORT + /* + * The user didn't specify any of the tls switches. Try to + * help them by implying -initialtls if they're using port 465 + * (smtps, until IANA revoked that registration in 1998). + */ + tls = ! strcmp (port, "465") || ! strcasecmp (port, "smtps") + ? 2 + : 0; +#else /* ! TLS_SUPPORT */ + tls = 0; +#endif /* ! TLS_SUPPORT */ + } + + /* + * If we were given any oauth flags, store the appropriate profile + * entries and make sure an authservice was given (we have to do this + * here because we aren't guaranteed the authservice will be given on + * the command line before the other OAuth flags are given). + */ + + if (oauth_flag) { + int i; + char sbuf[128]; + + if (auth_svc == NULL) { + adios(NULL, "No authentication service given with -authservice"); + } + + for (i = 0; oauthswitches[i].profname != NULL; i++) { + if (oauthswitches[i].value != NULL) { + snprintf(sbuf, sizeof(sbuf), + oauthswitches[i].profname, auth_svc); + sbuf[sizeof(sbuf) - 1] = '\0'; + add_profile_entry(sbuf, oauthswitches[i].value); + } + } + } + /* If we are doing a "whom" check */ if (whomsw) { /* This won't work with MTS_SENDMAIL_PIPE. */ - verify_all_addresses (1, envelope); + verify_all_addresses (1, envelope, oauth_flag, auth_svc); done (0); } @@ -636,22 +731,26 @@ main (int argc, char **argv) verify_all_addresses with MTS_SENDMAIL_PIPE, but that might require running sendmail as root. Note that spost didn't verify addresses. */ - verify_all_addresses (verbose, envelope); + verify_all_addresses (verbose, envelope, oauth_flag, auth_svc); } - post (tmpfil, 0, verbose, envelope); + post (tmpfil, 0, verbose, envelope, oauth_flag, auth_svc); } - post (bccfil, 1, verbose, envelope); - unlink (bccfil); + post (bccfil, 1, verbose, envelope, oauth_flag, auth_svc); + (void) m_unlink (bccfil); } else { - post (tmpfil, 0, isatty (1), envelope); + post (tmpfil, 0, isatty (1), envelope, oauth_flag, auth_svc); } p_refile (tmpfil); - unlink (tmpfil); + (void) m_unlink (tmpfil); + + if (verbose) { + if (partno) + printf ("Partial Message #%s Processed\n", partno); + else + printf ("Message Processed\n"); + } - if (verbose) - printf (partno ? "Partial Message #%s Processed\n" : "Message Processed\n", - partno); done (0); return 1; } @@ -666,7 +765,7 @@ putfmt (char *name, char *str, FILE *out) { int count, grp, i, keep; char *cp, *pp, *qp; - char namep[BUFSIZ]; + char namep[BUFSIZ], error[BUFSIZ]; struct mailname *mp = NULL, *np = NULL; struct headers *hdr; @@ -714,7 +813,7 @@ putfmt (char *name, char *str, FILE *out) if (hdr->flags & HFCC) { if ((cp = strrchr(str, '\n'))) *cp = 0; - for (cp = pp = str; (cp = strchr(pp, ',')); pp = cp) { + for (pp = str; (cp = strchr(pp, ',')); pp = cp) { *cp++ = 0; insert_fcc (hdr, pp); } @@ -729,18 +828,20 @@ putfmt (char *name, char *str, FILE *out) tmpaddrs.m_next = NULL; for (count = 0; (cp = getname (str)); count++) - if ((mp = getm (cp, NULL, 0, AD_HOST, NULL))) { + if ((mp = getm (cp, NULL, 0, error, sizeof(error)))) { if (tmpaddrs.m_next) np->m_next = mp; else tmpaddrs.m_next = mp; np = mp; } - else + else { + admonish(cp, "%s", error); if (hdr->flags & HTRY) badadr++; else badmsg++; + } if (count < 1) { if (hdr->flags & HNIL) @@ -781,7 +882,8 @@ putfmt (char *name, char *str, FILE *out) if (np->m_gname) putgrp (namep, np->m_gname, out, hdr->flags); while ((cp = getname (pp))) { - if (!(mp = getm (cp, NULL, 0, AD_HOST, NULL))) { + if (!(mp = getm (cp, NULL, 0, error, sizeof(error)))) { + admonish(cp, "%s", error); badadr++; continue; } @@ -930,9 +1032,6 @@ putfmt (char *name, char *str, FILE *out) static void start_headers (void) { - char *cp, sigbuf[BUFSIZ]; - struct mailname *mp; - time (&tclock); /* @@ -943,21 +1042,6 @@ start_headers (void) efrom[0] = '\0'; sender[0] = '\0'; fullfrom[0] = '\0'; - - if ((cp = getfullname ()) && *cp) { - strncpy (sigbuf, cp, sizeof(sigbuf)); - snprintf (signature, sizeof(signature), "%s <%s>", - sigbuf, getlocaladdr()); - if ((cp = getname (signature)) == NULL) - adios (NULL, "getname () failed -- you lose extraordinarily big"); - if ((mp = getm (cp, NULL, 0, AD_HOST, NULL)) == NULL) - adios (NULL, "bad signature '%s'", sigbuf); - mnfree (mp); - while (getname ("")) - continue; - } else { - strncpy (signature, getlocaladdr(), sizeof(signature)); - } } @@ -1294,8 +1378,9 @@ make_bcc_file (int dashstuff) FILE *out; char *tfile = NULL, *program; - tfile = m_mktemp2(NULL, "bccs", NULL, &out); - if (tfile == NULL) adios("bcc", "unable to create temporary file"); + if ((tfile = m_mktemp2(NULL, "bccs", NULL, &out)) == NULL) { + adios(NULL, "unable to create temporary file in %s", get_temp_dir()); + } strncpy (bccfil, tfile, sizeof(bccfil)); fprintf (out, "From: %s\n", fullfrom); @@ -1500,7 +1585,8 @@ do_addresses (int bccque, int talk) */ static void -post (char *file, int bccque, int talk, char *envelope) +post (char *file, int bccque, int talk, char *envelope, int oauth_flag, + char *auth_svc) { int fd; int retval, i; @@ -1549,9 +1635,10 @@ post (char *file, int bccque, int talk, char *envelope) } } else { if (rp_isbad (retval = sm_init (clientsw, serversw, port, watch, - verbose, snoop, queued, sasl, - saslssf, saslmech, user, tls)) || - rp_isbad (retval = sm_winit (envelope))) + verbose, snoop, sasl, saslssf, + saslmech, user, + oauth_flag ? auth_svc : NULL, tls)) + || rp_isbad (retval = sm_winit (envelope))) die (NULL, "problem initializing server; %s", rp_string (retval)); do_addresses (bccque, talk && verbose); @@ -1580,7 +1667,7 @@ post (char *file, int bccque, int talk, char *envelope) /* Address Verification */ static void -verify_all_addresses (int talk, char *envelope) +verify_all_addresses (int talk, char *envelope, int oauth_flag, char *auth_svc) { int retval; struct mailname *lp; @@ -1589,8 +1676,9 @@ verify_all_addresses (int talk, char *envelope) if (!whomsw || checksw) if (rp_isbad (retval = sm_init (clientsw, serversw, port, watch, - verbose, snoop, queued, sasl, - saslssf, saslmech, user, tls)) + verbose, snoop, sasl, saslssf, + saslmech, user, + oauth_flag ? auth_svc : NULL, tls)) || rp_isbad (retval = sm_winit (envelope))) die (NULL, "problem initializing server; %s", rp_string (retval)); @@ -1726,9 +1814,9 @@ sigser (int i) { NMH_UNUSED (i); - unlink (tmpfil); + (void) m_unlink (tmpfil); if (msgflags & MINV) - unlink (bccfil); + (void) m_unlink (bccfil); if (!whomsw || checksw) sm_end (NOTOK); @@ -1850,9 +1938,9 @@ die (char *what, char *fmt, ...) { va_list ap; - unlink (tmpfil); + (void) m_unlink (tmpfil); if (msgflags & MINV) - unlink (bccfil); + (void) m_unlink (bccfil); if (!whomsw || checksw) sm_end (NOTOK);