Re: [PATCHv5] Add contrib/credentials/netrc with GPG support

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

 



Ted Zlatanov <tzz@xxxxxxxxxxxx> writes:

> +	unless (scalar @entries) {
> +		if ($!) {
> +			log_verbose("Unable to open $file: $!");
> +		}
> +		else {

	} else {

> +			log_verbose("No netrc entries found in $file");
> +		}
> +
> +	if ($gpgmode) {
> +		# typical shell character escapes from http://www.slac.stanford.edu/slac/www/resource/how-to-use/cgi-rexx/cgi-esc.html
> +		my $f = $file;
> +		$f =~ s/([;<>\*\|`&\$!#\(\)\[\]\{\}:'"])/\\$1/g;

Yuck.  If you really have to quote, it is often far simpler to take
advantage of the fact that quoting rule for shell is much simpler
inside '', i.e.

	sub sq {
		my ($string) = @_;
		$string =~ s|'|'\\''|g;
		return "'$string'";
	}

The only thing you have to worry about is a single quote, which
would close the single quote you want to be in, and you express it
by first closing the single quote you opened, put the single quote
by emitting a backslash and a single quote, and then immediately 
open another single quote.

> +		# GPG doesn't work well with 2- or 3-argument open

I think I commented on this in a separate message.

> +	# Net::Netrc does this, but the functionality is merged with the file
> +	# detection logic, so we have to extract just the part we need
> +	my @netrc_entries = net_netrc_loader($io);
> +
> +	# these entries will use the credential helper protocol token names
> +	my @entries;
> +
> +	foreach my $nentry (@netrc_entries) {
> +		my %entry;
> +		my $num_port;
> +
> +		if (defined $nentry->{port} && $nentry->{port} =~ m/^\d+$/) {
> +			$num_port = $nentry->{port};
> +			delete $nentry->{port};
> +		}
> +
> +		# create the new entry for the credential helper protocol
> +		$entry{$options{tmap}->{$_}} = $nentry->{$_} foreach keys %$nentry;
> +
> +		# for "host X port Y" where Y is an integer (captured by
> +		# $num_port above), set the host to "X:Y"
> +		if (defined $entry{host} && defined $num_port) {
> +			$entry{host} = join(':', $entry{host}, $num_port);
> +		}
> +
> +		push @entries, \%entry;
> +	}
> +
> +	return @entries;
> +}

I'll leave this part to Peff to comment on.

> +sub net_netrc_loader {
> +	my $fh = shift @_;
> +	my @entries;
> +	my ($mach, $macdef, $tok, @tok);
> +
> +    LINE:
> +	while (<$fh>) {
> +		undef $macdef if /\A\n\Z/;
> +
> +		if ($macdef) {
> +			next LINE;
> +		}
> +
> +		s/^\s*//;
> +		chomp;
> +
> +		while (length && s/^("((?:[^"]+|\\.)*)"|((?:[^\\\s]+|\\.)*))\s*//) {
> +			(my $tok = $+) =~ s/\\(.)/$1/g;
> +			push(@tok, $tok);
> +		}
> +
> +	    TOKEN:
> +		while (@tok) {
> +			if ($tok[0] eq "default") {
> +				shift(@tok);
> +				undef $mach; # ignore 'default' lines

I think it is saner to do something like this instead here:

				$mach = { machine => undef }

Otherwise your log_debug() will be filled by the tokens used for the
default entry, and also this "undef $mach" here will break your
macdef skipping logic if the default entry has a macdef, I think.

You can ignore an entry with undefined "machine" in the loop at the
end of load_netrc.

> +				next TOKEN;
> +			}
> +
> +			$tok = shift(@tok);
> +
> +			if ($tok eq "machine") {
> +				my $host = shift @tok;
> +				$mach = { machine => $host };
> +				push @entries, $mach;
> +			}
> +			elsif (exists $options{tmap}->{$tok}) {
> +				unless ($mach) {
> +					log_debug("Skipping token $tok because no machine was given");
> +					next TOKEN;
> +				}
> +
> +				my $value = shift @tok;
> +				unless (defined $value) {
> +					log_debug("Token $tok had no value, skipping it.");
> +					next TOKEN;
> +				}
> +
> +				# Following line added by rmerrell to remove '/' escape char in .netrc
> +				$value =~ s/\/\\/\\/g;
> +				$mach->{$tok} = $value;
> +			}
> +			elsif ($tok eq "macdef") { # we ignore macros
> +				next TOKEN unless $mach;
> +				my $value = shift @tok;
> +				$macdef = 1;
> +			}
> +		}
> +	}
> +
> +	return @entries;
> +}
> +
> +sub read_credential_data_from_stdin {
> +	# the query: start with every token with no value
> +	my %q = map { $_ => undef } values(%{$options{tmap}});
> +
> +	while (<STDIN>) {
> +		next unless m/^([^=]+)=(.+)/;
> +
> +		my ($token, $value) = ($1, $2);
> +		die "Unknown search token $token" unless exists $q{$token};
> +		$q{$token} = $value;
> +		log_debug("We were given search token $token and value $value");
> +	}
> +
> +	foreach (sort keys %q) {
> +		log_debug("Searching for %s = %s", $_, $q{$_} || '(any value)');
> +	}
> +
> +	return \%q;
> +}
> +
> +# takes the search tokens and then a list of entries
> +# each entry is a hash reference
> +sub find_netrc_entry {
> +	my $query = shift @_;
> +
> +    ENTRY:
> +	foreach my $entry (@_)
> +	{
> +		my $entry_text = join ', ', map { "$_=$entry->{$_}" } keys %$entry;
> +		foreach my $check (sort keys %$query) {
> +			if (defined $query->{$check}) {
> +				log_debug("compare %s [%s] to [%s] (entry: %s)",
> +					  $check,
> +					  $entry->{$check},
> +					  $query->{$check},
> +					  $entry_text);
> +				unless ($query->{$check} eq $entry->{$check}) {
> +					next ENTRY;
> +				}
> +			}
> +			else {
> +				log_debug("OK: any value satisfies check $check");
> +			}
> +		}
> +
> +		return $entry;
> +	}
> +
> +	# nothing was found
> +	return;
> +}

I'll leave this part to Peff to comment on.

> +
> +sub print_credential_data {
> +	my $entry = shift @_;
> +	my $query = shift @_;
> +
> +	log_debug("entry has passed all the search checks");
> + TOKEN:
> +	foreach my $git_token (sort keys %$entry) {
> +		log_debug("looking for useful token $git_token");
> +		# don't print unknown (to the credential helper protocol) tokens
> +		next TOKEN unless exists $query->{$git_token};
> +
> +		# don't print things asked in the query (the entry matches them)
> +		next TOKEN if defined $query->{$git_token};
> +
> +		log_debug("FOUND: $git_token=$entry->{$git_token}");
> +		printf "%s=%s\n", $git_token, $entry->{$git_token};
> +	}
> +}
> +sub log_verbose {
> +	return unless $options{verbose};
> +	printf STDERR @_;
> +	printf STDERR "\n";
> +}
> +
> +sub log_debug {
> +	return unless $options{debug};
> +	printf STDERR @_;
> +	printf STDERR "\n";
> +}

Otherwise, looks almost ready to me.

Thanks.
--
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]