4 Add a user to to the uid/maintainer/fingerprint table and
5 add his key to the GPGKeyring
7 @contact: Debian FTP Master <ftpmaster@debian.org>
8 @copyright: 2004, 2009 Joerg Jaspert <joerg@ganneff.de>
9 @license: GNU General Public License version 2 or later
12 ################################################################################
13 # <elmo> wow, sounds like it'll be a big step up.. configuring dak on a
14 # new machine even scares me :)
15 ################################################################################
17 # You don't want to read this script if you know python.
18 # I know what I say. I dont know python and I wrote it. So go and read some other stuff.
28 from daklib import daklog
29 from daklib import utils
30 from daklib.dbconn import DBConn, add_database_user, get_or_set_uid
31 from daklib.regexes import re_gpg_fingerprint, re_user_address, re_user_mails, re_user_name
33 ################################################################################
40 ################################################################################
42 def usage(exit_code=0):
43 print """Usage: add-user [OPTION]...
44 Adds a new user to the dak databases and keyrings
46 -k, --key keyid of the User
47 -u, --user userid of the User
48 -c, --create create a system account for the user
49 -h, --help show this help and exit."""
52 ################################################################################
53 # Stolen from userdir-ldap
54 # Compute a random password using /dev/urandom.
56 # Generate a 10 character random string
57 SaltVals = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/."
58 Rand = open("/dev/urandom")
61 Password = Password + SaltVals[ord(Rand.read(1)[0]) % len(SaltVals)]
64 # Compute the MD5 crypted version of the given password
65 def HashPass(Password):
67 # Hash it telling glibc to use the MD5 algorithm - if you dont have
68 # glibc then just change Salt = "$1$" to Salt = ""
69 SaltVals = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/."
71 Rand = open("/dev/urandom")
73 Salt = Salt + SaltVals[ord(Rand.read(1)[0]) % len(SaltVals)]
74 Pass = crypt.crypt(Password,Salt)
76 raise "Password Error", "MD5 password hashing failed, not changing the password!"
79 ################################################################################
81 def createMail(login, passwd, keyid, keyring):
86 Additionally there is now an account created for you.
89 message+= "\nYour password for the login %s is: %s\n" % (login, passwd)
91 gnupg = GnuPGInterface.GnuPG()
92 gnupg.options.armor = 1
93 gnupg.options.meta_interactive = 0
94 gnupg.options.extra_args.append("--no-default-keyring")
95 gnupg.options.extra_args.append("--always-trust")
96 gnupg.options.extra_args.append("--no-secmem-warning")
97 gnupg.options.extra_args.append("--keyring=%s" % keyring)
98 gnupg.options.recipients = [keyid]
99 proc = gnupg.run(['--encrypt'], create_fhs=['stdin', 'stdout'])
100 proc.handles['stdin'].write(message)
101 proc.handles['stdin'].close()
102 output = proc.handles['stdout'].read()
103 proc.handles['stdout'].close()
107 ################################################################################
113 Cnf = utils.get_conf()
115 Arguments = [('h',"help","Add-User::Options::Help"),
116 ('c',"create","Add-User::Options::Create"),
117 ('k',"key","Add-User::Options::Key", "HasArg"),
118 ('u',"user","Add-User::Options::User", "HasArg"),
121 for i in [ "help", "create" ]:
122 if not Cnf.has_key("Add-User::Options::%s" % (i)):
123 Cnf["Add-User::Options::%s" % (i)] = ""
125 apt_pkg.ParseCommandLine(Cnf, Arguments, sys.argv)
127 Options = Cnf.SubTree("Add-User::Options")
131 session = DBConn().session()
134 keyrings = Cnf.ValueList("Dinstall::GPGKeyring")
136 # Ignore the PGP keyring for download of new keys. Ignore errors, if key is missing it will
137 # barf with the next commands.
138 cmd = "gpg --no-secmem-warning --no-default-keyring %s --recv-keys %s" \
139 % (utils.gpg_keyring_args(keyrings), Cnf["Add-User::Options::Key"])
140 (result, output) = commands.getstatusoutput(cmd)
142 cmd = "gpg --with-colons --no-secmem-warning --no-auto-check-trustdb --no-default-keyring %s --with-fingerprint --list-key %s" \
143 % (utils.gpg_keyring_args(keyrings),
144 Cnf["Add-User::Options::Key"])
145 (result, output) = commands.getstatusoutput(cmd)
146 m = re_gpg_fingerprint.search(output)
149 utils.fubar("0x%s: (1) No fingerprint found in gpg output but it returned 0?\n%s" \
150 % (Cnf["Add-User::Options::Key"], utils.prefix_multi_line_string(output, \
152 primary_key = m.group(1)
153 primary_key = primary_key.replace(" ","")
156 if Cnf.has_key("Add-User::Options::User") and Cnf["Add-User::Options::User"]:
157 uid = Cnf["Add-User::Options::User"]
158 name = Cnf["Add-User::Options::User"]
160 u = re_user_address.search(output)
163 utils.fubar("0x%s: (2) No userid found in gpg output but it returned 0?\n%s" \
164 % (Cnf["Add-User::Options::Key"], utils.prefix_multi_line_string(output, " [GPG output:] ")))
166 n = re_user_name.search(output)
169 # Look for all email addresses on the key.
171 for line in output.split('\n'):
172 e = re_user_mails.search(line)
175 emails.append(e.group(2))
178 print "0x%s -> %s <%s> -> %s -> %s" % (Cnf["Add-User::Options::Key"], name, emails[0], uid, primary_key)
180 prompt = "Add user %s with above data (y/N) ? " % (uid)
181 yn = utils.our_raw_input(prompt).lower()
184 # Create an account for the user?
186 if Cnf.FindB("Add-User::CreateAccount") or Cnf["Add-User::Options::Create"]:
188 pwcrypt = HashPass(password)
189 if Cnf.has_key("Add-User::GID"):
190 cmd = "sudo /usr/sbin/useradd -g users -m -p '%s' -c '%s' -G %s %s" \
191 % (pwcrypt, name, Cnf["Add-User::GID"], uid)
193 cmd = "sudo /usr/sbin/useradd -g users -m -p '%s' -c '%s' %s" \
194 % (pwcrypt, name, uid)
195 (result, output) = commands.getstatusoutput(cmd)
197 utils.fubar("Invocation of '%s' failed:\n%s\n" % (cmd, output), result)
199 summary+=createMail(uid, password, Cnf["Add-User::Options::Key"], Cnf["Dinstall::GPGKeyring"])
202 utils.warn("Could not prepare password information for mail, not sending password.")
204 # Now add user to the database.
205 # Note that we provide a session, so we're responsible for committing
206 uidobj = get_or_set_uid(uid, session=session)
207 uid_id = uidobj.uid_id
208 add_database_user(uid)
210 # The following two are kicked out in rhona, so we don't set them. kelly adds
211 # them as soon as she installs a package with unknown ones, so no problems to expect here.
212 # Just leave the comment in, to not think about "Why the hell aren't they added" in
213 # a year, if we ever touch uma again.
214 # maint_id = database.get_or_set_maintainer_id(name)
215 # session.execute("INSERT INTO fingerprint (fingerprint, uid) VALUES (:fingerprint, uid)",
216 # {'fingerprint': primary_key, 'uid': uid_id})
218 # Lets add user to the email-whitelist file if its configured.
219 if Cnf.has_key("Dinstall::MailWhiteList") and Cnf["Dinstall::MailWhiteList"] != "":
220 file = utils.open_file(Cnf["Dinstall::MailWhiteList"], "a")
222 file.write(mail+'\n')
225 print "Added:\nUid:\t %s (ID: %s)\nMaint:\t %s\nFP:\t %s" % (uid, uid_id, \
228 # Should we send mail to the newly added user?
229 if Cnf.FindB("Add-User::SendEmail"):
230 mail = name + "<" + emails[0] +">"
232 Subst["__NEW_MAINTAINER__"] = mail
233 Subst["__UID__"] = uid
234 Subst["__KEYID__"] = Cnf["Add-User::Options::Key"]
235 Subst["__PRIMARY_KEY__"] = primary_key
236 Subst["__FROM_ADDRESS__"] = Cnf["Dinstall::MyEmailAddress"]
237 Subst["__HOSTNAME__"] = Cnf["Dinstall::MyHost"]
238 Subst["__SUMMARY__"] = summary
239 new_add_message = utils.TemplateSubst(Subst,Cnf["Dir::Templates"]+"/add-user.added")
240 utils.send_mail(new_add_message)
246 #######################################################################################
248 if __name__ == '__main__':