[PATCH RFC3.5.1 04/12] send-email: Verification for --smtp-server and --smpt-server-port

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The server URI is verified according to RFCs (including IPv6 support).

The $smtp_server and $smtp_server_port setup code has been moved
higher in the file, so that send-email fails fast if they are bad.

Now, the 'host:port' server URI form is handled regardless of the
documentation deficiencies of Net::SMTP{,::SSL}.

Signed-off-by: Michael Witten <mfwitten@xxxxxxxxx>
---

		NOTE: This changed due to the change in:
		[PATCH RFC3.5.1 03/12] send-email: Interpret...
		Basically, only "a built-in" was changed to
		"the built-in".

		Is it ever useful to submit patches for patches
		rather than sending the whole patch gain? Or would
		that be even more trouble?

 Documentation/git-send-email.txt |   50 ++++++++++++-----
 git-send-email.perl              |  115 +++++++++++++++++++++++++++++++------
 2 files changed, 131 insertions(+), 34 deletions(-)

diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index 0937dd0..f306e88 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -125,23 +125,43 @@ specified (with '--smtp-pass' or 'sendemail.smtppass'), then the
 user is prompted for a password while the input is masked for privacy.
 
 --smtp-server=<server>::
-	If set, specifies the outgoing SMTP server to use (e.g.
-	`smtp.example.com` or a raw IP address).  Alternatively it can
-	specify a full pathname of a sendmail-like program instead;
-	the program must support the `-i` option.  Default value can
-	be specified by the 'sendemail.smtpserver' configuration
-	variable; the built-in default is `/usr/sbin/sendmail` or
-	`/usr/lib/sendmail` if such a program is available, or
-	`localhost` otherwise. Also, the built-in default is used if
-	`<host>` or 'sendemail.smtpserver' is the empty string (for
-	example, if '--smtp-server ""' is specified on the command line).
+	Specifies the outgoing SMTP server to use. The server may be
+	given as a domain name (e.g. `smtp.example.com:587`), raw IP
+	address (e.g. `192.168.0.1`), or absolute path to a command
+	(e.g. `/usr/sbin/sendmail`).
++
+Usually a server is specified with its URI form:
++
+	host[:port]
++
+The optional port, which identifies a particular service at the
+given host, is normally provided as a non-negative integer that
+is representable in 16-bits; however, it is possible to use any
+string composed of some combination of alphanumeric characters, the
+underscore, the hyphen, and punctuation (special) characters, so
+that symbolic service names can be employed (as defined by, say,
+`/etc/services` on Unix systems).
++
+Alternatively the server can be specified as an absolute path to
+a sendmail-like program; in particular, the program must support
+`sendmail's` `-i` option.
++
+Default value can be specified by the 'sendemail.smtpserver'
+configuration variable; the built-in default is `/usr/sbin/sendmail`
+or `/usr/lib/sendmail` if such a program is available, or `localhost`
+otherwise. Also, the built-in default is used if `<server>` or
+'sendemail.smtpserver' is the empty string (for example, if
+'--smtp-server ""' is specified on the command line).
 
 --smtp-server-port=<port>::
-	Specifies a port different from the default port (SMTP
-	servers typically listen to smtp port 25 and ssmtp port
-	465); symbolic service names (e.g. "submission" instead of 587)
-	are also accepted. The port can also be set with the
-	'sendemail.smtpserverport' configuration variable.
+	Specifies a port different from the default port (SMTP servers
+	typically listen to port 25, 587, or even non-standard 465); symbolic
+	service names (e.g. "submission" instead of 587) are also accepted,
+	provided the underlying system handles mappings in something like
+	`/etc/services`; such service names may only be composed of some
+	combination of alphanumeric characters, the underscore, the hyphen,
+	and punctuation (special) characters. The port can also be set with
+	the 'sendemail.smtpserverport' configuration variable.
 
 --smtp-ssl::
 	Legacy alias for '--smtp-encryption ssl'.
diff --git a/git-send-email.perl b/git-send-email.perl
index be6d171..559e17b 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -61,7 +61,7 @@ git send-email [options] <file | directory | rev-list options >
 
   Sending:
     --envelope-sender   <address>  * Email envelope sender.
-    --smtp-server        <server>  * Outgoing SMTP server. <host | command>
+    --smtp-server        <server>  * Outgoing SMTP server: <host[:port] | cmd>.
     --smtp-server-port     <port>  * Outgoing SMTP server port; symbolic too.
     --smtp-user        <username>  * Username for SMTP-AUTH.
     --smtp-pass       [<password>] * Password for SMTP-AUTH; not necessary.
