send-email: provide whitelist of SMTP AUTH mechanisms

When sending an e-mail, the client and server must agree on an
authentication mechanism. Some servers (due to misconfiguration
or a bug) deny valid credentials for certain mechanisms. In this
patch, a new option --smtp-auth and configuration entry smtpAuth
are introduced. If smtp_auth is defined, it works as a whitelist
of allowed mechanisms for authentication selected from the ones
supported by the installed SASL perl library.

Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
Helped-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Jan Viktorin 2015-08-12 01:39:44 +02:00 committed by Junio C Hamano
parent a17c56c056
commit 0f2e68b54c
2 changed files with 38 additions and 1 deletions

View File

@ -171,6 +171,19 @@ Sending
to determine your FQDN automatically. Default is the value of
'sendemail.smtpDomain'.
--smtp-auth=<mechanisms>::
Whitespace-separated list of allowed SMTP-AUTH mechanisms. This setting
forces using only the listed mechanisms. Example:
+
------
$ git send-email --smtp-auth="PLAIN LOGIN GSSAPI" ...
------
+
If at least one of the specified mechanisms matches the ones advertised by the
SMTP server and if it is supported by the utilized SASL library, the mechanism
is used for authentication. If neither 'sendemail.smtpAuth' nor '--smtp-auth'
is specified, all mechanisms supported by the SASL library can be used.
--smtp-pass[=<password>]::
Password for SMTP-AUTH. The argument is optional: If no
argument is specified, then the empty string is used as

View File

@ -75,6 +75,8 @@ git send-email [options] <file | directory | rev-list options >
Pass an empty string to disable certificate
verification.
--smtp-domain <str> * The domain name sent to HELO/EHLO handshake
--smtp-auth <str> * Space-separated list of allowed AUTH mechanisms.
This setting forces to use one of the listed mechanisms.
--smtp-debug <0|1> * Disable, enable Net::SMTP debug.
Automating:
@ -208,7 +210,7 @@ my ($cover_cc, $cover_to);
my ($to_cmd, $cc_cmd);
my ($smtp_server, $smtp_server_port, @smtp_server_options);
my ($smtp_authuser, $smtp_encryption, $smtp_ssl_cert_path);
my ($identity, $aliasfiletype, @alias_files, $smtp_domain);
my ($identity, $aliasfiletype, @alias_files, $smtp_domain, $smtp_auth);
my ($validate, $confirm);
my (@suppress_cc);
my ($auto_8bit_encoding);
@ -239,6 +241,7 @@ my %config_settings = (
"smtppass" => \$smtp_authpass,
"smtpsslcertpath" => \$smtp_ssl_cert_path,
"smtpdomain" => \$smtp_domain,
"smtpauth" => \$smtp_auth,
"to" => \@initial_to,
"tocmd" => \$to_cmd,
"cc" => \@initial_cc,
@ -310,6 +313,7 @@ my $rc = GetOptions("h" => \$help,
"smtp-ssl-cert-path=s" => \$smtp_ssl_cert_path,
"smtp-debug:i" => \$debug_net_smtp,
"smtp-domain:s" => \$smtp_domain,
"smtp-auth=s" => \$smtp_auth,
"identity=s" => \$identity,
"annotate!" => \$annotate,
"no-annotate" => sub {$annotate = 0},
@ -1136,6 +1140,12 @@ sub smtp_auth_maybe {
Authen::SASL->import(qw(Perl));
};
# Check mechanism naming as defined in:
# https://tools.ietf.org/html/rfc4422#page-8
if ($smtp_auth !~ /^(\b[A-Z0-9-_]{1,20}\s*)*$/) {
die "invalid smtp auth: '${smtp_auth}'";
}
# TODO: Authentication may fail not because credentials were
# invalid but due to other reasons, in which we should not
# reject credentials.
@ -1148,6 +1158,20 @@ sub smtp_auth_maybe {
'password' => $smtp_authpass
}, sub {
my $cred = shift;
if ($smtp_auth) {
my $sasl = Authen::SASL->new(
mechanism => $smtp_auth,
callback => {
user => $cred->{'username'},
pass => $cred->{'password'},
authname => $cred->{'username'},
}
);
return !!$smtp->auth($sasl);
}
return !!$smtp->auth($cred->{'username'}, $cred->{'password'});
});