summaryrefslogtreecommitdiffstats
path: root/urpm/signature.pm
blob: b70f5a9903251684308c4b7910221fa8f51d7c2a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package urpm::signature;

# $Id: signature.pm 253617 2009-03-05 11:18:45Z tv $

use strict;
use urpm::msg;
use urpm::media;
use urpm::util;


#- options: callback, basename
sub check {
    my ($urpm, $sources_install, $sources, %options) = @_;
    sort(_check($urpm, $sources_install, %options),
	 _check($urpm, $sources, %options));
}
sub _check {
    my ($urpm, $sources, %options) = @_;
    my ($medium, %invalid_sources);

    foreach my $id (keys %$sources) {
	my $filepath = $sources->{$id};
	$filepath !~ /\.spec$/ or next;

	$urpm->{debug} and $urpm->{debug}("verifying signature of $filepath");
	#- rpmlib is doing strftime %c, and so the string comes from the current encoding
	#- (URPM::bind_rpm_textdomain_codeset() doesn't help here)
	#- so we have to transform...
	my $verif = urpm::msg::from_locale_encoding(URPM::verify_signature($filepath, $urpm->{urpmi_root}));

	if ($verif =~ /NOT OK/) {
	    $verif =~ s/\n//g;
	    $invalid_sources{$filepath} = N("Invalid signature (%s)", $verif);
	} elsif ($verif =~ /OK \(\(none\)\)/ ) {
	    $verif =~ s/\n//g;
	    $invalid_sources{$filepath} = N("Missing signature (%s)", $verif);
	} else {
	    unless ($medium && urpm::media::is_valid_medium($medium) &&
		    $medium->{start} <= $id && $id <= $medium->{end})
	    {
		$medium = undef;
		foreach (@{$urpm->{media}}) {
		    urpm::media::is_valid_medium($_) && $_->{start} <= $id && $id <= $_->{end}
			and $medium = $_, last;
		}
	    }
	    #- no medium found for this rpm ?
	    next if !$medium;
	    #- check whether verify-rpm is specifically disabled for this medium
	    if (defined $medium->{'verify-rpm'} && !$medium->{'verify-rpm'}) {
		$urpm->{log}(N("NOT checking %s\n", $filepath));
		next;
	    }
	    next if defined $medium->{'verify-rpm'} && !$medium->{'verify-rpm'};

	    my $key_ids = $medium->{'key-ids'} || $urpm->{options}{'key-ids'};
	    #- check that the key ids of the medium match the key ids of the package.
	    if ($key_ids) {
		my $valid_ids = 0;
		my $invalid_ids = 0;

		foreach my $key_id ($verif =~ /(?:key id \w{8}|#)(\w+)/gi) {
		    if (any { hex($_) == hex($key_id) } split /[,\s]+/, $key_ids) {
			++$valid_ids;
		    } else {
			++$invalid_ids;
		    }
		}

		if ($invalid_ids) {
		    $invalid_sources{$filepath} = N("Invalid Key ID (%s)", $verif);
		} elsif (!$valid_ids) {
		    $invalid_sources{$filepath} = N("Missing signature (%s)", $verif);
		}
	    }
	    #- invoke check signature callback.
	    $options{callback} and $options{callback}->(
		$urpm, $filepath,
		id => $id,
		verif => $verif,
		why => $invalid_sources{$filepath},
	    );
	}
    }
    map { ($options{basename} ? basename($_) : $_) . ": $invalid_sources{$_}" }
      keys %invalid_sources;
}

1;
list_checks { my ($msec) = @_; difference2([ $msec->raw_checks_list ], [ qw(MAIL_WARN MAIL_USER) ]); } sub list_functions { my ($msec, $category) = @_; ## TODO handle 3 last functions here so they can be removed from this list my @ignore_list = qw(indirect commit_changes closelog error initlog log set_secure_level set_security_conf set_server_level print_changes get_translation create_server_link); my %options = ( 'network' => [qw(accept_bogus_error_responses accept_broadcasted_icmp_echo accept_icmp_echo enable_dns_spoofing_protection enable_ip_spoofing_protection enable_log_strange_packets enable_promisc_check no_password_aging_for)], 'system' => [qw(allow_autologin allow_issues allow_reboot allow_remote_root_login allow_root_login allow_user_list allow_xauth_from_root allow_x_connections allow_xserver_to_listen authorize_services enable_at_crontab enable_console_log enable_msec_cron enable_pam_wheel_for_su enable_password enable_security_check enable_sulogin password_aging password_history password_length set_root_umask set_shell_history_size set_shell_timeout set_user_umask)]); # get all function names; filter out those which are in the ignore # list, return what lefts. grep { !member($_, @ignore_list) && member($_, @{$options{$category}}) } keys %{$msec->{functions}{default}}; } #------------------------------------------------------------- # set back checks|functions values sub set_function { my ($msec, $function, $value) = @_; $msec->{functions}{value}{$function} = $value; } sub set_check { my ($msec, $check, $value) = @_; $msec->{checks}{value}{$check} = $value; } #------------------------------------------------------------- # apply configuration # config_(check|function)(check|function, value) - # Apply the configuration to 'prefix'/etc/security/msec/security.conf||/etc/security/msec/level.local sub apply_functions { my ($msec) = @_; my @list = sort($msec->list_functions('system'), $msec->list_functions('network')); touch($msec->{functions}{values_file}) if !-e $msec->{functions}{values_file}; substInFile { foreach my $function (@list) { s/^$function.*\n// } if (eof) { $_ .= join("\n", if_(!$_, ''), (map { my $value = $msec->get_function_value($_); if_($value ne 'default', "$_ ($value)"); } @list), ""); } } $msec->{functions}{values_file}; } sub apply_checks { my ($msec) = @_; my @list = sort $msec->raw_checks_list; setVarsInSh($msec->{checks}{values_file}, { map { my $value = $msec->get_check_value($_); if_($value ne 'default', $_ => $value); } @list } ); } sub reload { my ($msec) = @_; require security::level; my $num_level = security::level::get(); $msec->{functions}{defaults_file} = "$::prefix/usr/share/msec/level.$num_level"; $msec->{functions}{default} = { $msec->load_defaults('functions') }; } sub new { my ($type) = @_; my $msec = bless {}, $type; $msec->{functions}{values_file} = "$::prefix/etc/security/msec/level.local"; $msec->{checks}{values_file} = "$::prefix/etc/security/msec/security.conf"; $msec->{checks}{defaults_file} = "$::prefix/var/lib/msec/security.conf"; $msec->{checks}{val_separator} = '='; $msec->{functions}{val_separator} = '\('; $msec->{checks}{def_separator} = '='; $msec->{functions}{def_separator} = ' '; $msec->reload; $msec->{checks}{default} = { $msec->load_defaults('checks') }; $msec->{functions}{value} = { $msec->load_values('functions') }; $msec->{checks}{value} = { $msec->load_values('checks') }; $msec; } 1;