wintest: Rework support for the internal DNS server
[samba.git] / wintest / test-s4-howto.py
1 #!/usr/bin/env python
2
3 '''automated testing of the steps of the Samba4 HOWTO'''
4
5 import sys, os
6 import wintest, pexpect, time, subprocess
7
8 def set_krb5_conf(t):
9     t.putenv("KRB5_CONFIG", '${PREFIX}/private/krb5.conf')
10
11 def build_s4(t):
12     '''build samba4'''
13     t.info('Building s4')
14     t.chdir('${SOURCETREE}')
15     t.putenv('CC', 'ccache gcc')
16     t.run_cmd('make reconfigure || ./configure --enable-auto-reconfigure --enable-developer --prefix=${PREFIX} -C')
17     t.run_cmd('make -j')
18     t.run_cmd('rm -rf ${PREFIX}')
19     t.run_cmd('make -j install')
20
21
22 def provision_s4(t, func_level="2008"):
23     '''provision s4 as a DC'''
24     t.info('Provisioning s4')
25     t.chdir('${PREFIX}')
26     t.del_files(["var", "private"])
27     t.run_cmd("rm -f etc/smb.conf")
28     provision=['bin/samba-tool',
29                'domain',
30                'provision',
31                '--realm=${LCREALM}',
32                '--domain=${DOMAIN}',
33                '--adminpass=${PASSWORD1}',
34                '--server-role=domain controller',
35                '--function-level=%s' % func_level,
36                '-d${DEBUGLEVEL}',
37                '--option=interfaces=${INTERFACE}',
38                '--host-ip=${INTERFACE_IP}',
39                '--option=bind interfaces only=yes',
40                '--option=rndc command=${RNDC} -c${PREFIX}/etc/rndc.conf',
41                '${USE_NTVFS}',
42                '--dns-backend=${NAMESERVER_BACKEND}',
43                '${DNS_FORWARDER}']
44     if t.getvar('INTERFACE_IPV6'):
45         provision.append('--host-ip6=${INTERFACE_IPV6}')
46     t.run_cmd(provision)
47     t.run_cmd('bin/samba-tool user add testallowed ${PASSWORD1}')
48     t.run_cmd('bin/samba-tool user add testdenied ${PASSWORD1}')
49     t.run_cmd('bin/samba-tool group addmembers "Allowed RODC Password Replication Group" testallowed')
50
51
52 def start_s4(t):
53     '''startup samba4'''
54     t.info('Starting Samba4')
55     t.chdir("${PREFIX}")
56     t.run_cmd('killall -9 -q samba smbd nmbd winbindd', checkfail=False)
57     t.run_cmd(['sbin/samba',
58              '--option', 'panic action=gnome-terminal -e "gdb --pid %d"'])
59     t.port_wait("${INTERFACE_IP}", 139)
60
61 def test_smbclient(t):
62     '''test smbclient against localhost'''
63     t.info('Testing smbclient')
64     smbclient = t.getvar("smbclient")
65     t.chdir('${PREFIX}')
66     t.cmd_contains("%s --version" % (smbclient), ["Version 4.0"])
67     t.retry_cmd('%s -L ${INTERFACE_IP} -U%%' % (smbclient), ["netlogon", "sysvol", "IPC Service"])
68     child = t.pexpect_spawn('%s //${INTERFACE_IP}/netlogon -Uadministrator%%${PASSWORD1}' % (smbclient))
69     child.expect("smb:")
70     child.sendline("dir")
71     child.expect("blocks available")
72     child.sendline("mkdir testdir")
73     child.expect("smb:")
74     child.sendline("cd testdir")
75     child.expect('testdir')
76     child.sendline("cd ..")
77     child.sendline("rmdir testdir")
78
79
80 def create_shares(t):
81     '''create some test shares'''
82     t.info("Adding test shares")
83     t.chdir('${PREFIX}')
84     t.write_file("etc/smb.conf", '''
85 [test]
86        path = ${PREFIX}/test
87        read only = no
88 [profiles]
89        path = ${PREFIX}/var/profiles
90        read only = no
91     ''',
92                  mode='a')
93     t.run_cmd("mkdir -p test")
94     t.run_cmd("mkdir -p var/profiles")
95
96
97 def test_dns(t):
98     '''test that DNS is OK'''
99     t.info("Testing DNS")
100     t.cmd_contains("host -t SRV _ldap._tcp.${LCREALM}.",
101                  ['_ldap._tcp.${LCREALM} has SRV record 0 100 389 ${HOSTNAME}.${LCREALM}'])
102     t.cmd_contains("host -t SRV  _kerberos._udp.${LCREALM}.",
103                  ['_kerberos._udp.${LCREALM} has SRV record 0 100 88 ${HOSTNAME}.${LCREALM}'])
104     t.cmd_contains("host -t A ${HOSTNAME}.${LCREALM}",
105                  ['${HOSTNAME}.${LCREALM} has address'])
106
107 def test_kerberos(t):
108     '''test that kerberos is OK'''
109     t.info("Testing kerberos")
110     t.run_cmd("kdestroy")
111     t.kinit("administrator@${REALM}", "${PASSWORD1}")
112     # this copes with the differences between MIT and Heimdal klist
113     t.cmd_contains("klist", ["rincipal", "administrator@${REALM}"])
114
115
116 def test_dyndns(t):
117     '''test that dynamic DNS is working'''
118     t.chdir('${PREFIX}')
119     t.run_cmd("sbin/samba_dnsupdate --fail-immediately")
120     if not t.getvar('NAMESERVER_BACKEND') == 'SAMBA_INTERNAL':
121         t.rndc_cmd("flush")
122
123
124 def run_winjoin(t, vm):
125     '''join a windows box to our domain'''
126     t.setwinvars(vm)
127
128     t.run_winjoin(t, "${LCREALM}")
129
130 def test_winjoin(t, vm):
131     t.info("Checking the windows join is OK")
132     smbclient = t.getvar("smbclient")
133     t.chdir('${PREFIX}')
134     t.port_wait("${WIN_IP}", 139)
135     t.retry_cmd('%s -L ${WIN_HOSTNAME}.${LCREALM} -Uadministrator@${LCREALM}%%${PASSWORD1}' % (smbclient), ["C$", "IPC$", "Sharename"], retries=100)
136     t.cmd_contains("host -t A ${WIN_HOSTNAME}.${LCREALM}.", ['has address'])
137     t.cmd_contains('%s -L ${WIN_HOSTNAME}.${LCREALM} -Utestallowed@${LCREALM}%%${PASSWORD1}' % (smbclient), ["C$", "IPC$", "Sharename"])
138     t.cmd_contains('%s -L ${WIN_HOSTNAME}.${LCREALM} -k no -Utestallowed@${LCREALM}%%${PASSWORD1}' % (smbclient), ["C$", "IPC$", "Sharename"])
139     t.cmd_contains('%s -L ${WIN_HOSTNAME}.${LCREALM} -k yes -Utestallowed@${LCREALM}%%${PASSWORD1}' % (smbclient), ["C$", "IPC$", "Sharename"])
140     child = t.open_telnet("${WIN_HOSTNAME}", "${DOMAIN}\\administrator", "${PASSWORD1}")
141     child.sendline("net use t: \\\\${HOSTNAME}.${LCREALM}\\test")
142     child.expect("The command completed successfully")
143
144
145 def run_dcpromo(t, vm):
146     '''run a dcpromo on windows'''
147     t.setwinvars(vm)
148
149     t.info("Joining a windows VM ${WIN_VM} to the domain as a DC using dcpromo")
150     child = t.open_telnet("${WIN_HOSTNAME}", "administrator", "${WIN_PASS}", set_ip=True, set_noexpire=True)
151     child.sendline("copy /Y con answers.txt")
152     child.sendline('''
153 [DCINSTALL]
154 RebootOnSuccess=Yes
155 RebootOnCompletion=Yes
156 ReplicaOrNewDomain=Replica
157 ReplicaDomainDNSName=${LCREALM}
158 SiteName=Default-First-Site-Name
159 InstallDNS=No
160 ConfirmGc=Yes
161 CreateDNSDelegation=No
162 UserDomain=${LCREALM}
163 UserName=${LCREALM}\\administrator
164 Password=${PASSWORD1}
165 DatabasePath="C:\Windows\NTDS"
166 LogPath="C:\Windows\NTDS"
167 SYSVOLPath="C:\Windows\SYSVOL"
168 SafeModeAdminPassword=${PASSWORD1}
169 \1a
170 ''')
171     child.expect("copied.")
172     child.expect("C:")
173     child.expect("C:")
174     child.sendline("dcpromo /answer:answers.txt")
175     i = child.expect(["You must restart this computer", "failed", "Active Directory Domain Services was not installed", "C:"], timeout=120)
176     if i == 1 or i == 2:
177         child.sendline("echo off")
178         child.sendline("echo START DCPROMO log")
179         child.sendline("more c:\windows\debug\dcpromoui.log")
180         child.sendline("echo END DCPROMO log")
181         child.expect("END DCPROMO")
182         raise Exception("dcpromo failed")
183     t.wait_reboot()
184
185
186 def test_dcpromo(t, vm):
187     '''test that dcpromo worked'''
188     t.info("Checking the dcpromo join is OK")
189     smbclient = t.getvar("smbclient")
190     t.chdir('${PREFIX}')
191     t.port_wait("${WIN_IP}", 139)
192     t.retry_cmd("host -t A ${WIN_HOSTNAME}.${LCREALM}. ${NAMED_INTERFACE_IP}",
193                 ['${WIN_HOSTNAME}.${LCREALM} has address'],
194                 retries=30, delay=10, casefold=True)
195     t.retry_cmd('%s -L ${WIN_HOSTNAME}.${LCREALM} -Uadministrator@${LCREALM}%%${PASSWORD1}' % (smbclient), ["C$", "IPC$", "Sharename"])
196     t.cmd_contains("host -t A ${WIN_HOSTNAME}.${LCREALM}.", ['has address'])
197     t.cmd_contains('%s -L ${WIN_HOSTNAME}.${LCREALM} -Utestallowed@${LCREALM}%%${PASSWORD1}' % (smbclient), ["C$", "IPC$", "Sharename"])
198
199     t.cmd_contains("bin/samba-tool drs kcc ${HOSTNAME}.${LCREALM} -Uadministrator@${LCREALM}%${PASSWORD1}", ['Consistency check', 'successful'])
200     t.retry_cmd("bin/samba-tool drs kcc ${WIN_HOSTNAME}.${LCREALM} -Uadministrator@${LCREALM}%${PASSWORD1}", ['Consistency check', 'successful'])
201
202     t.kinit("administrator@${REALM}", "${PASSWORD1}")
203
204     # the first replication will transfer the dnsHostname attribute
205     t.cmd_contains("bin/samba-tool drs replicate ${HOSTNAME}.${LCREALM} ${WIN_HOSTNAME} CN=Configuration,${BASEDN} -k yes", ["was successful"])
206
207     for nc in [ '${BASEDN}', 'CN=Configuration,${BASEDN}', 'CN=Schema,CN=Configuration,${BASEDN}' ]:
208         t.cmd_contains("bin/samba-tool drs replicate ${HOSTNAME}.${LCREALM} ${WIN_HOSTNAME}.${LCREALM} %s -k yes" % nc, ["was successful"])
209         t.cmd_contains("bin/samba-tool drs replicate ${WIN_HOSTNAME}.${LCREALM} ${HOSTNAME}.${LCREALM} %s -k yes" % nc, ["was successful"])
210
211     t.cmd_contains("bin/samba-tool drs showrepl ${HOSTNAME}.${LCREALM} -k yes",
212                  [ "INBOUND NEIGHBORS",
213                    "${BASEDN}",
214                    "Last attempt .* was successful",
215                    "CN=Configuration,${BASEDN}",
216                    "Last attempt .* was successful",
217                    "CN=Configuration,${BASEDN}", # cope with either order
218                    "Last attempt .* was successful",
219                    "OUTBOUND NEIGHBORS",
220                    "${BASEDN}",
221                    "Last success",
222                    "CN=Configuration,${BASEDN}",
223                    "Last success",
224                    "CN=Configuration,${BASEDN}",
225                    "Last success"],
226                    ordered=True,
227                    regex=True)
228
229     t.cmd_contains("bin/samba-tool drs showrepl ${WIN_HOSTNAME}.${LCREALM} -k yes",
230                  [ "INBOUND NEIGHBORS",
231                    "${BASEDN}",
232                    "Last attempt .* was successful",
233                    "CN=Configuration,${BASEDN}",
234                    "Last attempt .* was successful",
235                    "CN=Configuration,${BASEDN}",
236                    "Last attempt .* was successful",
237                    "OUTBOUND NEIGHBORS",
238                    "${BASEDN}",
239                    "Last success",
240                    "CN=Configuration,${BASEDN}",
241                    "Last success",
242                    "CN=Configuration,${BASEDN}",
243                    "Last success" ],
244                    ordered=True,
245                    regex=True)
246
247     child = t.open_telnet("${WIN_HOSTNAME}", "${DOMAIN}\\administrator", "${PASSWORD1}", set_time=True)
248     child.sendline("net use t: \\\\${HOSTNAME}.${LCREALM}\\test")
249
250     retries = 10
251     i = child.expect(["The command completed successfully", "The network path was not found"])
252     while i == 1 and retries > 0:
253         child.expect("C:")
254         time.sleep(2)
255         child.sendline("net use t: \\\\${HOSTNAME}.${LCREALM}\\test")
256         i = child.expect(["The command completed successfully", "The network path was not found"])
257         retries -=1
258
259     t.run_net_time(child)
260
261     t.info("Checking if showrepl is happy")
262     child.sendline("repadmin /showrepl")
263     child.expect("${BASEDN}")
264     child.expect("was successful")
265     child.expect("CN=Configuration,${BASEDN}")
266     child.expect("was successful")
267     child.expect("CN=Schema,CN=Configuration,${BASEDN}")
268     child.expect("was successful")
269
270     t.info("Checking if new users propogate to windows")
271     t.retry_cmd('bin/samba-tool user add test2 ${PASSWORD2}', ["created successfully"])
272     t.retry_cmd("%s -L ${WIN_HOSTNAME}.${LCREALM} -Utest2%%${PASSWORD2} -k no" % (smbclient), ['Sharename', 'Remote IPC'])
273     t.retry_cmd("%s -L ${WIN_HOSTNAME}.${LCREALM} -Utest2%%${PASSWORD2} -k yes" % (smbclient), ['Sharename', 'Remote IPC'])
274
275     t.info("Checking if new users on windows propogate to samba")
276     child.sendline("net user test3 ${PASSWORD3} /add")
277     while True:
278         i = child.expect(["The command completed successfully",
279                           "The directory service was unable to allocate a relative identifier"])
280         if i == 0:
281             break
282         time.sleep(2)
283
284     t.retry_cmd("%s -L ${HOSTNAME}.${LCREALM} -Utest3%%${PASSWORD3} -k no" % (smbclient), ['Sharename', 'IPC'])
285     t.retry_cmd("%s -L ${HOSTNAME}.${LCREALM} -Utest3%%${PASSWORD3} -k yes" % (smbclient), ['Sharename', 'IPC'])
286
287     t.info("Checking propogation of user deletion")
288     t.run_cmd('bin/samba-tool user delete test2 -Uadministrator@${LCREALM}%${PASSWORD1}')
289     child.sendline("net user test3 /del")
290     child.expect("The command completed successfully")
291
292     t.retry_cmd("%s -L ${WIN_HOSTNAME}.${LCREALM} -Utest2%%${PASSWORD2} -k no" % (smbclient), ['LOGON_FAILURE'])
293     t.retry_cmd("%s -L ${HOSTNAME}.${LCREALM} -Utest3%%${PASSWORD3} -k no" % (smbclient), ['LOGON_FAILURE'])
294     t.retry_cmd("%s -L ${WIN_HOSTNAME}.${LCREALM} -Utest2%%${PASSWORD2} -k yes" % (smbclient), ['LOGON_FAILURE'])
295     t.retry_cmd("%s -L ${HOSTNAME}.${LCREALM} -Utest3%%${PASSWORD3} -k yes" % (smbclient), ['LOGON_FAILURE'])
296     t.vm_poweroff("${WIN_VM}")
297
298
299 def run_dcpromo_rodc(t, vm):
300     '''run a RODC dcpromo to join a windows DC to the samba domain'''
301     t.setwinvars(vm)
302     t.info("Joining a w2k8 box to the domain as a RODC")
303     t.vm_poweroff("${WIN_VM}", checkfail=False)
304     t.vm_restore("${WIN_VM}", "${WIN_SNAPSHOT}")
305     child = t.open_telnet("${WIN_HOSTNAME}", "administrator", "${WIN_PASS}", set_ip=True)
306     child.sendline("copy /Y con answers.txt")
307     child.sendline('''
308 [DCInstall]
309 ReplicaOrNewDomain=ReadOnlyReplica
310 ReplicaDomainDNSName=${LCREALM}
311 PasswordReplicationDenied="BUILTIN\Administrators"
312 PasswordReplicationDenied="BUILTIN\Server Operators"
313 PasswordReplicationDenied="BUILTIN\Backup Operators"
314 PasswordReplicationDenied="BUILTIN\Account Operators"
315 PasswordReplicationDenied="${DOMAIN}\Denied RODC Password Replication Group"
316 PasswordReplicationAllowed="${DOMAIN}\Allowed RODC Password Replication Group"
317 DelegatedAdmin="${DOMAIN}\\Administrator"
318 SiteName=Default-First-Site-Name
319 InstallDNS=No
320 ConfirmGc=Yes
321 CreateDNSDelegation=No
322 UserDomain=${LCREALM}
323 UserName=${LCREALM}\\administrator
324 Password=${PASSWORD1}
325 DatabasePath="C:\Windows\NTDS"
326 LogPath="C:\Windows\NTDS"
327 SYSVOLPath="C:\Windows\SYSVOL"
328 SafeModeAdminPassword=${PASSWORD1}
329 RebootOnCompletion=No
330 \1a
331 ''')
332     child.expect("copied.")
333     child.sendline("dcpromo /answer:answers.txt")
334     i = child.expect(["You must restart this computer", "failed", "could not be located in this domain"], timeout=120)
335     if i != 0:
336         child.sendline("echo off")
337         child.sendline("echo START DCPROMO log")
338         child.sendline("more c:\windows\debug\dcpromoui.log")
339         child.sendline("echo END DCPROMO log")
340         child.expect("END DCPROMO")
341         raise Exception("dcpromo failed")
342     child.sendline("shutdown -r -t 0")
343     t.wait_reboot()
344
345
346
347 def test_dcpromo_rodc(t, vm):
348     '''test the RODC dcpromo worked'''
349     t.info("Checking the w2k8 RODC join is OK")
350     smbclient = t.getvar("smbclient")
351     t.chdir('${PREFIX}')
352     t.port_wait("${WIN_IP}", 139)
353     child = t.open_telnet("${WIN_HOSTNAME}", "${DOMAIN}\\administrator", "${PASSWORD1}", set_time=True)
354     child.sendline("ipconfig /registerdns")
355     t.retry_cmd('%s -L ${WIN_HOSTNAME}.${LCREALM} -Uadministrator@${LCREALM}%%${PASSWORD1}' % (smbclient), ["C$", "IPC$", "Sharename"])
356     t.cmd_contains("host -t A ${WIN_HOSTNAME}.${LCREALM}.", ['has address'])
357     t.cmd_contains('%s -L ${WIN_HOSTNAME}.${LCREALM} -Utestallowed@${LCREALM}%%${PASSWORD1}' % (smbclient), ["C$", "IPC$", "Sharename"])
358     child.sendline("net use t: \\\\${HOSTNAME}.${LCREALM}\\test")
359     child.expect("The command completed successfully")
360
361     t.info("Checking if showrepl is happy")
362     child.sendline("repadmin /showrepl")
363     child.expect("${BASEDN}")
364     child.expect("was successful")
365     child.expect("CN=Configuration,${BASEDN}")
366     child.expect("was successful")
367     child.expect("CN=Configuration,${BASEDN}")
368     child.expect("was successful")
369
370     for nc in [ '${BASEDN}', 'CN=Configuration,${BASEDN}', 'CN=Schema,CN=Configuration,${BASEDN}' ]:
371         t.cmd_contains("bin/samba-tool drs replicate --add-ref ${WIN_HOSTNAME}.${LCREALM} ${HOSTNAME}.${LCREALM} %s" % nc, ["was successful"])
372
373     t.cmd_contains("bin/samba-tool drs showrepl ${HOSTNAME}.${LCREALM}",
374                  [ "INBOUND NEIGHBORS",
375                    "OUTBOUND NEIGHBORS",
376                    "${BASEDN}",
377                    "Last attempt.*was successful",
378                    "CN=Configuration,${BASEDN}",
379                    "Last attempt.*was successful",
380                    "CN=Configuration,${BASEDN}",
381                    "Last attempt.*was successful" ],
382                    ordered=True,
383                    regex=True)
384
385     t.info("Checking if new users are available on windows")
386     t.run_cmd('bin/samba-tool user add test2 ${PASSWORD2}')
387     t.retry_cmd("%s -L ${WIN_HOSTNAME}.${LCREALM} -Utest2%%${PASSWORD2} -k yes" % (smbclient), ['Sharename', 'Remote IPC'])
388     t.retry_cmd("bin/samba-tool drs replicate ${WIN_HOSTNAME}.${LCREALM} ${HOSTNAME}.${LCREALM} ${BASEDN}", ["was successful"])
389     t.retry_cmd("%s -L ${WIN_HOSTNAME}.${LCREALM} -Utest2%%${PASSWORD2} -k no" % (smbclient), ['Sharename', 'Remote IPC'])
390     t.run_cmd('bin/samba-tool user delete test2 -Uadministrator@${LCREALM}%${PASSWORD1}')
391     t.retry_cmd("%s -L ${WIN_HOSTNAME}.${LCREALM} -Utest2%%${PASSWORD2} -k yes" % (smbclient), ['LOGON_FAILURE'])
392     t.retry_cmd("%s -L ${WIN_HOSTNAME}.${LCREALM} -Utest2%%${PASSWORD2} -k no" % (smbclient), ['LOGON_FAILURE'])
393     t.vm_poweroff("${WIN_VM}")
394
395
396 def prep_join_as_dc(t, vm):
397     '''start VM and shutdown Samba in preperation to join a windows domain as a DC'''
398     t.info("Starting VMs for joining ${WIN_VM} as a second DC using samba-tool domain join DC")
399     t.chdir('${PREFIX}')
400     t.run_cmd('killall -9 -q samba smbd nmbd winbindd', checkfail=False)
401     if not t.getvar('NAMESERVER_BACKEND') == 'SAMBA_INTERNAL':
402         t.rndc_cmd('flush')
403     t.run_cmd("rm -rf etc/smb.conf private")
404     child = t.open_telnet("${WIN_HOSTNAME}", "${WIN_DOMAIN}\\administrator", "${WIN_PASS}", set_time=True)
405     t.get_ipconfig(child)
406
407 def join_as_dc(t, vm):
408     '''join a windows domain as a DC'''
409     t.setwinvars(vm)
410     t.info("Joining ${WIN_VM} as a second DC using samba-tool domain join DC")
411     t.port_wait("${WIN_IP}", 389)
412     t.retry_cmd("host -t SRV _ldap._tcp.${WIN_REALM} ${WIN_IP}", ['has SRV record'] )
413
414     t.retry_cmd("bin/samba-tool drs showrepl ${WIN_HOSTNAME}.${WIN_REALM} -Uadministrator%${WIN_PASS}", ['INBOUND NEIGHBORS'] )
415     t.run_cmd('bin/samba-tool domain join ${WIN_REALM} DC -Uadministrator%${WIN_PASS} -d${DEBUGLEVEL} --option=interfaces=${INTERFACE}')
416     t.run_cmd('bin/samba-tool drs kcc ${WIN_HOSTNAME}.${WIN_REALM} -Uadministrator@${WIN_REALM}%${WIN_PASS}')
417
418
419 def test_join_as_dc(t, vm):
420     '''test the join of a windows domain as a DC'''
421     t.info("Checking the DC join is OK")
422     smbclient = t.getvar("smbclient")
423     t.chdir('${PREFIX}')
424     t.retry_cmd('%s -L ${HOSTNAME}.${WIN_REALM} -Uadministrator@${WIN_REALM}%%${WIN_PASS}' % (smbclient), ["C$", "IPC$", "Sharename"])
425     t.cmd_contains("host -t A ${HOSTNAME}.${WIN_REALM}.", ['has address'])
426     child = t.open_telnet("${WIN_HOSTNAME}", "${WIN_DOMAIN}\\administrator", "${WIN_PASS}", set_time=True)
427
428     t.info("Forcing kcc runs, and replication")
429     t.run_cmd('bin/samba-tool drs kcc ${WIN_HOSTNAME}.${WIN_REALM} -Uadministrator@${WIN_REALM}%${WIN_PASS}')
430     t.run_cmd('bin/samba-tool drs kcc ${HOSTNAME}.${WIN_REALM} -Uadministrator@${WIN_REALM}%${WIN_PASS}')
431
432     t.kinit("administrator@${WIN_REALM}", "${WIN_PASS}")
433     for nc in [ '${WIN_BASEDN}', 'CN=Configuration,${WIN_BASEDN}', 'CN=Schema,CN=Configuration,${WIN_BASEDN}' ]:
434         t.cmd_contains("bin/samba-tool drs replicate ${HOSTNAME}.${WIN_REALM} ${WIN_HOSTNAME}.${WIN_REALM} %s -k yes" % nc, ["was successful"])
435         t.cmd_contains("bin/samba-tool drs replicate ${WIN_HOSTNAME}.${WIN_REALM} ${HOSTNAME}.${WIN_REALM} %s -k yes" % nc, ["was successful"])
436
437     child.sendline("ipconfig /flushdns")
438     child.expect("Successfully flushed")
439
440     retries = 10
441     i = 1
442     while i == 1 and retries > 0:
443         child.sendline("net use t: \\\\${HOSTNAME}.${WIN_REALM}\\test")
444         i = child.expect(["The command completed successfully", "The network path was not found"])
445         child.expect("C:")
446         if i == 1:
447             time.sleep(2)
448         retries -=1
449
450     t.info("Checking if showrepl is happy")
451     child.sendline("repadmin /showrepl")
452     child.expect("${WIN_BASEDN}")
453     child.expect("was successful")
454     child.expect("CN=Configuration,${WIN_BASEDN}")
455     child.expect("was successful")
456     child.expect("CN=Configuration,${WIN_BASEDN}")
457     child.expect("was successful")
458
459     t.info("Checking if new users propogate to windows")
460     t.retry_cmd('bin/samba-tool user add test2 ${PASSWORD2}', ["created successfully"])
461     t.retry_cmd("%s -L ${WIN_HOSTNAME}.${WIN_REALM} -Utest2%%${PASSWORD2} -k no" % (smbclient), ['Sharename', 'Remote IPC'])
462     t.retry_cmd("%s -L ${WIN_HOSTNAME}.${WIN_REALM} -Utest2%%${PASSWORD2} -k yes" % (smbclient), ['Sharename', 'Remote IPC'])
463
464     t.info("Checking if new users on windows propogate to samba")
465     child.sendline("net user test3 ${PASSWORD3} /add")
466     child.expect("The command completed successfully")
467     t.retry_cmd("%s -L ${HOSTNAME}.${WIN_REALM} -Utest3%%${PASSWORD3} -k no" % (smbclient), ['Sharename', 'IPC'])
468     t.retry_cmd("%s -L ${HOSTNAME}.${WIN_REALM} -Utest3%%${PASSWORD3} -k yes" % (smbclient), ['Sharename', 'IPC'])
469
470     t.info("Checking propogation of user deletion")
471     t.run_cmd('bin/samba-tool user delete test2 -Uadministrator@${WIN_REALM}%${WIN_PASS}')
472     child.sendline("net user test3 /del")
473     child.expect("The command completed successfully")
474
475     t.retry_cmd("%s -L ${WIN_HOSTNAME}.${WIN_REALM} -Utest2%%${PASSWORD2} -k no" % (smbclient), ['LOGON_FAILURE'])
476     t.retry_cmd("%s -L ${HOSTNAME}.${WIN_REALM} -Utest3%%${PASSWORD3} -k no" % (smbclient), ['LOGON_FAILURE'])
477     t.retry_cmd("%s -L ${WIN_HOSTNAME}.${WIN_REALM} -Utest2%%${PASSWORD2} -k yes" % (smbclient), ['LOGON_FAILURE'])
478     t.retry_cmd("%s -L ${HOSTNAME}.${WIN_REALM} -Utest3%%${PASSWORD3} -k yes" % (smbclient), ['LOGON_FAILURE'])
479
480     t.run_cmd('bin/samba-tool domain demote -Uadministrator@${WIN_REALM}%${WIN_PASS}')
481
482     t.vm_poweroff("${WIN_VM}")
483
484
485 def join_as_rodc(t, vm):
486     '''join a windows domain as a RODC'''
487     t.setwinvars(vm)
488     t.info("Joining ${WIN_VM} as a RODC using samba-tool domain join DC")
489     t.port_wait("${WIN_IP}", 389)
490     t.retry_cmd("host -t SRV _ldap._tcp.${WIN_REALM} ${WIN_IP}", ['has SRV record'] )
491     t.retry_cmd("bin/samba-tool drs showrepl ${WIN_HOSTNAME}.${WIN_REALM} -Uadministrator%${WIN_PASS}", ['INBOUND NEIGHBORS'] )
492     t.run_cmd('bin/samba-tool domain join ${WIN_REALM} RODC -Uadministrator%${WIN_PASS} -d${DEBUGLEVEL} --option=interfaces=${INTERFACE}')
493     t.run_cmd('bin/samba-tool drs kcc ${WIN_HOSTNAME}.${WIN_REALM} -Uadministrator@${WIN_REALM}%${WIN_PASS}')
494
495
496 def test_join_as_rodc(t, vm):
497     '''test a windows domain RODC join'''
498     t.info("Checking the RODC join is OK")
499     smbclient = t.getvar("smbclient")
500     t.chdir('${PREFIX}')
501     t.retry_cmd('%s -L ${HOSTNAME}.${WIN_REALM} -Uadministrator@${WIN_REALM}%%${WIN_PASS}' % (smbclient), ["C$", "IPC$", "Sharename"])
502     t.cmd_contains("host -t A ${HOSTNAME}.${WIN_REALM}.", ['has address'])
503     child = t.open_telnet("${WIN_HOSTNAME}", "${WIN_DOMAIN}\\administrator", "${WIN_PASS}", set_time=True)
504
505     t.info("Forcing kcc runs, and replication")
506     t.run_cmd('bin/samba-tool drs kcc ${HOSTNAME}.${WIN_REALM} -Uadministrator@${WIN_REALM}%${WIN_PASS}')
507     t.run_cmd('bin/samba-tool drs kcc ${WIN_HOSTNAME}.${WIN_REALM} -Uadministrator@${WIN_REALM}%${WIN_PASS}')
508
509     t.kinit("administrator@${WIN_REALM}", "${WIN_PASS}")
510     for nc in [ '${WIN_BASEDN}', 'CN=Configuration,${WIN_BASEDN}', 'CN=Schema,CN=Configuration,${WIN_BASEDN}' ]:
511         t.cmd_contains("bin/samba-tool drs replicate ${HOSTNAME}.${WIN_REALM} ${WIN_HOSTNAME}.${WIN_REALM} %s -k yes" % nc, ["was successful"])
512
513     retries = 10
514     i = 1
515     while i == 1 and retries > 0:
516         child.sendline("net use t: \\\\${HOSTNAME}.${WIN_REALM}\\test")
517         i = child.expect(["The command completed successfully", "The network path was not found"])
518         child.expect("C:")
519         if i == 1:
520             time.sleep(2)
521         retries -=1
522
523     t.info("Checking if showrepl is happy")
524     child.sendline("repadmin /showrepl")
525     child.expect("DSA invocationID")
526
527     t.cmd_contains("bin/samba-tool drs showrepl ${WIN_HOSTNAME}.${WIN_REALM} -k yes",
528                  [ "INBOUND NEIGHBORS",
529                    "OUTBOUND NEIGHBORS",
530                    "${WIN_BASEDN}",
531                    "Last attempt .* was successful",
532                    "CN=Configuration,${WIN_BASEDN}",
533                    "Last attempt .* was successful",
534                    "CN=Configuration,${WIN_BASEDN}",
535                    "Last attempt .* was successful" ],
536                    ordered=True,
537                    regex=True)
538
539     t.info("Checking if new users on windows propogate to samba")
540     child.sendline("net user test3 ${PASSWORD3} /add")
541     child.expect("The command completed successfully")
542     t.retry_cmd("%s -L ${HOSTNAME}.${WIN_REALM} -Utest3%%${PASSWORD3} -k no" % (smbclient), ['Sharename', 'IPC'])
543     t.retry_cmd("%s -L ${HOSTNAME}.${WIN_REALM} -Utest3%%${PASSWORD3} -k yes" % (smbclient), ['Sharename', 'IPC'])
544
545     # should this work?
546     t.info("Checking if new users propogate to windows")
547     t.cmd_contains('bin/samba-tool user add test2 ${PASSWORD2}', ['No RID Set DN'])
548
549     t.info("Checking propogation of user deletion")
550     child.sendline("net user test3 /del")
551     child.expect("The command completed successfully")
552
553     t.retry_cmd("%s -L ${HOSTNAME}.${WIN_REALM} -Utest3%%${PASSWORD3} -k no" % (smbclient), ['LOGON_FAILURE'])
554     t.retry_cmd("%s -L ${HOSTNAME}.${WIN_REALM} -Utest3%%${PASSWORD3} -k yes" % (smbclient), ['LOGON_FAILURE'])
555     t.vm_poweroff("${WIN_VM}")
556
557
558 def test_howto(t):
559     '''test the Samba4 howto'''
560
561     t.setvar("SAMBA_VERSION", "Version 4")
562     t.setvar("smbclient", "bin/smbclient4")
563     t.check_prerequesites()
564
565     # we don't need fsync safety in these tests
566     t.putenv('TDB_NO_FSYNC', '1')
567
568     if not t.skip("configure_bind"):
569         t.configure_bind(kerberos_support=True, include='${PREFIX}/private/named.conf')
570     if not t.skip("stop_bind"):
571         t.stop_bind()
572
573     if not t.skip("stop_vms"):
574         t.stop_vms()
575
576     if not t.skip("build"):
577         build_s4(t)
578
579     if not t.skip("provision"):
580         provision_s4(t)
581
582     set_krb5_conf(t)
583
584     if not t.skip("create-shares"):
585         create_shares(t)
586
587     if not t.skip("starts4"):
588         start_s4(t)
589     if not t.skip("smbclient"):
590         test_smbclient(t)
591
592     if not t.skip("configure_bind2"):
593         t.configure_bind(kerberos_support=True, include='${PREFIX}/private/named.conf')
594     if not t.skip("start_bind"):
595         t.start_bind()
596
597     if not t.skip("dns"):
598         test_dns(t)
599     if not t.skip("kerberos"):
600         test_kerberos(t)
601     if not t.skip("dyndns"):
602         test_dyndns(t)
603
604     if t.have_vm('WINDOWS7') and not t.skip("windows7"):
605         t.start_winvm("WINDOWS7")
606         t.test_remote_smbclient("WINDOWS7")
607         run_winjoin(t, "WINDOWS7")
608         test_winjoin(t, "WINDOWS7")
609         t.vm_poweroff("${WIN_VM}")
610
611     if t.have_vm('WINXP') and not t.skip("winxp"):
612         t.start_winvm("WINXP")
613         run_winjoin(t, "WINXP")
614         test_winjoin(t, "WINXP")
615         t.test_remote_smbclient("WINXP", "administrator", "${PASSWORD1}")
616         t.vm_poweroff("${WIN_VM}")
617
618     if t.have_vm('W2K3C') and not t.skip("win2k3_member"):
619         t.start_winvm("W2K3C")
620         run_winjoin(t, "W2K3C")
621         test_winjoin(t, "W2K3C")
622         t.test_remote_smbclient("W2K3C", "administrator", "${PASSWORD1}")
623         t.vm_poweroff("${WIN_VM}")
624
625     if t.have_vm('W2K8R2C') and not t.skip("dcpromo_rodc"):
626         t.info("Testing w2k8r2 RODC dcpromo")
627         t.start_winvm("W2K8R2C")
628         t.test_remote_smbclient('W2K8R2C')
629         run_dcpromo_rodc(t, "W2K8R2C")
630         test_dcpromo_rodc(t, "W2K8R2C")
631
632     if t.have_vm('W2K8R2B') and not t.skip("dcpromo_w2k8r2"):
633         t.info("Testing w2k8r2 dcpromo")
634         t.start_winvm("W2K8R2B")
635         t.test_remote_smbclient('W2K8R2B')
636         run_dcpromo(t, "W2K8R2B")
637         test_dcpromo(t, "W2K8R2B")
638
639     if t.have_vm('W2K8B') and not t.skip("dcpromo_w2k8"):
640         t.info("Testing w2k8 dcpromo")
641         t.start_winvm("W2K8B")
642         t.test_remote_smbclient('W2K8B')
643         run_dcpromo(t, "W2K8B")
644         test_dcpromo(t, "W2K8B")
645
646     if t.have_vm('W2K3B') and not t.skip("dcpromo_w2k3"):
647         t.info("Testing w2k3 dcpromo")
648         t.info("Changing to 2003 functional level")
649         provision_s4(t, func_level='2003')
650         create_shares(t)
651         start_s4(t)
652         test_smbclient(t)
653         t.restart_bind(kerberos_support=True, include='${PREFIX}/private/named.conf')
654         test_dns(t)
655         test_kerberos(t)
656         test_dyndns(t)
657         t.start_winvm("W2K3B")
658         t.test_remote_smbclient('W2K3B')
659         run_dcpromo(t, "W2K3B")
660         test_dcpromo(t, "W2K3B")
661
662     if t.have_vm('W2K8R2A') and not t.skip("join_w2k8r2"):
663         t.start_winvm("W2K8R2A")
664         prep_join_as_dc(t, "W2K8R2A")
665         t.run_dcpromo_as_first_dc("W2K8R2A", func_level='2008r2')
666         join_as_dc(t, "W2K8R2A")
667         create_shares(t)
668         start_s4(t)
669         test_dyndns(t)
670         test_join_as_dc(t, "W2K8R2A")
671
672     if t.have_vm('W2K8R2A') and not t.skip("join_rodc"):
673         t.start_winvm("W2K8R2A")
674         prep_join_as_dc(t, "W2K8R2A")
675         t.run_dcpromo_as_first_dc("W2K8R2A", func_level='2008r2')
676         join_as_rodc(t, "W2K8R2A")
677         create_shares(t)
678         start_s4(t)
679         test_dyndns(t)
680         test_join_as_rodc(t, "W2K8R2A")
681
682     if t.have_vm('W2K3A') and not t.skip("join_w2k3"):
683         t.start_winvm("W2K3A")
684         prep_join_as_dc(t, "W2K3A")
685         t.run_dcpromo_as_first_dc("W2K3A", func_level='2003')
686         join_as_dc(t, "W2K3A")
687         create_shares(t)
688         start_s4(t)
689         test_dyndns(t)
690         test_join_as_dc(t, "W2K3A")
691
692     t.info("Howto test: All OK")
693
694
695 def test_cleanup(t):
696     '''cleanup after tests'''
697     t.info("Cleaning up ...")
698     t.restore_resolv_conf()
699     if getattr(t, 'bind_child', False):
700         t.bind_child.kill()
701
702
703 if __name__ == '__main__':
704     t = wintest.wintest()
705
706     t.setup("test-s4-howto.py", "source4")
707
708     try:
709         test_howto(t)
710     except:
711         if not t.opts.nocleanup:
712             test_cleanup(t)
713         raise
714
715     if not t.opts.nocleanup:
716         test_cleanup(t)
717     t.info("S4 howto test: All OK")