@@ -328,6 +328,101 @@ foreach my $setting (values %config_bool_settings) {
 # 'default' encryption is none -- this only prevents a warning
 $smtp_encryption = '' unless (defined $smtp_encryption);
 
+# Define a function that verifies a server URI and returns
+# its host and port parts:
+
+sub parse_server_URI($) {
+
+	# These regular experssions were derived from:
+	#   * RFC 2373 (Appendix B) : IP Version 6 Addressing Architecture
+	#   * RFC 2732 (Section  3) : Format for Literal IPv6 Addresses in URL's
+	#   * RFC 2396 (Sec. 3.2.2) : Uniform Resource Identifiers (URI): Generic Syntax
+	# Also, ports are allowed to be symbolic, so that /etc/services mappings
+	# can be used.
+
+	# Define a port (RFC 2396 and extension):
+
+	my $port = qr/[\w[:punct:]]+/;
+
+	# Define an IPv4 address (RFC 2373):
+
+	my $dig3        = qr/\d{1,3}/;
+	my $IPv4address = qr/$dig3(?:\.$dig3){3}/;
+
+	# Define an IPv6 address (RFC 2373):
+
+	my $hex4        = qr/[[:xdigit:]]{1,4}/;
+	my $hexseq      = qr/$hex4(?::$hex4)*/;  		# RFC 2373 is really that loose.
+	my $hexpart     = qr/$hexseq|$hexseq?::$hexseq?/;
+	my $IPv6address = qr/$hexpart(?::$IPv4address)?/;
+
+	# Define an IPv6 literal (RFC 2732):
+
+	my $IPv6reference = qr/\[$IPv6address\]/;
+
+	# Define a server URI (RFC 2396 and RFC 2732):
+
+	my $toplabel    = qr/[[:alpha:]](?:(?:[[:alnum:]]|-)*[[:alpha:]])?/;
+	my $domainlabel = qr/[[:alnum:]](?:(?:[[:alnum:]]|-)*[[:alnum:]])?/;
+	my $hostname    = qr/(?:$domainlabel\.)*$toplabel\.?/;
+	my $host        = qr/$hostname|$IPv4address|$IPv6reference/;
+	my $hostport    = qr/^($host)(?::($port))?$/;
+
+	# Phew! Now parse
+
+	return shift =~ $hostport;
+}
+
+# Figure out how to contact the SMTP server.
+# After this code, $smtp_server_port is either
+# valid or undef:
+
+if (defined $smtp_server && $smtp_server ne '') {
+
+	if ($smtp_server_is_a_command = ($smtp_server =~ m{^/})) {
+
+		die "--smtp-server: The SMTP server command does not exist: $smtp_server\n"
+			unless -x $smtp_server;
+
+		print STDERR "--smtp-server: Using command '$smtp_server'; ignoring --smtp-server-port='$smtp_server_port'\n"
+			if defined $smtp_server_port;
+
+	} else {
+
+		($smtp_server, my $port) = parse_server_URI $smtp_server
+			or die "--smtp-server: Not a valid server URI: '$smtp_server'\n";
+
+		if (defined $smtp_server_port) {
+
+			$smtp_server_port =~ /[\w[:punct:]]+/ or die "--smtp-server-port: Invalid port: '$smtp_server_port'\n";
+
+			print STDERR "--smtp-server-port: Using port '$smtp_server_port'; ignoring --smtp-server's port '$port'\n"
+				if defined $port;
+
+		} else {
+
+			$smtp_server_port = $port;
+		}
+	}
+
+} else { # use a default:
+
+	foreach (qw( /usr/sbin/sendmail /usr/lib/sendmail )) {
+		if (-x $_) {
+			$smtp_server = $_;
+			$smtp_server_is_a_command = 1;
+
+			print STDERR "--smtp-server: Using command '$smtp_server'; ignoring --smtp-server-port='$smtp_server_port'\n"
+				if defined $smtp_server_port;
+
+			last;
+		}
+	}
+
+	$smtp_server = 'localhost' # 127.0.0.1 is not compatible with IPv6
+		unless $smtp_server_is_a_command;
+}
+
 # Set CC suppressions
 my(%suppress_cc);
 if (@suppress_cc) {
@@ -675,24 +770,6 @@ if (defined $initial_reply_to) {
 	$initial_reply_to = "<$initial_reply_to>" if $initial_reply_to ne '';
 }
 
-if (defined $smtp_server && $smtp_server ne '') {
-
-	$smtp_server_is_a_command = ($smtp_server =~ m{^/});
-
-} else { # use a default:
-
-	foreach (qw( /usr/sbin/sendmail /usr/lib/sendmail )) {
-		if (-x $_) {
-			$smtp_server = $_;
-			$smtp_server_is_a_command = 1;
-			last;
-		}
-	}
-
-	$smtp_server = 'localhost' # 127.0.0.1 is not compatible with IPv6
-		unless $smtp_server_is_a_command;
-}
-
 if ($compose && $compose > 0) {
 	@files = ($compose_filename . ".final", @files);
 }
-- 
1.6.2.2.479.g2aec

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]