3 # Sets password settings (Password complexity, history length,
4 # minimum password length, the minimum and maximum password age) on a
7 # Copyright Jelmer Vernooij 2008
8 # Copyright Matthias Dieter Wallnoefer 2009
9 # Released under the GNU GPL version 3 or later
13 sys.path.insert(0, os.path.join(os.path.dirname(sys.argv[0]), "../bin/python"))
15 import samba.getopt as options
20 from samba.auth import system_session
21 from samba.samdb import SamDB
22 from samba.dcerpc.samr import DOMAIN_PASSWORD_COMPLEX
24 parser = optparse.OptionParser("pwsettings (show | set <options>)")
25 sambaopts = options.SambaOptions(parser)
26 parser.add_option_group(sambaopts)
27 parser.add_option_group(options.VersionOptions(parser))
28 credopts = options.CredentialsOptions(parser)
29 parser.add_option_group(credopts)
30 parser.add_option("-H", help="LDB URL for database or target server", type=str)
31 parser.add_option("--complexity",
32 help="The password complexity (on | off). Default is 'on'", type=str)
33 parser.add_option("--history-length",
34 help="The password history length (<integer> | default)", type=str)
35 parser.add_option("--min-pwd-length",
36 help="The minimum password length (<integer> | default)", type=str)
37 parser.add_option("--min-pwd-age",
38 help="The minimum password age (<integer in days> | default)", type=str)
39 parser.add_option("--max-pwd-age",
40 help="The maximum password age (<integer in days> | default)", type=str)
42 opts, args = parser.parse_args()
45 # print a message if quiet is not set
55 lp = sambaopts.get_loadparm()
57 creds = credopts.get_credentials(lp)
59 if opts.H is not None:
62 url = lp.get("sam database")
64 samdb = SamDB(url=url, session_info=system_session(),
65 credentials=creds, lp=lp)
67 res = samdb.search("", scope=ldb.SCOPE_BASE,
68 expression="(defaultNamingContext=*)",
69 attrs=["defaultNamingContext"])
70 assert(len(res) == 1 and res[0]["defaultNamingContext"] is not None)
71 domain_dn = res[0]["defaultNamingContext"][0]
73 res = samdb.search(domain_dn, scope=ldb.SCOPE_BASE, attrs=["pwdProperties",
74 "pwdHistoryLength", "minPwdLength", "minPwdAge", "maxPwdAge"])
77 pwd_props = int(res[0]["pwdProperties"][0])
78 pwd_hist_len = int(res[0]["pwdHistoryLength"][0])
79 min_pwd_len = int(res[0]["minPwdLength"][0])
81 min_pwd_age = int(abs(int(res[0]["minPwdAge"][0])) / (10e7 * 60 * 60 * 24))
82 max_pwd_age = int(abs(int(res[0]["maxPwdAge"][0])) / (10e7 * 60 * 60 * 24))
85 print "ERROR: Password informations missing in your AD domain object!"
86 print "So no settings can be displayed!"
91 print "WARNING: Assuming previous password properties 0 (used for password complexity setting)"
94 print "Password informations for domain '" + domain_dn + "'"
96 if pwd_props & DOMAIN_PASSWORD_COMPLEX != 0:
97 print "Password complexity: on"
99 print "Password complexity: off"
100 print "Password history length: " + str(pwd_hist_len)
101 print "Minimum password length: " + str(min_pwd_len)
102 print "Minimum password age (days): " + str(min_pwd_age)
103 print "Maximum password age (days): " + str(max_pwd_age)
105 elif args[0] == "set":
106 if opts.complexity is not None:
107 if opts.complexity == "on":
108 pwd_props = pwd_props | DOMAIN_PASSWORD_COMPLEX
111 m.dn = ldb.Dn(samdb, domain_dn)
112 m["pwdProperties"] = ldb.MessageElement([],
113 ldb.CHANGETYPE_DELETE, "pwdProperties")
115 m["pwdProperties"] = ldb.MessageElement(str(pwd_props),
116 ldb.CHANGETYPE_ADD, "pwdProperties")
118 print "Password complexity activated!"
119 elif opts.complexity == "off":
120 pwd_props = pwd_props & (~DOMAIN_PASSWORD_COMPLEX)
123 m.dn = ldb.Dn(samdb, domain_dn)
124 m["pwdProperties"] = ldb.MessageElement([],
125 ldb.CHANGETYPE_DELETE, "pwdProperties")
127 m["pwdProperties"] = ldb.MessageElement(str(pwd_props),
128 ldb.CHANGETYPE_ADD, "pwdProperties")
130 print "Password complexity deactivated!"
132 print "ERROR: Wrong argument '" + opts.complexity + "'!"
135 if opts.history_length is not None:
136 if opts.history_length == "default":
139 pwd_hist_len = int(opts.history_length)
142 m.dn = ldb.Dn(samdb, domain_dn)
143 m["pwdHistoryLength"] = ldb.MessageElement([],
144 ldb.CHANGETYPE_DELETE, "pwdHistoryLength")
146 m["pwdHistoryLength"] = ldb.MessageElement(str(pwd_hist_len),
147 ldb.CHANGETYPE_ADD, "pwdHistoryLength")
149 print "Password history length changed!"
151 if opts.min_pwd_length is not None:
152 if opts.min_pwd_length == "default":
155 min_pwd_len = int(opts.min_pwd_length)
158 m.dn = ldb.Dn(samdb, domain_dn)
159 m["minPwdLength"] = ldb.MessageElement([],
160 ldb.CHANGETYPE_DELETE, "minPwdLength")
162 m["minPwdLength"] = ldb.MessageElement(str(min_pwd_len),
163 ldb.CHANGETYPE_ADD, "minPwdLength")
165 print "Minimum password length changed!"
167 if opts.min_pwd_age is not None:
168 if opts.min_pwd_age == "default":
171 min_pwd_age = int(opts.min_pwd_age)
173 min_pwd_age = -int(min_pwd_age * (24 * 60 * 60 * 10e7))
176 m.dn = ldb.Dn(samdb, domain_dn)
177 m["minPwdAge"] = ldb.MessageElement([],
178 ldb.CHANGETYPE_DELETE, "minPwdAge")
180 m["minPwdAge"] = ldb.MessageElement(str(min_pwd_age),
181 ldb.CHANGETYPE_ADD, "minPwdAge")
183 print "Minimum password age changed!"
185 if opts.max_pwd_age is not None:
186 if opts.max_pwd_age == "default":
189 max_pwd_age = int(opts.max_pwd_age)
191 max_pwd_age = -int(max_pwd_age * (24 * 60 * 60 * 10e7))
194 m.dn = ldb.Dn(samdb, domain_dn)
195 m["maxPwdAge"] = ldb.MessageElement([],
196 ldb.CHANGETYPE_DELETE, "maxPwdAge")
198 m["maxPwdAge"] = ldb.MessageElement(str(max_pwd_age),
199 ldb.CHANGETYPE_ADD, "maxPwdAge")
201 print "Maximum password age changed!"
203 print "All changes applied successfully!"
206 print "ERROR: Wrong argument '" + args[0] + "'!"