diff options
-rw-r--r-- | urpm/cfg.pm | 2 | ||||
-rw-r--r-- | urpm/ldap.pm | 218 | ||||
-rw-r--r-- | urpmi.schema | 170 |
3 files changed, 389 insertions, 1 deletions
diff --git a/urpm/cfg.pm b/urpm/cfg.pm index e3988ea5..5baffc60 100644 --- a/urpm/cfg.pm +++ b/urpm/cfg.pm @@ -115,7 +115,7 @@ sub load_config ($;$) { _syntax_error(); return; } - $config{$medium}{priority} = ++$priority; #- to preserve order + $config{$medium}{priority} = $priority++; #- to preserve order undef $medium; next; } diff --git a/urpm/ldap.pm b/urpm/ldap.pm new file mode 100644 index 00000000..21e19eaf --- /dev/null +++ b/urpm/ldap.pm @@ -0,0 +1,218 @@ +package urpm::ldap; + +use strict; +use warnings; +use urpm::msg 'N'; + +use Net::LDAP; +use MDK::Common; + +my $LDAP_CONFIG_FILE = '/etc/openldap/ldap.conf'; +# FIXME duplication +my @per_media_opt = qw( + downloader + hdlist + ignore + key-ids + list + md5sum + noreconfigure + priority + priority-upgrade + removable + synthesis + update + verify-rpm + virtual + with_hdlist +); + +# TODO +# use srv dns record ? +# complete the doc + + +=head1 NAME + +urpm::ldap - routines to handle configuration with ldap + +=head1 SYNOPSIS + +=head1 DESCRIPTION + +=over + +=item write_ldap_cache($urpm,$medium) + +Write the value fetched from ldap, in case of failure of server +This should not be used to reduce the load of ldap server, as +fetching is still needed, and therefore, caching is useless if server is up + +=item check_ldap_medium($medium) + +Check if the ldap medium has all needed attributes. + +=item read_ldap_cache($urpm,%options) + +Read the cache created by the function write_ldap_cache. +should be called if the ldap server do not respond ( upgrade, network problem, +mobile user, etc ). + +=item clean_ldap_cache($urpm) + +Clean the ldap cache, remove all file in the directory. + +=item load_ldap_media($urpm,%options) + +=item get_ldap_config + +=item get_ldap_config_file($file) + +=item get_ldap_config_dns + +=cut + +sub write_ldap_cache($$) { + my ($urpm, $medium) = @_; + my $ldap_cache = "$urpm->{cachedir}/ldap"; + # FIXME what perm for cache ? + mkdir_p($ldap_cache); + open(my $cache, ">$ldap_cache/$medium->{name}") or die N("Cannot write cache file for ldap\n"); + print $cache "# internal cache file for disconnect ldap operation, do not edit\n"; + foreach (keys %$medium) + { + defined $medium->{$_} or next; + print $cache "$_ = $medium->{$_}\n"; + } + close($cache); +} + +sub check_ldap_medium($) { + my ($medium) = @_; + return $medium->{name} && $medium->{clear_url}; +} + +sub read_ldap_cache($%) { + my ($urpm, %options) = @_; + foreach (glob("$urpm->{cachedir}/ldap/*")) + { + ! -f $_ and next; + my %medium = getVarsFromSh($_); + next if ! check_ldap_medium(\%medium); + $urpm->probe_medium(\%medium, %options) and push @{$urpm->{media}}, \%medium; + } +} + +#- clean the cache, before writing a new one +sub clean_ldap_cache($) { + my ($urpm) = @_; + unlink($_) foreach glob("$urpm->{cachedir}/ldap/*"); +} + +sub get_ldap_config { + return get_ldap_config_file($LDAP_CONFIG_FILE); +} + +sub get_ldap_config_file($) { + my ($file) = @_; + my %config; + # TODO more verbose error ? + open(my $CONFIG, $file) or return; + while(<$CONFIG>) { + s/#.*//; + s/^\s*//; + s/\s*$//; + s/\s{2}/ /g; + /^$/ and next; + /^(\S*)\s*(\S*)/; + ! $2 and next; + $config{$1} = $2; + } + close($CONFIG); + return \%config; +} + +sub get_ldap_config_dns { + # TODO + die "not implemented now"; +} + + +sub load_ldap_media($%) { + my ($urpm,%options) = @_; + + my $config = get_ldap_config() or return ; + + # try first urpmi_foo and then foo + for my $opt ('base', 'uri', 'filter', 'host', 'ssl', 'port', 'binddn', 'passwd', 'scope' ) + { + if ( !defined $config->{"$opt"} && defined $config->{"urpmi_$opt"}) + { + $config->{"$opt"} = $config->{"urpmi_$opt"}; + } + } + + die N("No server defined, missing uri or host") if ! ( defined $config->{'uri'} || defined $config->{'host'} ); + die N("No base defined") if ! defined $config->{'base'}; + + if (! defined $config->{'uri'}) { + $config->{'uri'} = "ldap" . ( $config->{'ssl'} eq 'on' ? "s" : "" ) . "://" . + $config->{'host'} . ( $config->{'port'} ? ":" . $config->{'port'} : "" ) . "/" ; + } + + + eval { + my $ldap = Net::LDAP->new($config->{'uri'}) + or die N("Cannot connect to ldap uri :"), $config->{'uri'}; + + $ldap->bind($config->{'binddn'}, $config->{'password'}) + or die N("Cannot connect to ldap uri :"), $config->{'uri'}; + #- base is mandatory + my $result = $ldap->search( + base => $config->{'base'} , + filter => $config->{'filter'} || '(objectClass=urpmiRepository)', + scope => $config->{'scope'} || 'sub' + ); + + $result->code and die $result->error; + # FIXME more than one server ? + clean_ldap_cache($urpm); + + foreach my $entry ($result->all_entries) { + my $medium = {}; + my %ldap_changed_attributes = ( + 'source-name' => 'name', + 'url' => 'clear_url', + 'with-hdlist' => 'with_hdlist' + ); + + foreach my $opt (@per_media_opt, keys %ldap_changed_attributes) { + defined $entry->get_value($opt) and $medium->{$opt} = $entry->get_value($opt); + } + + #- name is not valid for the schema ( already in top ) + #- and _ are forbidden in attributes names + + foreach ( keys ( %ldap_changed_attributes ) ) + { + $medium->{$ldap_changed_attributes{$_}} = $medium->{$_}; + delete $medium->{$_}; + } + #- add ldap_ to reduce collision + #- TODO check if name already defined ? + $medium->{'name'} = "ldap" . "_" . $medium->{'name'}; + $medium->{'ldap'} = 1; + next if ! check_ldap_medium($medium); + $urpm->probe_medium($medium, %options) and push @{$urpm->{media}}, $medium; + $urpm->write_ldap_cache($medium) or $urpm->{log}(N("Could not write ldap cache : ") . $_ ); + } + }; + if ($@) + { + $urpm->{log}($@); + read_ldap_cache($urpm,%options); + } + +} + +1; diff --git a/urpmi.schema b/urpmi.schema new file mode 100644 index 00000000..80a92893 --- /dev/null +++ b/urpmi.schema @@ -0,0 +1,170 @@ +# TODO sOmeone need to change this with Mandrakesoft OID. + +# http://www.iana.org/assignments/enterprise-numbers +# 21103 +# Mandrakesoft +# Frederic Lepied +# flepied@mandrakesoft.com + +objectidentifier MANDRIVA 1.3.6.1.4.1.21103 +#objectidentifier MANDRIVA:1 +objectidentifier URPMI 1.3.6.4.1.3.1.21103.1 +objectidentifier URPMIA URPMI:1 +objectidentifier URPMIO URPMI:2 + +# name is already taken +attributetype ( URPMIA:1 + NAME 'source-name' + DESC 'Name appended to the source' + EQUALITY caseExactMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + + +attributetype (URPMIA:2 + NAME 'url' + DESC 'Url of the rpm repository' + EQUALITY caseExactMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + +attributetype (URPMIA:3 + NAME 'downloader' + DESC 'Software used to download ( curl or wget )' + EQUALITY caseExactMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + +attributetype (URPMIA:4 + NAME 'hdlist' + DESC 'Name of the hdlist' + EQUALITY caseExactMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + +attributetype (URPMIA:5 + NAME 'key-ids' + DESC 'Key identifier' + EQUALITY caseExactMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + +attributetype (URPMIA:6 + NAME 'list' + DESC 'Name of the list file' + EQUALITY caseExactMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + +# md5sum => ?? +attributetype (URPMIA:7 + NAME 'md5sum' + DESC '??' + EQUALITY caseExactMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + +# removable => ?? +attributetype (URPMIA:9 + NAME 'removable' + DESC '??' + EQUALITY caseExactMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + +# _ is forbidden, so i use - +attributetype (URPMIA:10 + NAME 'with-hdlist' + DESC 'Path to the hdlist' + EQUALITY caseExactMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + + +# 1.3.6.1.4.1.1466.115.121.1.7 +# verify-rpm +attributetype (URPMIA:11 + NAME 'verify-rpm' + DESC 'Check if rpm needs to be verified' + EQUALITY booleanMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 ) + +# synthesis +attributetype (URPMIA:12 + NAME 'synthesis' + DESC 'Use synthesis index' + EQUALITY booleanMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 ) + +# virtual bool +attributetype (URPMIA:13 + NAME 'virtual' + DESC 'Is the repostiroy constructed on the fly' + EQUALITY booleanMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 ) + +# noreconfigure bool +# TODO isn't this implied, as urpmi cannot write to ldap +attributetype (URPMIA:14 + NAME 'noreconfigure' + DESC 'Do not attempt to reconfigure the source' + EQUALITY booleanMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 ) + +# update bool +attributetype (URPMIA:15 + NAME 'update' + DESC 'Source is a update one' + EQUALITY booleanMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 ) + +# ignore bool +attributetype (URPMIA:16 + NAME 'ignore' + DESC 'Source is ignored' + EQUALITY booleanMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 ) + +attributetype (URPMIA:17 + NAME 'http-proxy' + DESC 'Http proxy specification' + EQUALITY caseExactMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + +attributetype (URPMIA:18 + NAME 'ftp-proxy' + DESC 'Ftp proxy' + EQUALITY caseExactMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + +attributetype (URPMIA:19 + NAME 'proxy-user' + DESC 'User of the proxy' + EQUALITY caseExactMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + +attributetype (URPMIA:20 + NAME 'proxy-password' + DESC 'Password of the proxy' + EQUALITY caseExactMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + + + + +# TODO if virtual is TRUE, no need for hdlist +objectclass (URPMIO:1 NAME 'urpmiRepository' + DESC 'A urpmi repository' + SUP top + STRUCTURAL + MUST ( source-name $ url $ hdlist $ with-hdlist ) + MAY ( downloader $ key-ids $ list $ priority $ + md5sum $ removable $ verify-rpm $ synthesis $ virtual $ + noreconfigure $ update $ ignore $ http-proxy $ ftp-proxy $ + proxy-user $ proxy-password $ + cn ) + ) |