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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
#!/usr/bin/perl -w
#
#
# Comments on usage from the email we received:
# I showed a friend the following script. He said I should submit it for
# inclusion in openldap, because it might useful for others.
#
# The attached perl script, when used like
#
# ldapsearch | ldiftopasswd
#
# will automatically:
#
# 1. create /etc/passwd, /etc/shadow, /etc/group, and /etc/gshadow
#
# 2. append /etc/passwd.top, /etc/shadow.top, /etc/group.top, and /etc/gshadow.top to respective files.
#
# 3. use data from ldap to create the files (note: gshadow isn't really
# supported, because I don't use it, nor could I find any
# documentation. Adding support for other files should be easy).
#
# (of course you need access to all fields including the password field
# for this, so use correct parameters to ldapsearch).
#
# This could be useful for instance on laptop computers where you don't
# want to run a slave slapd server for some reason (perhaps memory
# constraints).
# ----------------------------------------
use strict;
use Getopt::Long;
use MIME::Base64;
use IO::File;
my $passwdfile="/etc/passwd";
my $shadowfile="/etc/shadow";
my $groupfile="/etc/group";
my $gshadowfile="/etc/gshadow";
my $help;
GetOptions (
'--passwd=s',\$passwdfile,
'--shadow=s',\$shadowfile,
'--group=s',\$groupfile,
'--gshadow=s',\$gshadowfile,
'--help',\$help,
) or die "Bad options\n";
if ($help or $#ARGV != -1) {
print STDERR "usage: $0 [etcfile=filename] [--help]\n";
exit 255;
}
sub start_file($) {
my ($file) = @_;
my $outhandle = new IO::File;
$outhandle->open(">$file") or die "Cannot open $file for writing";
open(TMP,"<$file.top") or die "cannot open $file.top for reading";
while (<TMP>) { $outhandle->print($_); }
close(TMP) or die "cannot close $file for reading";
return($outhandle);
}
my $PASSWD = start_file($passwdfile);
my $SHADOW = start_file($shadowfile);
my $GROUP = start_file($groupfile);
my $GSHADOW = start_file($gshadowfile);
sub dopasswd($) {
my ($record) = @_;
my $userPassword="*";
$PASSWD->print(
$record->{"uid"},":",
"x",":",
$record->{"uidNumber"},":",
$record->{"gidNumber"},":",
$record->{"gecos"},":",
$record->{"homeDirectory"},":",
$record->{"loginShell"},"\n");
if (defined($record->{"userPassword"}) &&
$record->{"userPassword"} =~ /^{(crypt)}(.*)$/)
{ $userPassword = $2; }
$SHADOW->print(
$record->{"uid"},":",
$userPassword,":",
$record->{"shadowLastChange"} || "10706",":",
$record->{"shadowMin"} || "0",":",
$record->{"shadowMax"} || "99999",":",
$record->{"shadowWarning"} || "7",":",
$record->{"shadowInactive"} || "",":",
$record->{"shadowExpire"} || "",":",
"","\n");
}
sub dogroup($) {
my ($record) = @_;
my $userPassword="*";
my $members="";
if (defined($record->{"memberUid"})) {
$members = join(",",@{$record->{"memberUid"}});
}
$GROUP->print(
$record->{"cn"},":",
"x",":",
$record->{"gidNumber"},":",
$members,"\n");
if (defined($record->{"userPassword"}) &&
$record->{"userPassword"} =~ /^{(crypt)}(.*)$/)
{ $userPassword = $2; }
# !FIXME!
# $GSHADOW->print
# $record->{"cn"},":",
# "*",":",
# "",":",
# "","\n";
}
my %record;
my $user=0;
my $group=0;
while (<>) {
if (/^$/) {
if ($user) {
dopasswd(\%record);
}
if ($group) {
dogroup(\%record);
}
$user = $group = 0;
%record=();
}
elsif (/^objectClass: posixAccount$/) {
$user = 1;
}
elsif (/^objectClass: posixGroup$/) {
$group = 1;
}
elsif (/^(uid|uidNumber|gidNumber|gecos|homeDirectory|loginShell): (.*)$/) {
if (!defined($record{$1})) { $record{$1} = $2; }
}
elsif (/^(userPassword|shadowLastChange|shadowMin|shadowMax|shadowWarning|shadowInactive|shadowExpire): (.*)$/) {
if (!defined($record{$1})) { $record{$1} = $2; }
}
elsif (/^(cn): (.*)$/) {
if (!defined($record{$1})) { $record{$1} = $2; }
}
elsif (/^(uniqueMember): (.*)$/) {
push @{$record{$1}},$2;
if ($2 =~ /uid=([a-zA-Z]*),/) {
push @{$record{"memberUid"}},$1;
}
}
elsif (/^(memberUid): (.*)$/) {
push @{$record{$1}},$2;
}
elsif (/^(userPassword):: (.*)$/) {
$record{$1} = decode_base64($2);
}
}
$PASSWD->close or die "Cannot close $passwdfile for writing";
$SHADOW->close or die "Cannot close $shadowfile for writing";
$GROUP->close or die "Cannot close $groupfile for writing";
$GSHADOW->close or die "Cannot close $gshadowfile for writing";
|