On Fri, May 14, 2021 at 03:38:12PM +0200, Eric Faurot wrote:
> Hello.
>
> This diff allows to specify protcols and ciphers in smtp(1).
> I thought it was cleaner to added a generic -O option flag for this.
I'm ok with this.
Two small points to consider:
Perhaps using -T as in nc(1) might make sense? (On the other hand,
ftp(1) uses -S which is already taken but not documented in smtp(1)).
Is it worth using getsubopt(3)?
>
> Eric.
>
> Index: smtp.1
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/smtp.1,v
> retrieving revision 1.9
> diff -u -p -r1.9 smtp.1
> --- smtp.1 13 Feb 2021 08:07:48 -0000 1.9
> +++ smtp.1 14 May 2021 13:25:59 -0000
> @@ -26,6 +26,7 @@
> .Op Fl a Ar authfile
> .Op Fl F Ar from
> .Op Fl H Ar helo
> +.Op Fl O Ar option
> .Op Fl s Ar server
> .Op Ar recipient ...
> .Sh DESCRIPTION
> @@ -63,6 +64,31 @@ Display usage.
> Do not actually execute a transaction,
> just try to establish an SMTP session and quit.
> When this option is given, no message is read from the standard input.
> +.It Fl O Ar option
> +Set additional configuration options that don't have a specific flag.
> +The
> +.Ar option
> +string has the form
> +.Sm off
> +.Ar name No = Ar value
> +.Sm on
> +where
> +.Ar name
> +is one of the following:
> +.Bl -tag -width "protocols"
> +.It protocols
> +Specify the protocols to use for tls connections.
> +Refer to
> +.Xr tls_config_parse_protocols 3
> +for
> +.Ar value .
> +.It ciphers
> +Specify the allowed ciphers for tls connections.
> +Refer to
> +.Xr tls_config_set_ciphers 3
> +for
> +.Ar value .
> +.El
> .It Fl s Ar server
> Specify the server to connect to and connection parameters.
> The format is
> Index: smtpc.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/smtpc.c,v
> retrieving revision 1.15
> diff -u -p -r1.15 smtpc.c
> --- smtpc.c 10 Apr 2021 10:19:19 -0000 1.15
> +++ smtpc.c 14 May 2021 13:31:45 -0000
> @@ -48,22 +48,45 @@ static struct smtp_mail mail;
> static const char *servname = NULL;
> static struct tls_config *tls_config;
>
> +static const char *protocols = NULL;
> +static const char *ciphers = NULL;
> +
> static void
> usage(void)
> {
> extern char *__progname;
>
> fprintf(stderr, "usage: %s [-Chnv] [-a authfile] [-F from] [-H helo] "
> + "[-O option] "
> "[-s server] [recipient ...]\n", __progname);
> exit(1);
> }
>
> +static void
> +parse_option(char *opt)
> +{
> + char *v;
> +
> + v = strchr(opt, '=');
> + if (v == NULL)
> + fatalx("invalid option string \"%s\"", opt);
> + *v++ = '\0';
> +
> + if (!strcmp(opt, "ciphers"))
> + ciphers = v;
> + else if (!strcmp(opt, "protocols"))
> + protocols = v;
> + else
> + fatalx("unknown option \"%s\"", opt);
> +}
> +
> int
> main(int argc, char **argv)
> {
> char hostname[256];
> FILE *authfile;
> int ch, i;
> + uint32_t protos;
> char *server = "localhost";
> char *authstr = NULL;
> size_t alloc = 0;
> @@ -91,7 +114,7 @@ main(int argc, char **argv)
> memset(&mail, 0, sizeof(mail));
> mail.from = pw->pw_name;
>
> - while ((ch = getopt(argc, argv, "CF:H:S:a:hns:v")) != -1) {
> + while ((ch = getopt(argc, argv, "CF:H:O:S:a:hns:v")) != -1) {
> switch (ch) {
> case 'C':
> params.tls_verify = 0;
> @@ -102,6 +125,9 @@ main(int argc, char **argv)
> case 'H':
> params.helo = optarg;
> break;
> + case 'O':
> + parse_option(optarg);
> + break;
> case 'S':
> servname = optarg;
> break;
> @@ -159,6 +185,17 @@ main(int argc, char **argv)
> tls_config = tls_config_new();
> if (tls_config == NULL)
> fatal("tls_config_new");
> +
> + if (protocols) {
> + if (tls_config_parse_protocols(&protos, protocols) == -1)
> + fatalx("failed to parse protocol '%s'", protocols);
> + if (tls_config_set_protocols(tls_config, protos) == -1)
> + fatalx("tls_config_set_protocols: %s",
> + tls_config_error(tls_config));
> + }
> + if (ciphers && tls_config_set_ciphers(tls_config, ciphers) == -1)
> + fatalx("tls_config_set_ciphers: %s",
> + tls_config_error(tls_config));
> if (tls_config_set_ca_file(tls_config, tls_default_ca_cert_file()) ==
> -1)
> fatal("tls_set_ca_file");
> if (!params.tls_verify) {
>