1 # Samba4 AD database checker
3 # Copyright (C) Andrew Tridgell 2011
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.
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.
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/>.
20 import samba
.getopt
as options
21 from samba
.auth
import system_session
22 from samba
.samdb
import SamDB
23 from samba
.netcmd
import (
28 from samba
.dbchecker
import dbcheck
31 class cmd_dbcheck(Command
):
32 """Check local AD database for errors."""
33 synopsis
= "%prog [<DN>] [options]"
35 takes_optiongroups
= {
36 "sambaopts": options
.SambaOptions
,
37 "versionopts": options
.VersionOptions
,
38 "credopts": options
.CredentialsOptionsDouble
,
44 Option("--scope", dest
="scope", default
="SUB",
45 help="Pass search scope that builds DN list. Options: SUB, ONE, BASE"),
46 Option("--fix", dest
="fix", default
=False, action
='store_true',
47 help='Fix any errors found'),
48 Option("--yes", dest
="yes", default
=False, action
='store_true',
49 help="don't confirm changes, just do them all as a single transaction"),
50 Option("--cross-ncs", dest
="cross_ncs", default
=False, action
='store_true',
51 help="cross naming context boundaries"),
52 Option("-v", "--verbose", dest
="verbose", action
="store_true", default
=False,
53 help="Print more details of checking"),
54 Option("--quiet", dest
="quiet", action
="store_true", default
=False,
55 help="don't print details of checking"),
56 Option("--attrs", dest
="attrs", default
=None, help="list of attributes to check (space separated)"),
57 Option("--reindex", dest
="reindex", default
=False, action
="store_true", help="force database re-index"),
58 Option("--force-modules", dest
="force_modules", default
=False, action
="store_true", help="force loading of Samba modules and ignore the @MODULES record (for very old databases)"),
59 Option("--reset-well-known-acls", dest
="reset_well_known_acls", default
=False, action
="store_true", help="reset ACLs on objects with well known default ACL values to the default"),
60 Option("-H", "--URL", help="LDB URL for database or target server (defaults to local SAM database)",
61 type=str, metavar
="URL", dest
="H"),
64 def run(self
, DN
=None, H
=None, verbose
=False, fix
=False, yes
=False,
65 cross_ncs
=False, quiet
=False,
66 scope
="SUB", credopts
=None, sambaopts
=None, versionopts
=None,
67 attrs
=None, reindex
=False, force_modules
=False,
68 reset_well_known_acls
=False):
70 lp
= sambaopts
.get_loadparm()
72 over_ldap
= H
is not None and H
.startswith('ldap')
75 creds
= credopts
.get_credentials(lp
, fallback_machine
=True)
80 samdb
= SamDB(session_info
=system_session(), url
=H
,
81 credentials
=creds
, lp
=lp
, options
=["modules=samba_dsdb"])
84 samdb
= SamDB(session_info
=system_session(), url
=H
,
85 credentials
=creds
, lp
=lp
)
87 raise CommandError("Failed to connect to DB at %s. If this is a really old sam.ldb (before alpha9), then try again with --force-modules" % H
)
90 if H
is None or not over_ldap
:
93 samdb_schema
= SamDB(session_info
=system_session(), url
=None,
94 credentials
=creds
, lp
=lp
)
96 scope_map
= { "SUB": ldb
.SCOPE_SUBTREE
, "BASE": ldb
.SCOPE_BASE
, "ONE":ldb
.SCOPE_ONELEVEL
}
98 if not scope
in scope_map
:
99 raise CommandError("Unknown scope %s" % scope
)
100 search_scope
= scope_map
[scope
]
102 controls
= ['show_deleted:1']
104 controls
.append('paged_results:1:1000')
106 controls
.append("search_options:1:2")
111 attrs
= attrs
.split()
113 started_transaction
= False
115 samdb
.transaction_start()
116 started_transaction
= True
118 chk
= dbcheck(samdb
, samdb_schema
=samdb_schema
, verbose
=verbose
,
119 fix
=fix
, yes
=yes
, quiet
=quiet
, in_transaction
=started_transaction
,
120 reset_well_known_acls
=reset_well_known_acls
)
123 self
.outf
.write("Re-indexing...\n")
125 if chk
.reindex_database():
126 self
.outf
.write("completed re-index OK\n")
129 self
.outf
.write("Resetting @MODULES...\n")
131 if chk
.reset_modules():
132 self
.outf
.write("completed @MODULES reset OK\n")
135 error_count
= chk
.check_database(DN
=DN
, scope
=search_scope
,
136 controls
=controls
, attrs
=attrs
)
138 if started_transaction
:
139 samdb
.transaction_cancel()
142 if started_transaction
:
143 samdb
.transaction_commit()