1 # rodc related commands
3 # Copyright Andrew Tridgell 2010
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/>.
19 from samba
.netcmd
import Command
, CommandError
, Option
, SuperCommand
20 import samba
.getopt
as options
21 from samba
.samdb
import SamDB
22 from samba
.auth
import system_session
24 from samba
.dcerpc
import misc
, drsuapi
25 from samba
.drs_utils
import drs_Replicate
28 class cmd_rodc_preload(Command
):
29 """Preload one account for an RODC."""
31 synopsis
= "%prog (<SID>|<DN>|<accountname>) [options]"
33 takes_optiongroups
= {
34 "sambaopts": options
.SambaOptions
,
35 "versionopts": options
.VersionOptions
,
36 "credopts": options
.CredentialsOptions
,
40 Option("--server", help="DC to use", type=str),
43 takes_args
= ["account"]
45 def get_dn(self
, samdb
, account
):
46 '''work out what DN they meant'''
48 # we accept the account in SID, accountname or DN form
49 if account
[0:2] == 'S-':
50 res
= samdb
.search(base
="<SID=%s>" % account
,
51 expression
="objectclass=user",
52 scope
=ldb
.SCOPE_BASE
, attrs
=[])
53 elif account
.find('=') >= 0:
54 res
= samdb
.search(base
=account
,
55 expression
="objectclass=user",
56 scope
=ldb
.SCOPE_BASE
, attrs
=[])
58 res
= samdb
.search(expression
="(&(samAccountName=%s)(objectclass=user))" % ldb
.binary_encode(account
),
59 scope
=ldb
.SCOPE_SUBTREE
, attrs
=[])
61 raise Exception("Failed to find account '%s'" % account
)
62 return str(res
[0]["dn"])
65 def run(self
, account
, sambaopts
=None,
66 credopts
=None, versionopts
=None, server
=None):
69 raise Exception("You must supply a server")
71 lp
= sambaopts
.get_loadparm()
73 creds
= credopts
.get_credentials(lp
, fallback_machine
=True)
75 # connect to the remote and local SAMs
76 samdb
= SamDB(url
="ldap://%s" % server
,
77 session_info
=system_session(),
78 credentials
=creds
, lp
=lp
)
80 local_samdb
= SamDB(url
=None, session_info
=system_session(),
81 credentials
=creds
, lp
=lp
)
83 # work out the source and destination GUIDs
84 dc_ntds_dn
= samdb
.get_dsServiceName()
85 res
= samdb
.search(base
=dc_ntds_dn
, scope
=ldb
.SCOPE_BASE
, attrs
=["invocationId"])
86 source_dsa_invocation_id
= misc
.GUID(local_samdb
.schema_format_value("objectGUID", res
[0]["invocationId"][0]))
88 dn
= self
.get_dn(samdb
, account
)
89 self
.outf
.write("Replicating DN %s\n" % dn
)
91 destination_dsa_guid
= misc
.GUID(local_samdb
.get_ntds_GUID())
93 local_samdb
.transaction_start()
94 repl
= drs_Replicate("ncacn_ip_tcp:%s[seal,print]" % server
, lp
, creds
,
95 local_samdb
, destination_dsa_guid
)
97 repl
.replicate(dn
, source_dsa_invocation_id
, destination_dsa_guid
,
98 exop
=drsuapi
.DRSUAPI_EXOP_REPL_SECRET
, rodc
=True)
100 local_samdb
.transaction_cancel()
101 raise CommandError("Error replicating DN %s" % dn
, e
)
102 local_samdb
.transaction_commit()
106 class cmd_rodc(SuperCommand
):
107 """Read-Only Domain Controller (RODC) management."""
110 subcommands
["preload"] = cmd_rodc_preload()