4 # Copyright (c) 1999 Jason Gunthorpe <jgg@debian.org>
5 # Copyright (c) 2003 James Troup <troup@debian.org>
6 # Copyright (c) 2004 Joey Schulze <joey@debian.org>
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, write to the Free Software
20 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 # Imports passwd, shadow and group files into the directory.
23 # You should cleanse the files of anything you do not want to add to the
26 # The first step is to call this script to import the passwd file and
27 # create all the new entries. This should be done on an empty freshly
28 # initialized directory with the rootdn/password set in the server.
29 # The command to execute is
30 # ldapimport -a -p ~/passwd
31 # The -a tells the script to add all the entries it finds, it should be
34 # The next step is to import the shadow file and group, no clensing need be
36 # this as any entries that do not exist will be ignored (silently)
37 # ldapimport -s /etc/shadow -g /etc/group
40 import string, re, time, ldap, getopt, sys;
41 from userdir_ldap import *;
49 # This parses a gecos field and returns a tuple containing the new normalized
50 # field and the first, middle and last name of the user. Gecos is formed
51 # in the standard debian manner with 5 feilds seperated by commas
52 def ParseGecos(Field):
53 Gecos = re.split("[,:]",Field);
58 (cn,mn,sn) = NameSplit(Gecos[0]);
60 # Normalize the gecos field
64 while (len(Gecos) < 5):
67 Gecos = ["","","","",""];
69 # Reconstruct the gecos after mauling it
70 Field = Gecos[0] + "," + Gecos[1] + "," + Gecos[2] + "," + \
71 Gecos[3] + "," + Gecos[4];
72 return (Field,cn,mn,sn);
74 # Check if a number string is really a number
77 string.index(string.digits,x);
79 # Read the passwd file into the database
80 def DoPasswd(l,Passwd):
81 # Read the passwd file and import it
82 Passwd = open(Passwd,"r");
85 Line = Passwd.readline();
89 Split = re.split("[:\n]",Line);
90 (Split[4],cn,mn,sn) = ParseGecos(Split[4]);
91 CheckNumber(Split[2]);
92 CheckNumber(Split[3]);
93 Rec = [(ldap.MOD_REPLACE,"uid",Split[0]),
94 (ldap.MOD_REPLACE,"uidNumber",Split[2]),
95 (ldap.MOD_REPLACE,"gidNumber",Split[3]),
96 (ldap.MOD_REPLACE,"gecos",Split[4]),
97 (ldap.MOD_REPLACE,"homeDirectory",Split[5]),
98 (ldap.MOD_REPLACE,"loginShell",Split[6]),
99 (ldap.MOD_REPLACE,"cn",cn),
100 (ldap.MOD_REPLACE,"mn",mn),
101 (ldap.MOD_REPLACE,"sn",sn)];
103 Dn = "uid=" + Split[0] + "," + BaseDn;
104 print "Importing",Dn,
107 # Unfortunately add_s does not take the same args as modify :|
110 l.add_s(Dn,[("uid",Split[0]),
111 ("objectClass","top"),
112 ("objectClass","account"),
113 ("objectClass","posixAccount"),
114 ("objectClass","shadowAccount"),
115 ("objectClass","debiandeveloper")]);
116 except ldap.ALREADY_EXISTS:
119 # Send the modify request
121 Outstanding = Outstanding + 1;
122 Outstanding = FlushOutstanding(l,Outstanding,1);
124 FlushOutstanding(l,Outstanding);
126 # Read the shadow file into the database
127 def DoShadow(l,Shadow):
128 # Read the passwd file and import it
129 Shadow = open(Shadow,"r");
132 Line = Shadow.readline();
136 Split = re.split("[:\n]",Line);
138 # Ignore system accounts with no password, they do not belong in the
140 if (Split[1] == 'x' or Split[1] == '*'):
141 print "Ignoring system account,",Split[0];
145 CheckNumber(Split[x]);
147 Rec = [(ldap.MOD_REPLACE,"shadowLastChange",Split[2]),
148 (ldap.MOD_REPLACE,"shadowMin",Split[3]),
149 (ldap.MOD_REPLACE,"shadowMax",Split[4]),
150 (ldap.MOD_REPLACE,"shadowWarning",Split[5]),
151 (ldap.MOD_REPLACE,"shadowInactive",Split[6]),
152 (ldap.MOD_REPLACE,"shadowExpire",Split[7])];
153 if (WritePasses == 1):
154 Rec.append((ldap.MOD_REPLACE,"userPassword","{crypt}"+Split[1]));
156 Dn = "uid=" + Split[0] + "," + BaseDn;
157 print "Importing",Dn,
160 # Send the modify request
162 Outstanding = Outstanding + 1;
164 Outstanding = FlushOutstanding(l,Outstanding,1);
165 FlushOutstanding(l,Outstanding);
167 # Read the group file into the database
168 def DoGroup(l,Group):
169 # Read the passwd file and import it
170 Group = open(Group,"r");
173 Line = Group.readline();
177 # Split up the group information
178 Split = re.split("[:\n]",Line);
179 Members = re.split("[, ]*",Split[3]);
180 CheckNumber(Split[2]);
182 # Iterate over the membership list and add the membership information
184 Rec = [(ldap.MOD_ADD,"supplementaryGid",Split[0])];
190 Dn = "uid=" + x + "," + BaseDn;
191 print "Adding",Dn,"to group",Split[0];
194 # Send the modify request
196 Outstanding = Outstanding + 1;
197 Outstanding = FlushOutstanding(l,Outstanding,1);
202 Rec = [(ldap.MOD_REPLACE,"gid",Split[0]),
203 (ldap.MOD_REPLACE,"gidNumber",Split[2])];
205 Dn = "gid=" + Split[0] + "," + BaseDn;
206 print "Importing",Dn,
209 # Unfortunately add_s does not take the same args as modify :|
212 l.add_s(Dn,[("gid",Split[0]),
213 ("objectClass","top"),
214 ("objectClass","posixGroup")]);
215 except ldap.ALREADY_EXISTS:
218 # Send the modify request
220 Outstanding = Outstanding + 1;
223 FlushOutstanding(l,Outstanding);
226 (options, arguments) = getopt.getopt(sys.argv[1:], "ap:s:g:xu:")
227 for (switch, val) in options:
232 elif (switch == '-p'):
234 elif (switch == '-s'):
236 elif (switch == '-g'):
238 elif (switch == '-u'):
241 # Main program starts here
243 # Connect to the ldap server
244 l = passwdAccessLDAP(LDAPServer, BaseDn, AdminUser)