Hrvatska akademska i istraživačka mreža
  NASLOVNICA MAPA WEBA TRAŽILICA KONTAKTI CARNET WEB
Hrvatska akademska i istraživačka mreža
 
menu 4
Sigurnost
menu 4
Distribucija
menu 4
Pomoć
menu 4
Dokumenti
menu 4
menu 4

 

 

10-02-04 09:56
Kako prebaciti korisnike iz LDAP imenika u (obrisan) /etc/passw

piše ŽELJA BOROŠ

Problem:

 

Podaci o korisničkim računima su obrisani. Backup traka je zakazala, odnosno sadržava nešto starije podatke. Velika većina korisničkih direktorija se i dalje nalazi na disku (ili su vraćeni s trake), obrisani su "samo" korisnički passwordi i grupe.

 

Što treba učiniti:

 

Vratiti korisnicima mogućnost prijave na sustav, čitanja pošte te spajanja na CMU. Pri tom je nužno očuvati korisničke UID-ove kako ne bi došlo do problema s pravima pristupa na /home direktorije i problema s korisničkim webovima u ~/public_html. Uključiti i postaviti kvote korisnicima.

 

Rješenje:

 

Kako je postojala recentna kopija dumpa LDAP baze (LDIF datoteka), bilo je moguće vratiti korisnike i njihove zaporke na sustav pisanjem skripte u perlu. Skripta je potrebna jer bi ručno dodavanja korisnika bilo nepraktično. Perl je odabran zbog fleksibilnosti i brzine.

 

Naknadno uočeni problemi:

 

Nisu svi korisnici na sustavu uneseni u LDAP, dok neki korisnici koji postoje u LDAP-u ne postoje na sustavu (nemaju /home direktorij). Prvi slučaj se može riješiti uvidom u "papirnatu" evidenciju i ručnim dodavanjem imena i prezimena (nakon rekreiranja /etc/passwd datoteke) naredbom 'usermod'.

 

Drugi slučaj se može riješiti skriptom, uz napomenu da takvi korisnici nužno dobivaju drugi UID (jer nemaju /home direktorij pa prema tome ni sačuvan UID). U ovom slučaju očuvanje UID-a ni nije prioritet, jer je sasvim svejedno koji će UID korisnik dobiti.

 

Postupak:

 

Iz LDIF se datoteke perl skriptom 'users_rescue.pl' izvlače podaci o korisnicima (ime, prezime, uid). Kako bi ova skripta pravilno radila, potrebno je kreirati dvije datoteke: 'uids.txt' i 'usernames.base64' (imena su proizvoljna, ali treba izmijeniti source perl skripte u slučaju promjene).

 

U prvoj datoteci ("uids.txt") se nalaze dva stupca: u prvom korisnički uid, u drugom username. U drugoj datoteci ("usernames.base64") se nalaze "izgrepani" samo potrebni podaci iz LDIF datoteke (kako bi perl kod bio što jednostavniji). Datoteke je najlakše kreirati naredbama:

 

ls -l /home | awk '{print $3, $9}' > uids.txt

egrep '(cn:|uid:)' < organization.ldif > usernames.base64

 

Nakon toga samo treba pokrenuti skriptu 'users_rescue.pl' koja će generirati

ispis u /etc/passwd formatu sa svim korisnicima koji imaju uid na sustavu a

ujedno se nalaze u LDAP-u. Skripta brine o imenima korisnika koji sadržavaju

dijakritičke znakove, te ih konvertira u oblik bez "kvačica".

 

Izlaz naredbe 'users_rescue.pl' preporučljivo je preusmjeriti u privremenu datoteku te ručno "zalijepiti" na /etc/passwd, pazeći da se ne preklapaju uid brojevi postojećih (sustavskih) i novih (korisničkih) računa.

 

Iako je pripremljena i skripta 'pass_rescue.pl' koja ima zadatak kreirati izlaz u formatu /etc/shadow datoteke, ona nije upotrijebljena.

 

