contrib: better support symbolic port names in git-credential-netrc
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>
Maxim Cournoyer committed
Jun 25, 2025 at 23:25 UTC
1926d9b6dac2cc7584362fb9275b55c2904891d3
5 files changed
+42
-8
contrib/credential/netrc/git-credential-netrc.perl
+7
-4
@@ -268,13 +268,16 @@ sub load_netrc {
268
next;
269
}
270
if (defined $nentry->{port}) {
271
- if ($nentry->{port} =~ m/^\d+$/) {
272
- $num_port = $nentry->{port};
273
- delete $nentry->{port};
274
- } else {
271
+ $num_port = Git::port_num($nentry->{port});
272
+ unless ($num_port) {
273
printf(STDERR "ignoring invalid port `%s' " .
274
"from netrc file\n", $nentry->{port});
275
}
276
+ # Since we've already validated and converted
277
+ # the port to its numerical value, do not
278
+ # capture it as the `protocol' value, as used
279
+ # to be the case for symbolic port names.
280
+ delete $nentry->{port};
281
}
282
283
# create the new entry for the credential helper protocol
contrib/credential/netrc/test.pl
+4
-4
@@ -45,7 +45,7 @@ chmod 0600, $netrc;
45
diag "Testing with invalid data\n";
46
$cred = run_credential(['-f', $netrc, 'get'],
47
"bad data");
48
-ok(scalar keys %$cred == 4, "Got first found keys with bad data");
48
+ok(scalar keys %$cred == 3, "Got first found keys with bad data");
49
50
diag "Testing netrc file for a missing corovamilkbar entry\n";
51
$cred = run_credential(['-f', $netrc, 'get'],
@@ -64,12 +64,12 @@ is($cred->{username}, 'carol', "Got correct Github username");
64
65
diag "Testing netrc file for a username-specific entry\n";
66
$cred = run_credential(['-f', $netrc, 'get'],
67
- { host => 'imap', username => 'bob' });
67
+ { host => 'imap:993', username => 'bob' });
68
69
-ok(scalar keys %$cred == 2, "Got 2 username-specific keys");
69
+# Only the password field gets returned.
70
+ok(scalar keys %$cred == 1, "Got 1 username-specific keys");
71
72
is($cred->{password}, 'bobwillknow', "Got correct user-specific password");
72
-is($cred->{protocol}, 'imaps', "Got correct user-specific protocol");
73
74
diag "Testing netrc file for a host:port-specific entry\n";
75
$cred = run_credential(['-f', $netrc, 'get'],
git-send-email.perl
+11
@@ -2101,6 +2101,17 @@ if ($validate) {
2101
}
2102
}
2103
2104
+ # Validate the SMTP server port, if provided.
2105
+ if (defined $smtp_server_port) {
2106
+ my $port = Git::port_num($smtp_server_port);
2107
+ if ($port) {
2108
+ $smtp_server_port = $port;
2109
+ } else {
2110
+ die sprintf(__("error: invalid SMTP port '%s'\n"),
2111
+ $smtp_server_port);
2112
+ }
2113
+ }
2114
+
2115
# Run the loop once again to avoid gaps in the counter due to FIFO
2116
# arguments provided by the user.
2117
my $num = 1;
perl/Git.pm
+13
@@ -1061,6 +1061,19 @@ sub _close_cat_blob {
1061
delete @$self{@vars};
1062
}
1063
1064
+# Given PORT, a port number or service name, return its numerical
1065
+# value else undef.
1066
+sub port_num {
1067
+ my ($port) = @_;
1068
+
1069
+ # Port can be either a positive integer within the 16-bit range...
1070
+ if ($port =~ /^\d+$/ && $port > 0 && $port <= (2**16 - 1)) {
1071
+ return $port;
1072
+ }
1073
+
1074
+ # ... or a symbolic port (service name).
1075
+ return scalar getservbyname($port, '');
1076
+}
1077
1078
=item credential_read( FILEHANDLE )
1079
t/t9001-send-email.sh
+7
@@ -201,6 +201,13 @@ test_expect_success $PREREQ 'cc trailer with get_maintainer.pl output' '
201
test_cmp expected-cc commandline1
202
'
203
204
+test_expect_failure $PREREQ 'invalid smtp server port value' '
205
+ clean_fake_sendmail &&
206
+ git send-email -1 --to=recipient@example.com \
207
+ --smtp-server-port=bogus-symbolic-name \
208
+ --smtp-server="$(pwd)/fake.sendmail"
209
+'
210
+
211
test_expect_success $PREREQ 'setup expect' "
212
cat >expected-show-all-headers <<\EOF
213
0001-Second.patch