s4-samba-tool: Add samba-tool ntacl sysvolcheck command
[samba.git] / source4 / scripting / python / samba / netcmd / ntacl.py
1 # Manipulate file NT ACLs
2 #
3 # Copyright Matthieu Patou 2010 <mat@matws.net>
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 #
18
19 from samba.credentials import DONT_USE_KERBEROS
20 import samba.getopt as options
21 from samba.dcerpc import security, idmap
22 from samba.ntacls import setntacl, getntacl
23 from samba import Ldb
24 from samba.ndr import ndr_unpack
25 from samba.samdb import SamDB
26 from samba.samba3 import param as s3param, passdb, smbd
27 from samba import provision
28
29 from ldb import SCOPE_BASE
30 import os
31
32 from samba.auth import system_session
33 from samba.netcmd import (
34     Command,
35     CommandError,
36     SuperCommand,
37     Option,
38     )
39
40
41
42 class cmd_ntacl_set(Command):
43     """Set ACLs on a file"""
44
45     synopsis = "%prog <acl> <file> [options]"
46
47     takes_optiongroups = {
48         "sambaopts": options.SambaOptions,
49         "credopts": options.CredentialsOptions,
50         "versionopts": options.VersionOptions,
51         }
52
53     takes_options = [
54         Option("--quiet", help="Be quiet", action="store_true"),
55         Option("--xattr-backend", type="choice", help="xattr backend type (native fs or tdb)",
56                choices=["native","tdb"]),
57         Option("--eadb-file", help="Name of the tdb file where attributes are stored", type="string"),
58         ]
59
60     takes_args = ["acl","file"]
61
62     def run(self, acl, file, quiet=False,xattr_backend=None,eadb_file=None,
63             credopts=None, sambaopts=None, versionopts=None):
64         lp = sambaopts.get_loadparm()
65         path = lp.private_path("secrets.ldb")
66         creds = credopts.get_credentials(lp)
67         creds.set_kerberos_state(DONT_USE_KERBEROS)
68         try:
69             ldb = Ldb(path, session_info=system_session(), credentials=creds,
70                       lp=lp)
71         except Exception, e:
72             raise CommandError("Unable to read domain SID from configuration files", e)
73         attrs = ["objectSid"]
74         res = ldb.search(expression="(objectClass=*)",
75             base="flatname=%s,cn=Primary Domains" % lp.get("workgroup"),
76             scope=SCOPE_BASE, attrs=attrs)
77         if len(res) !=0:
78             domainsid = ndr_unpack(security.dom_sid, res[0]["objectSid"][0])
79             setntacl(lp, file, acl, str(domainsid), xattr_backend, eadb_file)
80         else:
81             raise CommandError("Unable to read domain SID from configuration files")
82
83
84
85 class cmd_ntacl_get(Command):
86     """Set ACLs on a file"""
87     synopsis = "%prog <file> [options]"
88
89     takes_optiongroups = {
90         "sambaopts": options.SambaOptions,
91         "credopts": options.CredentialsOptions,
92         "versionopts": options.VersionOptions,
93         }
94
95     takes_options = [
96         Option("--as-sddl", help="Output ACL in the SDDL format", action="store_true"),
97         Option("--xattr-backend", type="choice", help="xattr backend type (native fs or tdb)",
98                choices=["native","tdb"]),
99         Option("--eadb-file", help="Name of the tdb file where attributes are stored", type="string"),
100         ]
101
102     takes_args = ["file"]
103
104     def run(self, file, as_sddl=False, xattr_backend=None, eadb_file=None,
105             credopts=None, sambaopts=None, versionopts=None):
106         lp = sambaopts.get_loadparm()
107         acl = getntacl(lp, file, xattr_backend, eadb_file)
108         if as_sddl:
109             anysid = security.dom_sid(security.SID_NT_SELF)
110             self.outf.write(acl.info.as_sddl(anysid)+"\n")
111         else:
112             acl.dump()
113
114
115 class cmd_ntacl_sysvolreset(Command):
116     """Reset sysvol ACLs to defaults (including correct ACLs on GPOs)"""
117     synopsis = "%prog <file> [options]"
118
119     takes_optiongroups = {
120         "sambaopts": options.SambaOptions,
121         "credopts": options.CredentialsOptions,
122         "versionopts": options.VersionOptions,
123         }
124
125     takes_options = [
126         Option("--use-ntvfs", help="Set the ACLs for use with the ntvfs file server", action="store_true"),
127         Option("--use-s3fs", help="Set the ACLs for use with the default s3fs file server", action="store_true")
128         ]
129
130     def run(self, use_ntvfs=False, use_s3fs=False,
131             credopts=None, sambaopts=None, versionopts=None):
132         lp = sambaopts.get_loadparm()
133         path = lp.private_path("secrets.ldb")
134         creds = credopts.get_credentials(lp)
135         creds.set_kerberos_state(DONT_USE_KERBEROS)
136         logger = self.get_logger()
137
138         netlogon = lp.get("path", "netlogon")
139         sysvol = lp.get("path", "sysvol")
140         try:
141             samdb = SamDB(session_info=system_session(), 
142                           lp=lp)
143         except Exception, e:
144             raise CommandError("Unable to open samdb:", e)
145
146         if not use_ntvfs and not use_s3fs:
147             use_ntvfs = "smb" in lp.get("server services")
148         elif use_s3fs:
149             use_ntvfs = False
150
151         domain_sid = security.dom_sid(samdb.domain_sid)
152
153         s3conf = s3param.get_context()
154         s3conf.load(lp.configfile)
155         # ensure we are using the right samba4 passdb backend, no matter what
156         s3conf.set("passdb backend", "samba4:%s" % samdb.url)
157
158         LA_sid = security.dom_sid(str(domain_sid)
159                                   +"-"+str(security.DOMAIN_RID_ADMINISTRATOR))
160         BA_sid = security.dom_sid(security.SID_BUILTIN_ADMINISTRATORS)
161
162         s4_passdb = passdb.PDB(s3conf.get("passdb backend"))
163
164         # These assertions correct for current plugin_s4_dc selftest
165         # configuration.  When other environments have a broad range of
166         # groups mapped via passdb, we can relax some of these checks
167         (LA_uid,LA_type) = s4_passdb.sid_to_id(LA_sid)
168         if (LA_type != idmap.ID_TYPE_UID and LA_type != idmap.ID_TYPE_BOTH):
169             raise CommandError("SID %s is not mapped to a UID" % LA_sid)
170         (BA_gid,BA_type) = s4_passdb.sid_to_id(BA_sid)
171         if (BA_type != idmap.ID_TYPE_GID and BA_type != idmap.ID_TYPE_BOTH):
172             raise CommandError("SID %s is not mapped to a GID" % BA_sid)
173
174         if use_ntvfs:
175             logger.warning("Please note that POSIX permissions have NOT been changed, only the stored NT ACL")
176                     
177         provision.setsysvolacl(samdb, netlogon, sysvol,
178                                LA_uid, BA_gid, domain_sid, 
179                                lp.get("realm").lower(), samdb.domain_dn(), 
180                                lp, use_ntvfs=use_ntvfs)
181
182 class cmd_ntacl_sysvolcheck(Command):
183     """Check sysvol ACLs match defaults (including correct ACLs on GPOs)"""
184     synopsis = "%prog <file> [options]"
185
186     takes_optiongroups = {
187         "sambaopts": options.SambaOptions,
188         "credopts": options.CredentialsOptions,
189         "versionopts": options.VersionOptions,
190         }
191
192     def run(self, 
193             credopts=None, sambaopts=None, versionopts=None):
194         lp = sambaopts.get_loadparm()
195         path = lp.private_path("secrets.ldb")
196         creds = credopts.get_credentials(lp)
197         creds.set_kerberos_state(DONT_USE_KERBEROS)
198         logger = self.get_logger()
199
200         netlogon = lp.get("path", "netlogon")
201         sysvol = lp.get("path", "sysvol")
202         try:
203             samdb = SamDB(session_info=system_session(), 
204                           lp=lp)
205         except Exception, e:
206             raise CommandError("Unable to open samdb:", e)
207
208         domain_sid = security.dom_sid(samdb.domain_sid)
209
210         provision.checksysvolacl(samdb, netlogon, sysvol,
211                                  domain_sid, 
212                                  lp.get("realm").lower(), samdb.domain_dn(), 
213                                  lp)
214
215
216 class cmd_ntacl(SuperCommand):
217     """NT ACLs manipulation"""
218
219     subcommands = {}
220     subcommands["set"] = cmd_ntacl_set()
221     subcommands["get"] = cmd_ntacl_get()
222     subcommands["sysvolreset"] = cmd_ntacl_sysvolreset()
223     subcommands["sysvolcheck"] = cmd_ntacl_sysvolcheck()
224