summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuillaume Cottenceau <gc@mandriva.com>2003-11-14 15:39:13 +0000
committerGuillaume Cottenceau <gc@mandriva.com>2003-11-14 15:39:13 +0000
commitf383158b26368bc0b3d9f2fa59d8066b9d1e2278 (patch)
tree19326ae57648b45bab466927b342efd27ef8d6ac
parent1b791cfb9d9ca2efdd1ede0cf3b8f4b9148ab462 (diff)
downloaddrakx-f383158b26368bc0b3d9f2fa59d8066b9d1e2278.tar
drakx-f383158b26368bc0b3d9f2fa59d8066b9d1e2278.tar.gz
drakx-f383158b26368bc0b3d9f2fa59d8066b9d1e2278.tar.bz2
drakx-f383158b26368bc0b3d9f2fa59d8066b9d1e2278.tar.xz
drakx-f383158b26368bc0b3d9f2fa59d8066b9d1e2278.zip
fix shadow password
-rw-r--r--move/data/etcfiles1
-rw-r--r--move/move.pm4
2 files changed, 3 insertions, 2 deletions
diff --git a/move/data/etcfiles b/move/data/etcfiles
index bb1223b4b..693d13a2d 100644
--- a/move/data/etcfiles
+++ b/move/data/etcfiles
@@ -14,6 +14,7 @@
# OVERWRITE files that will be overwritten
/etc/modules
+/etc/.pwd.lock
# DIR mandatory directories because files will be written in
/etc/profile.d
diff --git a/move/move.pm b/move/move.pm
index 4cad87821..2dc8779d6 100644
--- a/move/move.pm
+++ b/move/move.pm
@@ -53,7 +53,7 @@ sub init {
symlinkf "/proc/mounts", "/etc/mtab";
#- these files need be writable but we need a sensible first contents
- system("cp /image/etc/$_ /etc") foreach qw(passwd group sudoers fstab);
+ system("cp /image/etc/$_ /etc") foreach qw(passwd passwd- group sudoers fstab);
#- these files are typically opened in read-write mode, we need them copied
mkdir_p("/etc/$_"), system("cp -R /image/etc/$_/* /etc/$_")
@@ -67,7 +67,7 @@ sub init {
#- ro things
symlinkf_short("/image/etc/$_", "/etc/$_")
- foreach qw(alternatives shadow man.config services shells pam.d security inputrc ld.so.conf
+ foreach qw(alternatives man.config services shells pam.d security inputrc ld.so.conf
DIR_COLORS bashrc profile rc.d init.d devfsd.conf gtk-2.0 pango fonts modules.devfs
dynamic hotplug gnome-vfs-2.0 gnome-vfs-mime-magic gtk gconf menu menu-methods nsswitch.conf default login.defs
skel ld.so.cache openoffice xinetd.d xinetd.conf syslog.conf sysctl.conf sysconfig/networking/ifcfg-lo
a> 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
#!/usr/bin/perl -T
use strict;

########################################
# config files
$nfs_exports::default_options = '*(ro,all_squash,sync)';
$nfs_exports::conf_file = '/etc/exports';
$smb_exports::conf_file = '/etc/samba/smb.conf';
my $authorisation_file = '/etc/security/fileshare.conf';
my $authorisation_group = 'fileshare';


########################################
# fileshare utility $Id$
# Copyright (C) 2001-2005 Mandriva (pixel@mandrakesoft.com)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.


########################################
my $uid = $<;
my $username = getpwuid($uid);

########################################
# errors
my $usage =
"usage: fileshareset --add <dir>
       fileshareset --remove <dir>";
my $non_authorised =
qq(You are not authorised to use fileshare'ing
To grant you the rights:
- put "RESTRICT=no" in $authorisation_file
- or put user "$username" in group "$authorisation_group");
my $no_export_method = "can not export anything: no nfs, no smb";

my %exit_codes = reverse(
  1 => $non_authorised,
  2 => $usage,

# when adding
  3 => "already exported", 
  4 => "invalid mount point",

# when removing
  5 => "not exported",

  6 => $no_export_method,

  255 => "various",
);

################################################################################
# correct PATH needed to call /etc/init.d/... ? seems not, but...
%ENV = ();#(PATH => '/bin:/sbin:/usr/bin:/usr/sbin');

my $modify = $0 =~ /fileshareset/;

authorisation::check($modify);

my @exports = (
	       -e $nfs_exports::conf_file ? nfs_exports::read() : (),
	       -e $smb_exports::conf_file ? smb_exports::read() : (),
	      );
@exports or error($no_export_method);

if ($modify) {
    my ($cmd, $dir) = @ARGV;
    $< = $>;
    @ARGV == 2 && ($cmd eq '--add' || $cmd eq '--remove') or error($usage);

    verify_mntpoint($dir);

    if ($cmd eq '--add') {
	my @errs = map { eval { $_->add($dir) }; $@ } @exports;
	grep { !$_ } @errs or error("already exported");
    } else {
	my @errs = map { eval { $_->remove($dir) }; $@ } @exports;
	grep { !$_ } @errs or error("not exported");
    }    
    foreach my $export (@exports) {
	$export->write;
	$export->update_server;
    }
}
my @mntpoints = grep { $_ } uniq(map { map { $_->{mntpoint} } @$_ } @exports);
print "$_\n" foreach grep { own($_) } @mntpoints;


sub own { $uid == 0 || (stat($_[0]))[4] == $uid }

sub verify_mntpoint {
    local ($_) = @_;
    my $ok = 1;
    $ok &&= m|^/|;
    $ok &&= !m|\Q/../|;
    $ok &&= !m|[\0\n\r]|;
    $ok &&= -d $_;
    $ok &&= own($_);
    $ok or error("invalid mount point");
}

sub error {
    my ($string) = @_;
    print STDERR "$string\n";
    exit($exit_codes{$string} || 255);
}
sub member { my $e = shift; foreach (@_) { $e eq $_ and return 1 } 0 }
sub uniq { my %l; $l{$_} = 1 foreach @_; grep { delete $l{$_} } @_ }


################################################################################
package authorisation;

my $F_lock;
sub read_conf {
    my ($exclusive_lock) = @_;
    open $F_lock, $authorisation_file; # do not care if it's missing
    flock($F_lock, $exclusive_lock ? 2 : 1) or die "can not lock";
    my %conf;
    foreach (<$F_lock>) {
	s/#.*//; # remove comments
	s/^\s+//; 
	s/\s+$//;
	/^$/ and next;
	my ($cmd, $value) = split('=', $_, 2);
	$conf{$cmd} = $value || warn qq(suspicious line "$_" in $authorisation_file\n);
    }
    # no close $F_lock, keep it locked
    \%conf
}

sub check {
    my ($exclusive_lock) = @_;
    my $conf = read_conf($exclusive_lock);

    if (lc($conf->{RESTRICT}) eq 'no') {
	# ok, access granted for everybody
    } else {
	my @l;
	while (@l = getgrent) {
	    last if $l[0] eq $authorisation_group;
	}
	::member($username, split(' ', $l[3])) or ::error($non_authorised);
    }
}

################################################################################
package exports;

sub find {
    my ($exports, $mntpoint) = @_;
    foreach (@$exports) {
	$_->{mntpoint} eq $mntpoint and return $_;
    }
    undef;
}

sub add {
    my ($exports, $mntpoint) = @_;
    find($exports, $mntpoint) and die 'add';
    push @$exports, my $e = { mntpoint => $mntpoint };
    $e;
}

sub remove {
    my ($exports, $mntpoint) = @_;
    my @l = grep { $_->{mntpoint} ne $mntpoint } @$exports;
    @l < @$exports or die 'remove';
    @$exports = @l;  
}


################################################################################
package nfs_exports;

use vars qw(@ISA $conf_file $default_options);
BEGIN { @ISA = 'exports' }

sub read() {
    my $file = $conf_file;
    open(my $F, $file) or return [];

    my ($prev_raw, $prev_line, @l);
    my $line_nb = 0;
    foreach my $raw (<$F>) {
	$line_nb++;
	local $_ = $raw;
	$raw .= "\n" if !/\n/;

	s/#.*//; # remove comments

	s/^\s+//; 
	s/\s+$//; # remove unuseful spaces to help regexps

	if (/^$/) {
	    # blank lines ignored
	    $prev_raw .= $raw;
	    next;
	}

	if (/\\$/) {
	    # line continue across lines
	    chop; # remove the backslash
	    $prev_line .= "$_ ";
	    $prev_raw .= $raw;
	    next;
	}
	my $line = $prev_line . $_;
	my $raw_line = $prev_raw . $raw;
	($prev_line, $prev_raw) = ('', '');

	my ($mntpoint, $options) = $line =~ /("[^"]*"|\S+)\s+(.*)/ or die "$file:$line_nb: bad line $line\n";

	# You can also specify spaces or any other unusual characters in the
	# export path name using a backslash followed by the character code as
	# 3 octal digits.
	$mntpoint =~ s/\\(\d{3})/chr(oct $1)/ge;

	# not accepting weird characters that would break the output
	$mntpoint =~ m/[\0\n\r]/ and die "i will not handle this";
	push @l, { mntpoint => $mntpoint, option => $options, raw => $raw_line };
    }
    bless \@l, 'nfs_exports';
}

sub write {
    my ($nfs_exports) = @_;
    foreach (@$nfs_exports) {
	if (!exists $_->{options}) {
	    $_->{options} = $default_options;
	}
	if (!exists $_->{raw}) {	    
	    my $mntpoint = $_->{mntpoint} =~ /\s/ ? qq("$_->{mntpoint}") : $_->{mntpoint};
	    $_->{raw} = sprintf("%s %s\n", $mntpoint, $_->{options});
	}
    }
    open(my $F, ">$conf_file") or die "can not write $conf_file";
    print $F $_->{raw} foreach @$nfs_exports;
}

sub update_server() {
    if (fork()) {
	system('/usr/sbin/exportfs', '-r');
	if (system('/sbin/pidof rpc.mountd >/dev/null') != 0 ||
	    system('/sbin/pidof nfsd >/dev/null') != 0) {
	    # trying to start the server...
	    system('/etc/init.d/portmap start') if system('/etc/init.d/portmap status >/dev/null') != 0;
	    system('/etc/init.d/nfs', $_) foreach 'stop', 'start';
	}
	exit 0;
    }
}

################################################################################
package smb_exports;

use vars qw(@ISA $conf_file);
BEGIN { @ISA = 'exports' }

sub read() {
    my ($s, @l);
    open(my $F, $conf_file);
    local $_;
    while (<$F>) {
	if (/^\s*\[.*\]/ || eof $F) {
	    #- first line in the category
	    my ($label) = $s =~ /^\s*\[(.*)\]/;
	    my ($mntpoint) = $s =~ /^\s*path\s*=\s*(.*)/m;
	    push @l, { mntpoint => $mntpoint, raw => $s, label => $label };
	    $s = '';
	}
	$s .= $_;
    }
    bless \@l, 'smb_exports';
}

sub write {
    my ($smb_exports) = @_;
    foreach (@$smb_exports) {
	if (!exists $_->{raw}) {
	    $_->{raw} = <<EOF;

[$_->{label}]
   path = $_->{mntpoint}
   comment = $_->{mntpoint}
   public = yes
   guest ok = yes
   writable = no
   wide links = no
EOF
	}
    }
    open(my $F, ">$conf_file") or die "can not write $conf_file";
    print $F $_->{raw} foreach @$smb_exports;
}

sub add {
    my ($exports, $mntpoint) = @_;
    my $e = $exports->exports::add($mntpoint);
    $e->{label} = name_mangle($mntpoint, map { $_->{label} } @$exports);
}

sub name_mangle {
    my ($input, @others) = @_;

    local $_ = $input;

    # 1. first only keep legal characters. "/" is also kept for the moment
    tr|a-z|A-Z|;
    s|[^A-Z0-9#\-_!/]|_|g; # "$" is allowed except at the end, remove it in any case
    
    # 2. removing non-interesting parts
    s|^/||;
    s|^home/||;
    s|_*/_*|/|g;
    s|_+|_|g;

    # 3. if size is too small (!), make it bigger
    $_ .= "_" while length($_) < 3;

    # 4. if size is too big, shorten it
    while (length > 12) {
	my ($s) = m|.*?/(.*)|;
	if (length($s) > 8 && !grep { /\Q$s/ } @others) {
	    # dropping leading directories when the resulting is still long and meaningful
	    $_ = $s;
	} else {
	    s|(.*)[0-9#\-_!/]|$1|
	      # inspired by "Christian Brolin" "Long names are doom" on comp.lang.functional
	      || s|(.+)[AEIOU]|$1|# allButFirstVowels
	      || s|(.*)(.)\2|$1$2| # adjacentDuplicates
	      || s|(.*).|$1|; # booh, :'-(
	}
    }

    # 5. remove "/"s still there
    s|/|_|g;

    # 6. resolving conflicts
    my $l = join("|", map { quotemeta } @others);
    my $conflicts = qr|^($l)$|;
    if (/$conflicts/) {
      A: while (1) {
	    for (my $nb = 1; length("$_$nb") <= 12; $nb++) {
		if ("$_$nb" !~ /$conflicts/) {
		    $_ = "$_$nb";
		    last A;
		}
	    }
	    $_ or die "can not find a unique name";
	    # can not find a unique name, dropping the last letter
	    s|(.*).|$1|;
	}
    }

    # 7. done
    $_;
}

sub update_server() {
    if (fork()) {
	system('/usr/bin/killall -HUP smbd 2>/dev/null');
	if (system('/sbin/pidof smbd >/dev/null') != 0 ||
	    system('/sbin/pidof nmbd >/dev/null') != 0) {
	    # trying to start the server...
	    system('/etc/init.d/smb', $_) foreach 'stop', 'start';
	}
	exit 0;
    }
}