Razlog je slaba podrška za SHA (Secure Hash Algorithm) način "hashiranja"

zaporki kao načina autentificiranja na Linuxu (a nikakva na Solarisu). Iz tog razloga (kao i što bržeg rješenja problema), išlo se na direktnu autentifikaciju preko PAM LDAP modula. Ovo je zapravo prednost, jer korisnik sad ima samo jednu zaporku za sve: e-mail, CMU, shell pristup itd.

 

Kako Linux ima složeniju strukturu PAM-a (svaki servis ima svoju datoteku, za razliku od Solarisa koji rabi samo jednu, /etc/pam.conf), kreirana je skripta 'pam-fix.sh' koja automatski pravi nužne promjene u PAM konfiguracijskim datotekama. Naravno, predviđeno je kreiranje pričuvnih

kopija datoteka u /etc/pam.d direktoriju (imaju dodatak .orig).

 

U datoteku /etc/nsswitch.conf još treba dodati (izmijeniti) redak

 

passwd: compat

 

u

 

passwd: ldap compat

 

Korisnici se u LDAP dodaju preko standardne 'ldapmodify' naredbe (postoji

"kuharica" na webu: http://cmung.cmu.carnet.hr).

 

Vjerojatno se navedeno moglo i elegantnije izvesti, ali bitan ograničavajući

čimbenik je bilo vrijeme, kako bi korisnici što prije mogli početi rabiti e-mail i CMU sustav, kao i ažurirati vlastite web stranice.

 

NAPOMENA: Prije svih operacija potrebno je napraviti backup svih datoteka

koje se mijenjaju: /etc/passwd, /etc/shadow itd. Skripte ne moraju nužno odmah proraditi kod vas, jer su pisane za specifične potrebe. No, u slučaju potrebe, s lakoćom se mogu modificirati jer su pisane u perlu.

 

DISCLAIMER: Sve navedene skripte i upute koristite na vlastitu odgovornost!

 

------------

# pam-fix.sh

# Author: zelja@zelja.com Wed, 4 Feb 2004 22:43:15 +0100

# Script adjusts PAM files so that every service tries to authenticate

# against LDAP first. Failing that, it tries previous configuration.

# Script makes backup files, but make your own backup first.

# Use at your own risk!

set -e

 

cd /etc/pam.d

perl -pi.orig -e 's/^(.*)(required)(.*pam_unix.*so.*)$/#$1$2$3\n$1sufficient$3\n$1required\tpam_ldap.so\n/g;' $1

 

----------

# users_rescue.pl

#!/usr/bin/perl

# Author: zelja@zelja.com Wed, 4 Feb 2004 22:43:15 +0100

# Script recreates /etc/passwd from LDIF file, preserving UIDs found on system

# Create $base64 file with:

# egrep '(cn:|uid:)' < organization.ldif > usernames.base64

# Create $uids file with:

# ls -l /home | awk '{print $3, $9}' > uids.txt

# DO backup before running this script.

# Use at your own risk!

 

# Numerical value of 'users' group on linux. Modify according to your system.

$defgid = "100";

$uids = "uids.txt";

$base64 = "usernames.base64";

$pisi = 0;

%UIDS = ();

%USERNAMES = ();

 

# read uids in field UIDS

open(UIDS, "<$uids") or die "No \'$uids\' file!";

while (<UIDS>) {

chomp ($_);

($uid, $username) = split;

$UIDS{$username} = $uid;

$USERNAMES{$uid} = $username;

}

close UIDS;

undef $uid, $username;

 

# read uids and names from ldif

open (B64, "<$base64") or die "No \'$base64\' file!";

while (<B64>) {

chomp ($_);

($what, $value) = split(/: /);

$name = $value;

 

next unless ($what eq "uid" || $what =~ "cn:");

 

# if $what looks like 'cn::' don't decode

if ($what eq "cn::") {

$decoded = $name;

}

elsif ($what eq "cn:")

{

use MIME::Base64;

$decoded = decode_base64($name);

$decoded =~ s/�/c/g; #meko ch

$decoded =~ s/�/c/g; #ch

$decoded =~ s/�/dj/g; #dj

$decoded =~ s/�/C/g; #meko CH

$decoded =~ s/�/C/g; #CH

$decoded =~ s/Ĺ /S/g; #SH

$decoded =~ s/Ĺž/z/g; #zh

$decoded =~ s/ĹĄ/s/g; #sh

$decoded =~ s/�/Dj/g; #DJ

$decoded =~ s/Ĺ˝/Z/g; #ZH

$decoded =~ s/ĂŚ/c/g; #meko ch 2

$decoded =~ s/Ăź/ue/g; #u s prijeglasom

}

 

 

# read only users found in 'uids.txt' file

if (($what eq "uid") && ($UIDS{$value} ne "")) {

$line = "$value:x:";

$line .= "$UIDS{$value}\:";

$line .= "$defgid:";

$line .= "$decoded\:";

$line .= "/home/$name:/bin/bash";

print "$line\n";

undef $line;

}

}

 

exit 0;

 

 

------------

# pass_rescue.pl

#!/usr/bin/perl

# Author: zelja@zelja.com Wed, 4 Feb 2004 22:43:15 +0100

# Script tries to recreate /etc/shadow from LDIF file

# Create $base64 file with:

# egrep '(cn:|uid:)' < organization.ldif > usernames.base64

# DO backup before running this script.

# Use at your own risk! This script is not tested in production!

 

use MIME::Base64;

$ldif = "organization.ldif";

$base64 = "usernames.base64";

 

%USERS = ();

%PASS = ();

 

open(USERS, "<$ldif") or die "No \'$ldif\' file!";

while (<USERS>) {

if (/uid:/) {

chomp ($_);

($dummy, $user) = split;

$USERS{$user} = decode_base64($pass);

# 12400 = number of days between epoch and last pass change

print "$user:$USERS{$user}:12400::::::\n";

} elsif (/userPassword:/) {

($dummy, $pass) = split;

}

 

}

 

exit 0;

 

# THE REST IS JUST AN EXAMPLE, MODIFY IF NEEDED (AND REMOVE exit 0;

open (B64, "<$base64");

while (<B64>) {

chomp ($_);

($prvi, $ime) = split(/: /);

 

if ($prvi eq "uid") {

$username = $ime;

undef $ime;

$line = "$username:x:";

if ($UIDS{$username} eq "") {

$line .= "NOUID\:";

} else {

$line .= "$UIDS{$username}\:";

}

$line .= "100:";

next;

}

 

if ($prvi ne "cn:") { $decoded = $ime; goto OUT; }

 

use MIME::Base64;

$decoded = decode_base64($ime);

$decoded =~ s/�/c/g; #meko ch

$decoded =~ s/�/c/g; #ch

$decoded =~ s/�/dj/g; #dj

$decoded =~ s/�/C/g; #meko CH

$decoded =~ s/�/C/g; #CH

$decoded =~ s/Ĺ /S/g; #SH

$decoded =~ s/Ĺž/z/g; #zh

$decoded =~ s/ĹĄ/s/g; #sh

$decoded =~ s/�/Dj/g; #DJ

$decoded =~ s/Ĺ˝/Z/g; #ZH

 

$decoded =~ s/ĂŚ/c/g; #meko ch 2

$decoded =~ s/Ăź/ue/g; #u s prijeglasom

 

OUT:

#print "uid=$uid, $UIDOVI{$username}, $UIDS{$username}, $username\n";

$line .= "$decoded\:";

$line .= "/home/$username:/bin/bash";

print "$line\n";

 

}

 





[Lista]
Ovu uslugu CARNeta realizira Sveučilišni računski centar Sveučilišta u Zagrebu
  Copyright ©2005. CARNet. Sva prava zadržana. Impressum.
Mail to
sys-portal@CARNet.hr