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
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 import dsdb
30 from samba.net import Net
32 from samba.netcmd import (
40 class cmd_user_create(Command):
43 This command creates a new user account in the Active Directory domain. The username specified on the command is the sAMaccountName.
45 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).
47 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.
49 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.
52 samba-tool user add User1 passw0rd --given-name=John --surname=Smith --must-change-at-next-login -H ldap://samba.samdom.example.com -Uadministrator%passw1rd
54 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.
57 sudo samba-tool user add User2 passw2rd --given-name=Jane --surname=Doe --must-change-at-next-login
59 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.
62 samba-tool user add User3 passw3rd --userou=OrgUnit
64 Example3 shows how to create a new user in the OrgUnit organizational unit.
67 synopsis = "%prog <username> [<password>] [options]"
70 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
71 metavar="URL", dest="H"),
72 Option("--must-change-at-next-login",
73 help="Force password to be changed on next login",
75 Option("--random-password",
76 help="Generate random password",
78 Option("--use-username-as-cn",
79 help="Force use of username as user's CN",
82 help="Alternative location (without domainDN counterpart) to default CN=Users in which new user object will be created",
84 Option("--surname", help="User's surname", type=str),
85 Option("--given-name", help="User's given name", type=str),
86 Option("--initials", help="User's initials", type=str),
87 Option("--profile-path", help="User's profile path", type=str),
88 Option("--script-path", help="User's logon script path", type=str),
89 Option("--home-drive", help="User's home drive letter", type=str),
90 Option("--home-directory", help="User's home directory path", type=str),
91 Option("--job-title", help="User's job title", type=str),
92 Option("--department", help="User's department", type=str),
93 Option("--company", help="User's company", type=str),
94 Option("--description", help="User's description", type=str),
95 Option("--mail-address", help="User's email address", type=str),
96 Option("--internet-address", help="User's home page", type=str),
97 Option("--telephone-number", help="User's phone number", type=str),
98 Option("--physical-delivery-office", help="User's office location", type=str),
101 takes_args = ["username", "password?"]
103 def run(self, username, password=None, credopts=None, sambaopts=None,
104 versionopts=None, H=None, must_change_at_next_login=False, random_password=False,
105 use_username_as_cn=False, userou=None, surname=None, given_name=None, initials=None,
106 profile_path=None, script_path=None, home_drive=None, home_directory=None,
107 job_title=None, department=None, company=None, description=None,
108 mail_address=None, internet_address=None, telephone_number=None, physical_delivery_office=None):
111 password = generate_random_password(128, 255)
114 if password is not None and password is not '':
116 password = getpass("New Password: ")
118 lp = sambaopts.get_loadparm()
119 creds = credopts.get_credentials(lp)
122 samdb = SamDB(url=H, session_info=system_session(),
123 credentials=creds, lp=lp)
124 samdb.newuser(username, password,
125 force_password_change_at_next_login_req=must_change_at_next_login,
126 useusernameascn=use_username_as_cn, userou=userou, surname=surname, givenname=given_name, initials=initials,
127 profilepath=profile_path, homedrive=home_drive, scriptpath=script_path, homedirectory=home_directory,
128 jobtitle=job_title, department=department, company=company, description=description,
129 mailaddress=mail_address, internetaddress=internet_address,
130 telephonenumber=telephone_number, physicaldeliveryoffice=physical_delivery_office)
132 raise CommandError("Failed to add user '%s': " % username, e)
134 self.outf.write("User '%s' created successfully\n" % username)
137 class cmd_user_add(cmd_user_create):
138 __doc__ = cmd_user_create.__doc__
139 # take this print out after the add subcommand is removed.
140 # the add subcommand is deprecated but left in for now to allow people to migrate to create
142 def run(self, *args, **kwargs):
143 self.err.write("\nNote: samba-tool user add is deprecated. Please use samba-tool user create for the same function.\n")
144 return super(self, cmd_user_add).run(*args, **kwargs)
147 class cmd_user_delete(Command):
150 This command deletes a user account from the Active Directory domain. The username specified on the command is the sAMAccountName.
152 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.
154 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.
157 samba-tool user delete User1 -H ldap://samba.samdom.example.com --username=administrator --password=passw1rd
159 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.
162 sudo samba-tool user delete User2
164 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.
167 synopsis = "%prog <username> [options]"
170 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
171 metavar="URL", dest="H"),
174 takes_args = ["username"]
176 def run(self, username, credopts=None, sambaopts=None, versionopts=None, H=None):
178 lp = sambaopts.get_loadparm()
179 creds = credopts.get_credentials(lp, fallback_machine=True)
182 samdb = SamDB(url=H, session_info=system_session(),
183 credentials=creds, lp=lp)
184 samdb.deleteuser(username)
186 raise CommandError('Failed to remove user "%s"' % username, e)
187 self.outf.write("Deleted user %s\n" % username)
190 class cmd_user_list(Command):
193 synopsis = "%prog [options]"
196 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
197 metavar="URL", dest="H"),
200 def run(self, sambaopts=None, credopts=None, versionopts=None, H=None):
201 lp = sambaopts.get_loadparm()
202 creds = credopts.get_credentials(lp, fallback_machine=True)
204 samdb = SamDB(url=H, session_info=system_session(),
205 credentials=creds, lp=lp)
207 domain_dn = samdb.domain_dn()
208 res = samdb.search(domain_dn, scope=ldb.SCOPE_SUBTREE,
209 expression=("(&(objectClass=user)(userAccountControl:%s:=%u))"
210 % (ldb.OID_COMPARATOR_AND, dsdb.UF_NORMAL_ACCOUNT)),
217 self.outf.write("%s\n" % msg["name"][0])
218 except Exception, msg:
219 raise CommandError("Failed to get user list: %s" % msg)
222 class cmd_user_enable(Command):
225 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.
227 There are many reasons why an account may become disabled. These include:
228 - If a user exceeds the account policy for logon attempts
229 - If an administrator disables the account
230 - If the account expires
232 The samba-tool user enable command allows an administrator to enable an account which has become disabled.
234 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.
236 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.
239 samba-tool user enable Testuser1 --URL=ldap://samba.samdom.example.com --username=administrator --password=passw1rd
241 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.
244 su samba-tool user enable Testuser2
246 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.
249 samba-tool user enable --filter=samaccountname=Testuser3
251 Example3 shows how to enable a user in the domain against a local LDAP server. It uses the --filter=samaccountname to specify the username.
254 synopsis = "%prog (<username>|--filter <filter>) [options]"
257 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
258 metavar="URL", dest="H"),
259 Option("--filter", help="LDAP Filter to set password on", type=str),
262 takes_args = ["username?"]
264 def run(self, username=None, sambaopts=None, credopts=None,
265 versionopts=None, filter=None, H=None):
266 if username is None and filter is None:
267 raise CommandError("Either the username or '--filter' must be specified!")
270 filter = "(&(objectClass=user)(sAMAccountName=%s))" % (ldb.binary_encode(username))
272 lp = sambaopts.get_loadparm()
273 creds = credopts.get_credentials(lp, fallback_machine=True)
275 samdb = SamDB(url=H, session_info=system_session(),
276 credentials=creds, lp=lp)
278 samdb.enable_account(filter)
279 except Exception, msg:
280 raise CommandError("Failed to enable user '%s': %s" % (username or filter, msg))
281 self.outf.write("Enabled user '%s'\n" % (username or filter))
284 class cmd_user_disable(Command):
287 synopsis = "%prog (<username>|--filter <filter>) [options]"
290 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
291 metavar="URL", dest="H"),
292 Option("--filter", help="LDAP Filter to set password on", type=str),
295 takes_args = ["username?"]
297 def run(self, username=None, sambaopts=None, credopts=None,
298 versionopts=None, filter=None, H=None):
299 if username is None and filter is None:
300 raise CommandError("Either the username or '--filter' must be specified!")
303 filter = "(&(objectClass=user)(sAMAccountName=%s))" % (ldb.binary_encode(username))
305 lp = sambaopts.get_loadparm()
306 creds = credopts.get_credentials(lp, fallback_machine=True)
308 samdb = SamDB(url=H, session_info=system_session(),
309 credentials=creds, lp=lp)
311 samdb.disable_account(filter)
312 except Exception, msg:
313 raise CommandError("Failed to disable user '%s': %s" % (username or filter, msg))
316 class cmd_user_setexpiry(Command):
317 """Sets the expiration of a user account
319 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.
321 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.
323 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.
326 samba-tool user setexpiry User1 --days=20 --URL=ldap://samba.samdom.example.com --username=administrator --password=passw1rd
328 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.
331 su samba-tool user setexpiry User2
333 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.
336 samba-tool user setexpiry --days=20 --filter=samaccountname=User3
338 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.
341 samba-tool user setexpiry --noexpiry User4
342 Example4 shows how to set the account expiration so that it will never expire. The username and sAMAccountName in this example is User4.
345 synopsis = "%prog (<username>|--filter <filter>) [options]"
348 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
349 metavar="URL", dest="H"),
350 Option("--filter", help="LDAP Filter to set password on", type=str),
351 Option("--days", help="Days to expiry", type=int, default=0),
352 Option("--noexpiry", help="Password does never expire", action="store_true", default=False),
355 takes_args = ["username?"]
357 def run(self, username=None, sambaopts=None, credopts=None,
358 versionopts=None, H=None, filter=None, days=None, noexpiry=None):
359 if username is None and filter is None:
360 raise CommandError("Either the username or '--filter' must be specified!")
363 filter = "(&(objectClass=user)(sAMAccountName=%s))" % (ldb.binary_encode(username))
365 lp = sambaopts.get_loadparm()
366 creds = credopts.get_credentials(lp)
368 samdb = SamDB(url=H, session_info=system_session(),
369 credentials=creds, lp=lp)
372 samdb.setexpiry(filter, days*24*3600, no_expiry_req=noexpiry)
373 except Exception, msg:
374 # FIXME: Catch more specific exception
375 raise CommandError("Failed to set expiry for user '%s': %s" % (
376 username or filter, msg))
377 self.outf.write("Set expiry for user '%s' to %u days\n" % (
378 username or filter, days))
381 class cmd_user_password(Command):
382 """Change password for a user account (the one provided in authentication)
388 synopsis = "%prog [options]"
391 Option("--newpassword", help="New password", type=str),
394 def run(self, credopts=None, sambaopts=None, versionopts=None,
397 lp = sambaopts.get_loadparm()
398 creds = credopts.get_credentials(lp)
400 # get old password now, to get the password prompts in the right order
401 old_password = creds.get_password()
403 net = Net(creds, lp, server=credopts.ipaddress)
405 password = newpassword
407 if password is not None and password is not '':
409 password = getpass("New Password: ")
412 net.change_password(password)
413 except Exception, msg:
414 # FIXME: catch more specific exception
415 raise CommandError("Failed to change password : %s" % msg)
416 self.outf.write("Changed password OK\n")
419 class cmd_user_setpassword(Command):
420 """Sets or resets the password of a user account
422 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.
424 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.
426 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.
428 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.
431 samba-tool user setpassword TestUser1 passw0rd --URL=ldap://samba.samdom.example.com -Uadministrator%passw1rd
433 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.
436 sudo samba-tool user setpassword TestUser2 passw0rd --must-change-at-next-login
438 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.
441 samba-tool user setpassword --filter=samaccountname=TestUser3 --password=passw0rd
443 Example3 shows how an administrator would reset TestUser3 user's password to passw0rd using the --filter= option to specify the username.
446 synopsis = "%prog (<username>|--filter <filter>) [options]"
449 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
450 metavar="URL", dest="H"),
451 Option("--filter", help="LDAP Filter to set password on", type=str),
452 Option("--newpassword", help="Set password", type=str),
453 Option("--must-change-at-next-login",
454 help="Force password to be changed on next login",
455 action="store_true"),
456 Option("--random-password",
457 help="Generate random password",
458 action="store_true"),
461 takes_args = ["username?"]
463 def run(self, username=None, filter=None, credopts=None, sambaopts=None,
464 versionopts=None, H=None, newpassword=None,
465 must_change_at_next_login=False, random_password=False):
466 if filter is None and username is None:
467 raise CommandError("Either the username or '--filter' must be specified!")
470 password = generate_random_password(128, 255)
472 password = newpassword
475 if password is not None and password is not '':
477 password = getpass("New Password: ")
480 filter = "(&(objectClass=user)(sAMAccountName=%s))" % (ldb.binary_encode(username))
482 lp = sambaopts.get_loadparm()
483 creds = credopts.get_credentials(lp)
485 creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL)
487 samdb = SamDB(url=H, session_info=system_session(),
488 credentials=creds, lp=lp)
491 samdb.setpassword(filter, password,
492 force_change_at_next_login=must_change_at_next_login,
494 except Exception, msg:
495 # FIXME: catch more specific exception
496 raise CommandError("Failed to set password for user '%s': %s" % (username or filter, msg))
497 self.outf.write("Changed password OK\n")
500 class cmd_user(SuperCommand):
501 """User management"""
504 subcommands["add"] = cmd_user_create()
505 subcommands["create"] = cmd_user_create()
506 subcommands["delete"] = cmd_user_delete()
507 subcommands["disable"] = cmd_user_disable()
508 subcommands["enable"] = cmd_user_enable()
509 subcommands["list"] = cmd_user_list()
510 subcommands["setexpiry"] = cmd_user_setexpiry()
511 subcommands["password"] = cmd_user_password()
512 subcommands["setpassword"] = cmd_user_setpassword()