Add a --random-password option to user create command.
[Samba/id10ts.git] / source4 / scripting / python / samba / netcmd / user.py
blob78e09fd3242b211002f04aeeb2a2b57ca6ead743
1 #!/usr/bin/env python
3 # user management
5 # Copyright Jelmer Vernooij 2010 <jelmer@samba.org>
6 # Copyright Theresa Halloran 2011 <theresahalloran@gmail.com>
7 # Copyright Giampaolo Lauria 2011 <lauria2@yahoo.com>
9 # This program is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 3 of the License, or
12 # (at your option) any later version.
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with this program. If not, see <http://www.gnu.org/licenses/>.
23 import samba.getopt as options
24 import sys, ldb
25 from getpass import getpass
26 from samba.auth import system_session
27 from samba.samdb import SamDB
28 from samba import gensec, generate_random_password
29 from samba.net import Net
31 from samba.netcmd import (
32 Command,
33 CommandError,
34 SuperCommand,
35 Option,
39 class cmd_user_create(Command):
40 """Creates a new user
42 This command creates a new user account in the Active Directory domain. The username specified on the command is the sAMaccountName.
44 User accounts may represent physical entities, such as people or may be used as service accounts for applications. User accounts are also referred to as security principals and are assigned a security identifier (SID).
46 A user account enables a user to logon to a computer and domain with an identity that can be authenticated. To maximize security, each user should have their own unique user account and password. A user's access to domain resources is based on permissions assigned to the user account.
48 The command may be run from the root userid or another authorized userid. The -H or --URL= option can be used to execute the command against a remote server.
50 Example1:
51 samba-tool user add User1 passw0rd --given-name=John --surname=Smith --must-change-at-next-login -H ldap://samba.samdom.example.com -Uadministrator%passw1rd
53 Example1 shows how to create a new user in the domain against a remote LDAP server. The -H parameter is used to specify the remote target server. The -U option is used to pass the userid and password authorized to issue the command remotely.
55 Example2:
56 sudo samba-tool user add User2 passw2rd --given-name=Jane --surname=Doe --must-change-at-next-login
58 Example2 shows how to create a new user in the domain against the local server. sudo is used so a user may run the command as root. In this example, after User2 is created, he/she will be forced to change their password when they logon.
60 Example3:
61 samba-tool user add User3 passw3rd --userou=OrgUnit
63 Example3 shows how to create a new user in the OrgUnit organizational unit.
65 """
66 synopsis = "%prog <username> [<password>] [options]"
68 takes_options = [
69 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
70 metavar="URL", dest="H"),
71 Option("--must-change-at-next-login",
72 help="Force password to be changed on next login",
73 action="store_true"),
74 Option("--random-password",
75 help="Generate random password",
76 action="store_true"),
77 Option("--use-username-as-cn",
78 help="Force use of username as user's CN",
79 action="store_true"),
80 Option("--userou",
81 help="Alternative location (without domainDN counterpart) to default CN=Users in which new user object will be created",
82 type=str),
83 Option("--surname", help="User's surname", type=str),
84 Option("--given-name", help="User's given name", type=str),
85 Option("--initials", help="User's initials", type=str),
86 Option("--profile-path", help="User's profile path", type=str),
87 Option("--script-path", help="User's logon script path", type=str),
88 Option("--home-drive", help="User's home drive letter", type=str),
89 Option("--home-directory", help="User's home directory path", type=str),
90 Option("--job-title", help="User's job title", type=str),
91 Option("--department", help="User's department", type=str),
92 Option("--company", help="User's company", type=str),
93 Option("--description", help="User's description", type=str),
94 Option("--mail-address", help="User's email address", type=str),
95 Option("--internet-address", help="User's home page", type=str),
96 Option("--telephone-number", help="User's phone number", type=str),
97 Option("--physical-delivery-office", help="User's office location", type=str),
100 takes_args = ["username", "password?"]
102 def run(self, username, password=None, credopts=None, sambaopts=None,
103 versionopts=None, H=None, must_change_at_next_login=None, random_password=False,
104 use_username_as_cn=None, userou=None, surname=None, given_name=None, initials=None,
105 profile_path=None, script_path=None, home_drive=None, home_directory=None,
106 job_title=None, department=None, company=None, description=None,
107 mail_address=None, internet_address=None, telephone_number=None, physical_delivery_office=None):
109 if random_password is not False:
110 password = generate_random_password(128, 255)
112 while 1:
113 if password is not None and password is not '':
114 break
115 password = getpass("New Password: ")
117 lp = sambaopts.get_loadparm()
118 creds = credopts.get_credentials(lp)
120 try:
121 samdb = SamDB(url=H, session_info=system_session(),
122 credentials=creds, lp=lp)
123 samdb.newuser(username, password,
124 force_password_change_at_next_login_req=must_change_at_next_login,
125 useusernameascn=use_username_as_cn, userou=userou, surname=surname, givenname=given_name, initials=initials,
126 profilepath=profile_path, homedrive=home_drive, scriptpath=script_path, homedirectory=home_directory,
127 jobtitle=job_title, department=department, company=company, description=description,
128 mailaddress=mail_address, internetaddress=internet_address,
129 telephonenumber=telephone_number, physicaldeliveryoffice=physical_delivery_office)
130 except Exception, e:
131 raise CommandError("Failed to add user '%s': " % username, e)
133 self.outf.write("User '%s' created successfully\n" % username)
136 class cmd_user_add(cmd_user_create):
137 __doc__ = cmd_user_create.__doc__
138 # take this print out after the add subcommand is removed.
139 # the add subcommand is deprecated but left in for now to allow people to migrate to create
141 def run(self, *args, **kwargs):
142 self.err.write("\nNote: samba-tool user add is deprecated. Please use samba-tool user create for the same function.\n")
143 return super(self, cmd_user_add).run(*args, **kwargs)
146 class cmd_user_delete(Command):
147 """Deletes a user
149 This command deletes a user account from the Active Directory domain. The username specified on the command is the sAMAccountName.
151 Once the account is deleted, all permissions and memberships associated with that account are deleted. If a new user account is added with the same name as a previously deleted account name, the new user does not have the previous permissions. The new account user will be assigned a new security identifier (SID) and permissions and memberships will have to be added.
153 The command may be run from the root userid or another authorized userid. The -H or --URL= option can be used to execute the command against a remote server.
155 Example1:
156 samba-tool user delete User1 -H ldap://samba.samdom.example.com --username=administrator --password=passw1rd
158 Example1 shows how to delete a user in the domain against a remote LDAP server. The -H parameter is used to specify the remote target server. The --username= and --password= options are used to pass the username and password of a user that exists on the remote server and is authorized to issue the command on that server.
160 Example2:
161 sudo samba-tool user delete User2
163 Example2 shows how to delete a user in the domain against the local server. sudo is used so a user may run the command as root.
166 synopsis = "%prog <username> [options]"
168 takes_options = [
169 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
170 metavar="URL", dest="H"),
173 takes_args = ["username"]
175 def run(self, username, credopts=None, sambaopts=None, versionopts=None, H=None):
177 lp = sambaopts.get_loadparm()
178 creds = credopts.get_credentials(lp, fallback_machine=True)
180 try:
181 samdb = SamDB(url=H, session_info=system_session(),
182 credentials=creds, lp=lp)
183 samdb.deleteuser(username)
184 except Exception, e:
185 raise CommandError('Failed to remove user "%s"' % username, e)
186 self.outf.write("Deleted user %s\n" % username)
189 class cmd_user_enable(Command):
190 """Enables a user
192 This command enables a user account for logon to an Active Directory domain. The username specified on the command is the sAMAccountName. The username may also be specified using the --filter option.
194 There are many reasons why an account may become disabled. These include:
195 - If a user exceeds the account policy for logon attempts
196 - If an administrator disables the account
197 - If the account expires
199 The samba-tool user enable command allows an administrator to enable an account which has become disabled.
201 Additionally, the enable function allows an administrator to have a set of created user accounts defined and setup with default permissions that can be easily enabled for use.
203 The command may be run from the root userid or another authorized userid. The -H or --URL= option can be used to execute the command against a remote server.
205 Example1:
206 samba-tool user enable Testuser1 --URL=ldap://samba.samdom.example.com --username=administrator --password=passw1rd
208 Example1 shows how to enable a user in the domain against a remote LDAP server. The --URL parameter is used to specify the remote target server. The --username= and --password= options are used to pass the username and password of a user that exists on the remote server and is authorized to update that server.
210 Exampl2:
211 su samba-tool user enable Testuser2
213 Example2 shows how to enable user Testuser2 for use in the domain on the local server. sudo is used so a user may run the command as root.
215 Example3:
216 samba-tool user enable --filter=samaccountname=Testuser3
218 Example3 shows how to enable a user in the domain against a local LDAP server. It uses the --filter=samaccountname to specify the username.
221 synopsis = "%prog (<username>|--filter <filter>) [options]"
223 takes_options = [
224 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
225 metavar="URL", dest="H"),
226 Option("--filter", help="LDAP Filter to set password on", type=str),
229 takes_args = ["username?"]
231 def run(self, username=None, sambaopts=None, credopts=None,
232 versionopts=None, filter=None, H=None):
233 if username is None and filter is None:
234 raise CommandError("Either the username or '--filter' must be specified!")
236 if filter is None:
237 filter = "(&(objectClass=user)(sAMAccountName=%s))" % (ldb.binary_encode(username))
239 lp = sambaopts.get_loadparm()
240 creds = credopts.get_credentials(lp, fallback_machine=True)
242 samdb = SamDB(url=H, session_info=system_session(),
243 credentials=creds, lp=lp)
244 try:
245 samdb.enable_account(filter)
246 except Exception, msg:
247 raise CommandError("Failed to enable user '%s': %s" % (username or filter, msg))
248 self.outf.write("Enabled user '%s'\n" % (username or filter))
251 class cmd_user_setexpiry(Command):
252 """Sets the expiration of a user account
254 This command sets the expiration of a user account. The username specified on the command is the sAMAccountName. The username may also be specified using the --filter option.
256 When a user account expires, it becomes disabled and the user is unable to logon. The administrator may issue the samba-tool user enable command to enable the account for logon. The permissions and memberships associated with the account are retained when the account is enabled.
258 The command may be run from the root userid or another authorized userid. The -H or --URL= option can be used to execute the command on a remote server.
260 Example1:
261 samba-tool user setexpiry User1 --days=20 --URL=ldap://samba.samdom.example.com --username=administrator --password=passw1rd
263 Example1 shows how to set the expiration of an account in a remote LDAP server. The --URL parameter is used to specify the remote target server. The --username= and --password= options are used to pass the username and password of a user that exists on the remote server and is authorized to update that server.
265 Exampl2:
266 su samba-tool user setexpiry User2
268 Example2 shows how to set the account expiration of user User2 so it will never expire. The user in this example resides on the local server. sudo is used so a user may run the command as root.
270 Example3:
271 samba-tool user setexpiry --days=20 --filter=samaccountname=User3
273 Example3 shows how to set the account expiration date to end of day 20 days from the current day. The username or sAMAccountName is specified using the --filter= paramter and the username in this example is User3.
275 Example4:
276 samba-tool user setexpiry --noexpiry User4
277 Example4 shows how to set the account expiration so that it will never expire. The username and sAMAccountName in this example is User4.
280 synopsis = "%prog (<username>|--filter <filter>) [options]"
282 takes_options = [
283 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
284 metavar="URL", dest="H"),
285 Option("--filter", help="LDAP Filter to set password on", type=str),
286 Option("--days", help="Days to expiry", type=int, default=0),
287 Option("--noexpiry", help="Password does never expire", action="store_true", default=False),
290 takes_args = ["username?"]
292 def run(self, username=None, sambaopts=None, credopts=None,
293 versionopts=None, H=None, filter=None, days=None, noexpiry=None):
294 if username is None and filter is None:
295 raise CommandError("Either the username or '--filter' must be specified!")
297 if filter is None:
298 filter = "(&(objectClass=user)(sAMAccountName=%s))" % (ldb.binary_encode(username))
300 lp = sambaopts.get_loadparm()
301 creds = credopts.get_credentials(lp)
303 samdb = SamDB(url=H, session_info=system_session(),
304 credentials=creds, lp=lp)
306 try:
307 samdb.setexpiry(filter, days*24*3600, no_expiry_req=noexpiry)
308 except Exception, msg:
309 # FIXME: Catch more specific exception
310 raise CommandError("Failed to set expiry for user '%s': %s" % (
311 username or filter, msg))
312 self.outf.write("Set expiry for user '%s' to %u days\n" % (
313 username or filter, days))
316 class cmd_user_password(Command):
317 """Change password for a user account (the one provided in authentication)
323 synopsis = "%prog [options]"
325 takes_options = [
326 Option("--newpassword", help="New password", type=str),
329 def run(self, credopts=None, sambaopts=None, versionopts=None,
330 newpassword=None):
332 lp = sambaopts.get_loadparm()
333 creds = credopts.get_credentials(lp)
335 # get old password now, to get the password prompts in the right order
336 old_password = creds.get_password()
338 net = Net(creds, lp, server=credopts.ipaddress)
340 password = newpassword
341 while 1:
342 if password is not None and password is not '':
343 break
344 password = getpass("New Password: ")
346 try:
347 net.change_password(password)
348 except Exception, msg:
349 # FIXME: catch more specific exception
350 raise CommandError("Failed to change password : %s" % msg)
351 self.outf.write("Changed password OK\n")
354 class cmd_user_setpassword(Command):
355 """Sets or resets the password of a user account
357 This command sets or resets the logon password for a user account. The username specified on the command is the sAMAccountName. The username may also be specified using the --filter option.
359 If the password is not specified on the command through the --newpassword parameter, the user is prompted for the password to be entered through the command line.
361 It is good security practice for the administrator to use the --must-change-at-next-login option which requires that when the user logs on to the account for the first time following the password change, he/she must change the password.
363 The command may be run from the root userid or another authorized userid. The -H or --URL= option can be used to execute the command against a remote server.
365 Example1:
366 samba-tool user setpassword TestUser1 passw0rd --URL=ldap://samba.samdom.example.com -Uadministrator%passw1rd
368 Example1 shows how to set the password of user TestUser1 on a remote LDAP server. The --URL parameter is used to specify the remote target server. The -U option is used to pass the username and password of a user that exists on the remote server and is authorized to update the server.
370 Example2:
371 sudo samba-tool user setpassword TestUser2 passw0rd --must-change-at-next-login
373 Example2 shows how an administrator would reset the TestUser2 user's password to passw0rd. The user is running under the root userid using the sudo command. In this example the user TestUser2 must change their password the next time they logon to the account.
375 Example3:
376 samba-tool user setpassword --filter=samaccountname=TestUser3 --password=passw0rd
378 Example3 shows how an administrator would reset TestUser3 user's password to passw0rd using the --filter= option to specify the username.
381 synopsis = "%prog (<username>|--filter <filter>) [options]"
383 takes_options = [
384 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
385 metavar="URL", dest="H"),
386 Option("--filter", help="LDAP Filter to set password on", type=str),
387 Option("--newpassword", help="Set password", type=str),
388 Option("--must-change-at-next-login",
389 help="Force password to be changed on next login",
390 action="store_true"),
391 Option("--random-password",
392 help="Generate random password",
393 action="store_true"),
396 takes_args = ["username?"]
398 def run(self, username=None, filter=None, credopts=None, sambaopts=None,
399 versionopts=None, H=None, newpassword=None,
400 must_change_at_next_login=None, random_password=False):
401 if filter is None and username is None:
402 raise CommandError("Either the username or '--filter' must be specified!")
404 if random_password is not False:
405 password = generate_random_password(128, 255)
406 else:
407 password = newpassword
408 while 1:
409 if password is not None and password is not '':
410 break
411 password = getpass("New Password: ")
413 if filter is None:
414 filter = "(&(objectClass=user)(sAMAccountName=%s))" % (ldb.binary_encode(username))
416 lp = sambaopts.get_loadparm()
417 creds = credopts.get_credentials(lp)
419 creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL)
421 samdb = SamDB(url=H, session_info=system_session(),
422 credentials=creds, lp=lp)
424 try:
425 samdb.setpassword(filter, password,
426 force_change_at_next_login=must_change_at_next_login,
427 username=username)
428 except Exception, msg:
429 # FIXME: catch more specific exception
430 raise CommandError("Failed to set password for user '%s': %s" % (username or filter, msg))
431 self.outf.write("Changed password OK\n")
434 class cmd_user(SuperCommand):
435 """User management"""
437 subcommands = {}
438 subcommands["add"] = cmd_user_create()
439 subcommands["create"] = cmd_user_create()
440 subcommands["delete"] = cmd_user_delete()
441 subcommands["enable"] = cmd_user_enable()
442 subcommands["setexpiry"] = cmd_user_setexpiry()
443 subcommands["password"] = cmd_user_password()
444 subcommands["setpassword"] = cmd_user_setpassword()