]> git.ipfire.org Git - thirdparty/git.git/commitdiff
contrib: better support symbolic port names in git-credential-netrc
authorMaxim Cournoyer <maxim@guixotic.coop>
Tue, 24 Jun 2025 01:48:57 +0000 (10:48 +0900)
committerJunio C Hamano <gitster@pobox.com>
Tue, 24 Jun 2025 16:05:35 +0000 (09:05 -0700)
To improve support for symbolic port names in netrc files, this
changes does the following:

 - Treat symbolic port names as ports, not protocols in git-credential-netrc
 - Validate the SMTP server port provided to send-email
 - Convert the above symbolic port names to their numerical values.

Before this change, it was not possible to have a SMTP server port set
to "smtps" in a netrc file (e.g. Emacs' ~/.authinfo.gpg), as it would
be registered as a protocol and break the match for a "smtp" protocol
host, as queried for by git-send-email.

Signed-off-by: Maxim Cournoyer <maxim@guixotic.coop>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
contrib/credential/netrc/git-credential-netrc.perl
contrib/credential/netrc/test.pl
git-send-email.perl
perl/Git.pm
t/t9001-send-email.sh

index 09d77b4f69380b376a840cce0499567693a5718c..3c0a532d0e2409da9cc2854e69d169603e44a2f4 100755 (executable)
@@ -268,13 +268,16 @@ sub load_netrc {
                        next;
                }
                if (defined $nentry->{port}) {
-                       if ($nentry->{port} =~ m/^\d+$/) {
-                               $num_port = $nentry->{port};
-                               delete $nentry->{port};
-                       } else {
+                       $num_port = Git::port_num($nentry->{port});
+                       unless ($num_port) {
                                printf(STDERR "ignoring invalid port `%s' " .
                                       "from netrc file\n", $nentry->{port});
                        }
+                       # Since we've already validated and converted
+                       # the port to its numerical value, do not
+                       # capture it as the `protocol' value, as used
+                       # to be the case for symbolic port names.
+                       delete $nentry->{port};
                }
 
                # create the new entry for the credential helper protocol
index 67a0ede5644dd23f9eb38098f7b5ef8f61885424..8a7fc2588a37f331e690cb5bc4a017979f21432e 100755 (executable)
@@ -45,7 +45,7 @@ chmod 0600, $netrc;
 diag "Testing with invalid data\n";
 $cred = run_credential(['-f', $netrc, 'get'],
                       "bad data");
-ok(scalar keys %$cred == 4, "Got first found keys with bad data");
+ok(scalar keys %$cred == 3, "Got first found keys with bad data");
 
 diag "Testing netrc file for a missing corovamilkbar entry\n";
 $cred = run_credential(['-f', $netrc, 'get'],
@@ -64,12 +64,12 @@ is($cred->{username}, 'carol', "Got correct Github username");
 
 diag "Testing netrc file for a username-specific entry\n";
 $cred = run_credential(['-f', $netrc, 'get'],
-                      { host => 'imap', username => 'bob' });
+                      { host => 'imap:993', username => 'bob' });
 
-ok(scalar keys %$cred == 2, "Got 2 username-specific keys");
+# Only the password field gets returned.
+ok(scalar keys %$cred == 1, "Got 1 username-specific keys");
 
 is($cred->{password}, 'bobwillknow', "Got correct user-specific password");
-is($cred->{protocol}, 'imaps', "Got correct user-specific protocol");
 
 diag "Testing netrc file for a host:port-specific entry\n";
 $cred = run_credential(['-f', $netrc, 'get'],
index 659e6c588bcf8792363385643ba17f08e4885d06..d2cf9b717af047d4fb8e5a9533cc97563a084daf 100755 (executable)
@@ -2101,6 +2101,17 @@ if ($validate) {
                }
        }
 
+       # Validate the SMTP server port, if provided.
+       if (defined $smtp_server_port) {
+               my $port = Git::port_num($smtp_server_port);
+               if ($port) {
+                       $smtp_server_port = $port;
+               } else  {
+                       die sprintf(__("error: invalid SMTP port '%s'\n"),
+                                   $smtp_server_port);
+               }
+       }
+
        # Run the loop once again to avoid gaps in the counter due to FIFO
        # arguments provided by the user.
        my $num = 1;
index 6f47d653abe522accec37b8394ca0ab9e0ba12a0..090cf77daba32351f9e34f9a781fadbbac62b4f0 100644 (file)
@@ -1061,6 +1061,19 @@ sub _close_cat_blob {
        delete @$self{@vars};
 }
 
+# Given PORT, a port number or service name, return its numerical
+# value else undef.
+sub port_num {
+    my ($port) = @_;
+
+    # Port can be either a positive integer within the 16-bit range...
+    if ($port =~ /^\d+$/ && $port > 0 && $port <= (2**16 - 1)) {
+        return $port;
+    }
+
+    # ... or a symbolic port (service name).
+    return scalar getservbyname($port, '');
+}
 
 =item credential_read( FILEHANDLE )
 
index 0c1af43f6fbb41b7482776d9f03e7e28166d3bcb..e56e0c8d7770b070b706ef9b7c90b7945a0b3a3a 100755 (executable)
@@ -201,6 +201,13 @@ test_expect_success $PREREQ 'cc trailer with get_maintainer.pl output' '
        test_cmp expected-cc commandline1
 '
 
+test_expect_failure $PREREQ 'invalid smtp server port value' '
+       clean_fake_sendmail &&
+       git send-email -1 --to=recipient@example.com \
+               --smtp-server-port=bogus-symbolic-name \
+               --smtp-server="$(pwd)/fake.sendmail"
+'
+
 test_expect_success $PREREQ 'setup expect' "
 cat >expected-show-all-headers <<\EOF
 0001-Second.patch