12246b545acf3ad591fd682813a0e97d14ac5af8
[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("--quiet", help="Be quiet", action="store_true")
31 parser.add_option("-H", help="LDB URL for database or target server", type=str)
32 parser.add_option("--complexity",
33   help="The password complexity (on | off). Default is 'on'", type=str)
34 parser.add_option("--history-length",
35   help="The password history length (<integer> | default)", type=str)
36 parser.add_option("--min-pwd-length",
37   help="The minimum password length (<integer> | default)", type=str)
38 parser.add_option("--min-pwd-age",
39   help="The minimum password age (<integer in days> | default)", type=str)
40 parser.add_option("--max-pwd-age",
41   help="The maximum password age (<integer in days> | default)", type=str)
42
43 opts, args = parser.parse_args()
44
45 #
46 #  print a message if quiet is not set
47 #
48 def message(text):
49         if not opts.quiet:
50                 print text
51
52 if len(args) == 0:
53         parser.print_usage()
54         sys.exit(1)
55
56 lp = sambaopts.get_loadparm()
57
58 creds = credopts.get_credentials(lp)
59
60 if opts.H is not None:
61         url = opts.H
62 else:
63         url = lp.get("sam database")
64
65 samdb = SamDB(url=url, session_info=system_session(),
66               credentials=creds, lp=lp)
67
68 domain_dn = SamDB.domain_dn(samdb)
69 res = samdb.search(domain_dn, scope=ldb.SCOPE_BASE,
70   attrs=["pwdProperties", "pwdHistoryLength", "minPwdLength", "minPwdAge",
71   "maxPwdAge"])
72 assert(len(res) == 1)
73 try:
74         pwd_props = int(res[0]["pwdProperties"][0])
75         pwd_hist_len = int(res[0]["pwdHistoryLength"][0])
76         min_pwd_len = int(res[0]["minPwdLength"][0])
77         # ticks -> days
78         min_pwd_age = int(abs(int(res[0]["minPwdAge"][0])) / (1e7 * 60 * 60 * 24))
79         max_pwd_age = int(abs(int(res[0]["maxPwdAge"][0])) / (1e7 * 60 * 60 * 24))
80 except:
81         if args[0] == "show":
82                 print "ERROR: Password informations missing in your AD domain object!"
83                 print "So no settings can be displayed!"
84                 sys.exit(1)
85         else:
86                 pwd_props = 0
87                 message("WARNING: Assuming previous password properties 0 (used for password complexity setting)")
88
89 if args[0] == "show":
90         message("Password informations for domain '" + domain_dn + "'")
91         message("")
92         if pwd_props & DOMAIN_PASSWORD_COMPLEX != 0:
93                 message("Password complexity: on")
94         else:
95                 message("Password complexity: off")
96         message("Password history length: " + str(pwd_hist_len))
97         message("Minimum password length: " + str(min_pwd_len))
98         message("Minimum password age (days): " + str(min_pwd_age))
99         message("Maximum password age (days): " + str(max_pwd_age))
100
101 elif args[0] == "set":
102         if opts.complexity is not None:
103                 if opts.complexity == "on":
104                         pwd_props = pwd_props | DOMAIN_PASSWORD_COMPLEX
105
106                         m = ldb.Message()
107                         m.dn = ldb.Dn(samdb, domain_dn)
108                         m["pwdProperties"] = ldb.MessageElement(str(pwd_props),
109                           ldb.FLAG_MOD_REPLACE, "pwdProperties")
110                         samdb.modify(m)
111                         message("Password complexity activated!")
112                 elif opts.complexity == "off":
113                         pwd_props = pwd_props & (~DOMAIN_PASSWORD_COMPLEX)
114
115                         m = ldb.Message()
116                         m.dn = ldb.Dn(samdb, domain_dn)
117                         m["pwdProperties"] = ldb.MessageElement(str(pwd_props),
118                           ldb.FLAG_MOD_REPLACE, "pwdProperties")
119                         samdb.modify(m)
120                         message("Password complexity deactivated!")
121                 else:
122                         print "ERROR: Wrong argument '" + opts.complexity + "'!"
123                         sys.exit(1)
124
125         if opts.history_length is not None:
126                 if opts.history_length == "default":
127                         pwd_hist_len = 24
128                 else:
129                         pwd_hist_len = int(opts.history_length)
130
131                 m = ldb.Message()
132                 m.dn = ldb.Dn(samdb, domain_dn)
133                 m["pwdHistoryLength"] = ldb.MessageElement(str(pwd_hist_len),
134                   ldb.FLAG_MOD_REPLACE, "pwdHistoryLength")
135                 samdb.modify(m)
136                 message("Password history length changed!")
137
138         if opts.min_pwd_length is not None:
139                 if opts.min_pwd_length == "default":
140                         min_pwd_len = 7
141                 else:
142                         min_pwd_len = int(opts.min_pwd_length)
143
144                 m = ldb.Message()
145                 m.dn = ldb.Dn(samdb, domain_dn)
146                 m["minPwdLength"] = ldb.MessageElement(str(min_pwd_len),
147                   ldb.FLAG_MOD_REPLACE, "minPwdLength")
148                 samdb.modify(m)
149                 message("Minimum password length changed!")
150
151         if opts.min_pwd_age is not None:
152                 if opts.min_pwd_age == "default":
153                         min_pwd_age = 0
154                 else:
155                         min_pwd_age = int(opts.min_pwd_age)
156                 # days -> ticks
157                 min_pwd_age = -int(min_pwd_age * (24 * 60 * 60 * 1e7))
158
159                 m = ldb.Message()
160                 m.dn = ldb.Dn(samdb, domain_dn)
161                 m["minPwdAge"] = ldb.MessageElement(str(min_pwd_age),
162                   ldb.FLAG_MOD_REPLACE, "minPwdAge")
163                 samdb.modify(m)
164                 message("Minimum password age changed!")
165
166         if opts.max_pwd_age is not None:
167                 if opts.max_pwd_age == "default":
168                         max_pwd_age = 43
169                 else:
170                         max_pwd_age = int(opts.max_pwd_age)
171                 # days -> ticks
172                 max_pwd_age = -int(max_pwd_age * (24 * 60 * 60 * 1e7))
173
174                 m = ldb.Message()
175                 m.dn = ldb.Dn(samdb, domain_dn)
176                 m["maxPwdAge"] = ldb.MessageElement(str(max_pwd_age),
177                   ldb.FLAG_MOD_REPLACE, "maxPwdAge")
178                 samdb.modify(m)
179                 message("Maximum password age changed!")
180
181         message("All changes applied successfully!")
182
183 else:
184         print "ERROR: Wrong argument '" + args[0] + "'!"
185         sys.exit(1)