s4:pwsettings script - Fix a small glitch
[ira/wip.git] / source4 / setup / pwsettings
1 #!/usr/bin/python
2 #
3 #       Sets password settings (Password complexity, history length,
4 #       minimum password length, the minimum and maximum password age) on a
5 #       Samba4 server
6 #
7 #       Copyright Jelmer Vernooij 2008
8 #       Copyright Matthias Dieter Wallnoefer 2009
9 #       Released under the GNU GPL version 3 or later
10 #
11 import os, sys
12
13 sys.path.insert(0, os.path.join(os.path.dirname(sys.argv[0]), "../bin/python"))
14
15 import samba.getopt as options
16 import optparse
17 import pwd
18 import ldb
19
20 from samba.auth import system_session
21 from samba.samdb import SamDB
22 from samba.dcerpc.samr import DOMAIN_PASSWORD_COMPLEX
23
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)
41
42 opts, args = parser.parse_args()
43
44 #
45 #  print a message if quiet is not set
46 #
47 def message(text):
48         if not opts.quiet:
49                 print text
50
51 if len(args) == 0:
52         parser.print_usage()
53         sys.exit(1)
54
55 lp = sambaopts.get_loadparm()
56
57 creds = credopts.get_credentials(lp)
58
59 if opts.H is not None:
60         url = opts.H
61 else:
62         url = lp.get("sam database")
63
64 samdb = SamDB(url=url, session_info=system_session(),
65               credentials=creds, lp=lp)
66
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]
72
73 res = samdb.search(domain_dn, scope=ldb.SCOPE_BASE, attrs=["pwdProperties",
74   "pwdHistoryLength", "minPwdLength", "minPwdAge", "maxPwdAge"])
75 assert(len(res) == 1)
76 try:
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])
80         # ticks -> days
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))
83 except:
84         if args[0] == "show":
85                 print "ERROR: Password informations missing in your AD domain object!"
86                 print "So no settings can be displayed!"
87                 sys.exit(1)
88         else:
89                 if pwd_props is None:
90                         pwd_props = 0
91                         print "WARNING: Assuming previous password properties 0 (used for password complexity setting)"
92
93 if args[0] == "show":
94         print "Password informations for domain '" + domain_dn + "'"
95         print ""
96         if pwd_props & DOMAIN_PASSWORD_COMPLEX != 0:
97                 print "Password complexity: on"
98         else:
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)
104
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
109
110                         m = ldb.Message()
111                         m.dn = ldb.Dn(samdb, domain_dn)
112                         m["pwdProperties"] = ldb.MessageElement([],
113                           ldb.CHANGETYPE_DELETE, "pwdProperties")
114                         samdb.modify(m)
115                         m["pwdProperties"] = ldb.MessageElement(str(pwd_props),
116                           ldb.CHANGETYPE_ADD, "pwdProperties")
117                         samdb.modify(m)
118                         print "Password complexity activated!"
119                 elif opts.complexity == "off":
120                         pwd_props = pwd_props & (~DOMAIN_PASSWORD_COMPLEX)
121
122                         m = ldb.Message()
123                         m.dn = ldb.Dn(samdb, domain_dn)
124                         m["pwdProperties"] = ldb.MessageElement([],
125                           ldb.CHANGETYPE_DELETE, "pwdProperties")
126                         samdb.modify(m)
127                         m["pwdProperties"] = ldb.MessageElement(str(pwd_props),
128                           ldb.CHANGETYPE_ADD, "pwdProperties")
129                         samdb.modify(m)
130                         print "Password complexity deactivated!"
131                 else:
132                         print "ERROR: Wrong argument '" + opts.complexity + "'!"
133                         sys.exit(1)
134
135         if opts.history_length is not None:
136                 if opts.history_length == "default":
137                         pwd_hist_len = 24
138                 else:
139                         pwd_hist_len = int(opts.history_length)
140
141                 m = ldb.Message()
142                 m.dn = ldb.Dn(samdb, domain_dn)
143                 m["pwdHistoryLength"] = ldb.MessageElement([],
144                   ldb.CHANGETYPE_DELETE, "pwdHistoryLength")
145                 samdb.modify(m)
146                 m["pwdHistoryLength"] = ldb.MessageElement(str(pwd_hist_len),
147                   ldb.CHANGETYPE_ADD, "pwdHistoryLength")
148                 samdb.modify(m)
149                 print "Password history length changed!"
150
151         if opts.min_pwd_length is not None:
152                 if opts.min_pwd_length == "default":
153                         min_pwd_len = 7
154                 else:
155                         min_pwd_len = int(opts.min_pwd_length)
156
157                 m = ldb.Message()
158                 m.dn = ldb.Dn(samdb, domain_dn)
159                 m["minPwdLength"] = ldb.MessageElement([],
160                   ldb.CHANGETYPE_DELETE, "minPwdLength")
161                 samdb.modify(m)
162                 m["minPwdLength"] = ldb.MessageElement(str(min_pwd_len),
163                   ldb.CHANGETYPE_ADD, "minPwdLength")
164                 samdb.modify(m)
165                 print "Minimum password length changed!"
166
167         if opts.min_pwd_age is not None:
168                 if opts.min_pwd_age == "default":
169                         min_pwd_age = 0
170                 else:
171                         min_pwd_age = int(opts.min_pwd_age)
172                 # days -> ticks
173                 min_pwd_age = -int(min_pwd_age * (24 * 60 * 60 * 10e7))
174
175                 m = ldb.Message()
176                 m.dn = ldb.Dn(samdb, domain_dn)
177                 m["minPwdAge"] = ldb.MessageElement([],
178                   ldb.CHANGETYPE_DELETE, "minPwdAge")
179                 samdb.modify(m)
180                 m["minPwdAge"] = ldb.MessageElement(str(min_pwd_age),
181                   ldb.CHANGETYPE_ADD, "minPwdAge")
182                 samdb.modify(m)
183                 print "Minimum password age changed!"
184
185         if opts.max_pwd_age is not None:
186                 if opts.max_pwd_age == "default":
187                         max_pwd_age = 43
188                 else:
189                         max_pwd_age = int(opts.max_pwd_age)
190                 # days -> ticks
191                 max_pwd_age = -int(max_pwd_age * (24 * 60 * 60 * 10e7))
192
193                 m = ldb.Message()
194                 m.dn = ldb.Dn(samdb, domain_dn)
195                 m["maxPwdAge"] = ldb.MessageElement([],
196                   ldb.CHANGETYPE_DELETE, "maxPwdAge")
197                 samdb.modify(m)
198                 m["maxPwdAge"] = ldb.MessageElement(str(max_pwd_age),
199                   ldb.CHANGETYPE_ADD, "maxPwdAge")
200                 samdb.modify(m)
201                 print "Maximum password age changed!"
202
203         print "All changes applied successfully!"
204
205 else:
206         print "ERROR: Wrong argument '" + args[0] + "'!"
207         sys.exit(1)