summaryrefslogtreecommitdiffstats
path: root/source4/scripting/bin/samba_downgrade_db
blob: b9a09098a8a36f12cd8b01f85fae2a53cc86fd40 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/usr/bin/python3
#
# Unix SMB/CIFS implementation.
# Copyright (C) Andrew Bartlett <abartlet@samba.org> 2019
#
# Downgrade a database from 4.11 format to 4.7 format. 4.7 Format will
# run on any version of Samba AD, and Samba will repack/reconfigure the
# database if necessary.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
import optparse
import sys

# Find right directory when running from source tree
sys.path.insert(0, "bin/python")


import samba
import ldb
import urllib
import os
from samba import getopt as options
from samba.samdb import SamDB
from samba.dbchecker import dbcheck
from samba.credentials import Credentials
parser = optparse.OptionParser("samba_downgrade_db")
sambaopts = options.SambaOptions(parser)
parser.add_option_group(options.VersionOptions(parser))
parser.add_option("-H", "--URL", help="LDB URL for database",
                  type=str, metavar="URL", dest="H")
opts, args = parser.parse_args()

if len(args) != 0:
    parser.print_usage()
    sys.exit(1)

lp_ctx = sambaopts.get_loadparm()

if opts.H is None:
    url = lp_ctx.private_path("sam.ldb")
else:
    url = opts.H

samdb = ldb.Ldb(url=url,
                flags=ldb.FLG_DONT_CREATE_DB,
                options=["modules:"])

partitions = samdb.search(base="@PARTITION",
                          scope=ldb.SCOPE_BASE,
                          attrs=["backendStore", "partition"])

backend = str(partitions[0].get('backendStore', 'tdb'))

if backend == "mdb":
    samdb = None
    options = ["pack_format_override=%d" % ldb.PACKING_FORMAT]
    # We can't remove GUID indexes from LMDB in case there are very
    # long DNs, so we just move down the pack format, which also removes
    # references to ORDERED_INTEGER in @ATTRIBUTES.

    # Reopen the DB with pack_format_override set
    samdb = SamDB(url=url,
                  flags=ldb.FLG_DONT_CREATE_DB,
                  lp=lp_ctx,
                  options=options)
    samdb.transaction_start()
    samdb.transaction_commit()
    print("Your database has been downgraded to LDB pack format version %0x (v1)." % ldb.PACKING_FORMAT)

    print("NOTE: Any use of a Samba 4.11 tool that modifies the DB will "
          "auto-upgrade back to pack format version %0x (v2)" %
          ldb.PACKING_FORMAT_V2)
    exit(0);

# This is needed to force the @ATTRIBUTES and @INDEXLIST to be correct
lp_ctx.set("dsdb:guid index", "false")

modmsg = ldb.Message()
modmsg.dn = ldb.Dn(samdb, '@INDEXLIST')
modmsg.add(ldb.MessageElement(
    elements=[],
    flags=ldb.FLAG_MOD_REPLACE,
    name='@IDXGUID'))
modmsg.add(ldb.MessageElement(
    elements=[],
    flags=ldb.FLAG_MOD_REPLACE,
    name='@IDX_DN_GUID'))

samdb.transaction_start()
samdb.modify(modmsg)

privatedir = os.path.dirname(url)

dbs = []
for part in partitions[0]['partition']:
    dbname = str(part).split(":")[1]
    dbpath = os.path.join(privatedir, dbname)
    if os.path.isfile(dbpath):
        dbpath = "ldb://" + dbpath
    db = ldb.Ldb(url=dbpath,
                 options=["modules:"],
                 flags=ldb.FLG_DONT_CREATE_DB)
    db.transaction_start()
    db.modify(modmsg)
    dbs.append(db)

for db in dbs:
    db.transaction_commit()

samdb.transaction_commit()

print("Re-opening with the full DB stack")
samdb = SamDB(url=url,
              flags=ldb.FLG_DONT_CREATE_DB,
              lp=lp_ctx)
print("Re-triggering another re-index")
chk = dbcheck(samdb)

chk.reindex_database()

print("Your database has been downgraded to DN-based index values.")

print("NOTE: Any use of a Samba 4.8 or later tool including ldbsearch will "
      "auto-upgrade back to GUID index mode")