#! /usr/bin/perl # **** License **** # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. # # 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. # # This code was originally developed by Vyatta, Inc. # Portions created by Vyatta are Copyright (C) 2008 Vyatta, Inc. # All Rights Reserved. # **** End License **** use lib "/opt/vyatta/share/perl5/"; use Vyatta::Config; use strict; use Getopt::Long; my ( $resync, $verbose, $force, $check ); GetOptions( "verbose" => \$verbose, "resync" => \$resync, "force" => \$force, "check" => \$check, ); # NOTE: the directory manipulations were changed to simply using "my_set" # and "my_delete" since the new CLI library no longer expose the # filesystem directories/paths. this should provide the same # functionality as the original script, so the original limitations # still apply: # 1. the script is supposed to be run manually in config mode. # 2. when necessary (given the configurations and options), the # script adds/modifies users in the "working config" (errors # not checked). # 3. after running this script, a "commit" will need to be issued # before any changes will take effect. sub set_user_attr { my $user = shift; system('/opt/vyatta/sbin/my_set', 'system', 'login', 'user', $user, @_); } sub del_user { my $user = shift; system('/opt/vyatta/sbin/my_delete', 'system', 'login', 'user', $user); } my $members; ( undef, undef, undef, $members ) = getgrnam('operator'); my @operators = split(/ /, $members ); ( undef, undef, undef, $members ) = getgrnam('vyattacfg'); my @admins = split(/ /, $members ); sub get_user_level { my $name = shift; return 'admin' if ( $name eq 'root' ); foreach my $id (@admins) { return 'admin' if ( $id eq $name ); } foreach my $id (@operators) { return 'operator' if ( $id eq $name ); } # If level indetermined returns undef } my @field_names = ( 'encrypted password', 'full name', 'home directory', 'level' ); sub system_vyatta_users { my %users = (); setpwent(); while ( my ( $name, $passwd, $uid, $gid, undef, $comment, undef, $home, $shell ) = getpwent() ) { if ( $name eq 'root' || $shell eq '/bin/vbash' ) { $users{$name} = [ $passwd, $comment, $home, get_user_level($name) ]; } } endpwent(); return %users; } sub listOrigUsers { my $config = new Vyatta::Config; my %users = (); foreach my $name ( $config->listOrigNodes('system login user') ) { $config->setLevel("system login user $name"); my $passwd = $config->returnOrigValue('authentication encrypted-password'); my $comment = $config->returnOrigValue('full-name'); my $home = $config->returnOrigValue('home-directory'); my $level = $config->returnOrigValue('level'); $level = 'admin' if ( !defined $level ); $users{$name} = [ $passwd, $comment, $home, $level ]; } return %users; } sub check_config { my %pwdusers = system_vyatta_users(); my %vtyusers = listOrigUsers(); my $exit_code = 0; if ($verbose) { printf "System users: %s\n", join( ', ', keys %pwdusers ); printf "Configured users: %s\n", join( ', ', keys %vtyusers ); } while ( my ( $user, $fields ) = each(%vtyusers) ) { my @pwd_fields = @{ $pwdusers{$user} }; my @cfg_fields = @$fields; if (@pwd_fields) { for ( my $i = 0 ; $i <= $#pwd_fields ; $i++ ) { if ( $pwd_fields[$i] ne $cfg_fields[$i] ) { printf "%s: %s mismatch: '%s' != '%s'\n", $user, $field_names[$i], $pwd_fields[$i], $cfg_fields[$i]; $exit_code = 1; } } delete $pwdusers{$user}; } else { print "$user: does not exist in system\n"; $exit_code = 1; } } foreach my $user ( keys %pwdusers ) { print "$user: does not exist in vyatta configuration\n"; $exit_code = 1; } exit $exit_code; } sub listUsers { my $config = new Vyatta::Config; my %users = (); foreach my $name ( $config->listOrigNodes('system login user') ) { $config->setLevel("system login user $name"); my $passwd = $config->returnOrigValue('authentication encrypted-password'); my $comment = $config->returnOrigValue('full-name'); my $home = $config->returnOrigValue('home-directory'); my $level = $config->returnOrigValue('level'); $level = 'admin' if ( !defined $level ); $users{$name} = [ $passwd, $comment, $home, $level ]; } return %users; } sub resync_config { my %system_users = system_vyatta_users(); my %vyatta_users = listUsers(); my $config = new Vyatta::Config; $config->setLevel('system login user'); foreach my $user ( keys %vyatta_users ) { if ( !defined $system_users{$user} ) { if ($force) { print "Deleting user: $user\n" if ($verbose); del_user($user); } else { print "user: $user does not exist in passwd file\n"; } } } foreach my $user ( keys %system_users ) { my ( $passwd, $comment, $home, $level ) = @{ $system_users{$user} }; if ( !defined $level ) { print "user $user: could not determine level (incorrect groups)\n"; next; } my $existing = $vyatta_users{$user}; if ( !defined $existing ) { if ($force) { print "Adding $user\n" if ($verbose); # user will be added in later "set" operations. } else { print "user: $user does not exist in vyatta config\n"; next; } } else { my ( $opasswd, $ocomment, $ohome, $olevel ) = @{$existing}; if ( $opasswd eq $passwd && $ocomment eq $comment && $ohome eq $home && $olevel eq $level ) { print "$user: no change\n" if ($verbose); next; } else { print "$user: fields don't match\n" if ($verbose); } } if ( $comment ne '' ) { set_user_attr($user, 'full-name', $comment); } set_user_attr($user, 'authentication', 'encrypted-password', $passwd); set_user_attr($user, 'level', $level); set_user_attr($user, 'home-directory', $home); } } if ($check) { check_config(); exit 0; } if ($resync) { resync_config(); exit 0; } print <