wintest Add testing of kerberos connections to Windows members of an AD domain
authorAndrew Bartlett <abartlet@samba.org>
Mon, 13 Dec 2010 23:53:34 +0000 (10:53 +1100)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 14 Dec 2010 00:54:46 +0000 (01:54 +0100)
This improves the Samba3 wintest script to test against Windows7 and
WinXP domain members, and Windows7 standalone servers.  To do this,
more of the samba4 script is put in common, and we splut up the
starting of the VMs from the preperation of the VM.

This also improves the nmblookup command parsing to cope with both the
samba3 and samba4 nmblookup commands.

A krb5.conf is now provided for both s3 and s4 tests.

Andrew Bartlett

Autobuild-User: Andrew Bartlett <abartlet@samba.org>
Autobuild-Date: Tue Dec 14 01:54:46 CET 2010 on sn-devel-104

wintest/test-s3.py
wintest/test-s4-howto.py
wintest/wintest.py

index 33f4aca..3002777 100755 (executable)
@@ -9,6 +9,15 @@ import wintest
 def set_libpath(t):
     t.putenv("LD_LIBRARY_PATH", "${PREFIX}/lib")
 
+def set_krb5_conf(t):
+    t.run_cmd("mkdir -p ${PREFIX}/etc")
+    t.write_file("${PREFIX}/etc/krb5.conf", 
+                    '''[libdefaults]
+       dns_lookup_realm = false
+       dns_lookup_kdc = true''')
+
+    t.putenv("KRB5_CONFIG", '${PREFIX}/etc/krb5.conf')
+
 def build_s3(t):
     '''build samba3'''
     t.info('Building s3')
@@ -31,7 +40,6 @@ def start_s3(t):
     t.run_cmd(['sbin/smbd', "-D"])
     t.port_wait("${INTERFACE_IP}", 139)
 
-
 def test_wbinfo(t):
     t.info('Testing wbinfo')
     t.chdir('${PREFIX}')
@@ -69,7 +77,18 @@ def test_smbclient(t):
     t.cmd_contains("bin/smbclient --version", ["Version 3."])
     t.cmd_contains('bin/smbclient -L ${INTERFACE_IP} -U%', ["Domain=[${WIN_DOMAIN}]", "test", "IPC$", "Samba 3."],
                    casefold=True)
-    child = t.pexpect_spawn('bin/smbclient //${HOSTNAME}.${WIN_REALM}/test -Uroot%${PASSWORD2}')
+    child = t.pexpect_spawn('bin/smbclient //${HOSTNAME}.${WIN_REALM}/test -Uroot@${WIN_REALM}%${PASSWORD2}')
+    child.expect("smb:")
+    child.sendline("dir")
+    child.expect("blocks available")
+    child.sendline("mkdir testdir")
+    child.expect("smb:")
+    child.sendline("cd testdir")
+    child.expect('testdir')
+    child.sendline("cd ..")
+    child.sendline("rmdir testdir")
+
+    child = t.pexpect_spawn('bin/smbclient //${HOSTNAME}.${WIN_REALM}/test -Uroot@${WIN_REALM}%${PASSWORD2} -k')
     child.expect("smb:")
     child.sendline("dir")
     child.expect("blocks available")
@@ -160,6 +179,7 @@ def test_join_as_member(t, vm):
 def test_s3(t):
     '''basic s3 testing'''
 
+    t.setvar("SAMBA_VERSION", "Version 3")
     t.check_prerequesites()
     set_libpath(t)
 
@@ -173,12 +193,16 @@ def test_s3(t):
     if not t.skip("build"):
         build_s3(t)
 
+    set_krb5_conf(t)
     if not t.skip("configure_bind2"):
         t.configure_bind()
     if not t.skip("start_bind"):
         t.start_bind()
 
+    dc_started = False
     if t.have_var('W2K8R2A_VM') and not t.skip("join_w2k8r2"):
+        t.start_winvm('W2K8R2A')
+        dc_started = True
         prep_join_as_member(t, "W2K8R2A")
         t.run_dcpromo_as_first_dc("W2K8R2A", func_level='2008r2')
         join_as_member(t, "W2K8R2A")
@@ -186,6 +210,43 @@ def test_s3(t):
         start_s3(t)
         test_join_as_member(t, "W2K8R2A")
 
+    if t.have_var('WINDOWS7_VM') and t.have_var('W2K8R2A_VM') and not t.skip("join_windows7_2008r2"):
+        if not dc_started:
+            t.start_winvm('W2K8R2A')
+            t.run_dcpromo_as_first_dc("W2K8R2A", func_level='2008r2')
+            dc_started = True
+        else:
+            t.setwinvars('W2K8R2A')
+        realm = t.getvar("WIN_REALM")
+        dom_username = t.getvar("WIN_USER")
+        dom_password = t.getvar("WIN_PASS")
+        dom_realm = t.getvar("WIN_REALM")
+        t.start_winvm('WINDOWS7')
+        t.test_remote_smbclient("WINDOWS7")
+        t.run_winjoin('WINDOWS7', realm, username=dom_username, password=dom_password)
+        t.test_remote_smbclient("WINDOWS7", dom_username, dom_password)
+        t.test_remote_smbclient('WINDOWS7', dom_username, dom_password, args='--option=clientntlmv2auth=no')
+        t.test_remote_smbclient('WINDOWS7', "%s@%s" % (dom_username, dom_realm), dom_password, args="-k")
+        t.test_remote_smbclient('WINDOWS7', "%s@%s" % (dom_username, dom_realm), dom_password, args="-k --option=clientusespnegoprincipal=yes")
+
+    if t.have_var('WINXP_VM') and t.have_var('W2K8R2A_VM') and not t.skip("join_winxp_2008r2"):
+        if not dc_started:
+            t.start_winvm('W2K8R2A')
+            t.run_dcpromo_as_first_dc("W2K8R2A", func_level='2008r2')
+            dc_started = True
+        else:
+            t.setwinvars('W2K8R2A')
+        realm = t.getvar("WIN_REALM")
+        dom_username = t.getvar("WIN_USER")
+        dom_password = t.getvar("WIN_PASS")
+        dom_realm = t.getvar("WIN_REALM")
+        t.start_winvm('WINXP')
+        t.run_winjoin('WINXP', realm, username=dom_username, password=dom_password)
+        t.test_remote_smbclient('WINXP', dom_username, dom_password)
+        t.test_remote_smbclient('WINXP', dom_username, dom_password, args='--option=clientntlmv2auth=no')
+        t.test_remote_smbclient('WINXP', "%s@%s" % (dom_username, dom_realm), dom_password, args="-k")
+        t.test_remote_smbclient('WINXP', "%s@%s" % (dom_username, dom_realm), dom_password, args="-k --clientusespnegoprincipal=yes")
+
     t.info("S3 test: All OK")
 
 
index 63a27d2..c4a430c 100755 (executable)
@@ -5,6 +5,9 @@
 import sys, os
 import wintest, pexpect, time, subprocess
 
+def set_krb5_conf(t):
+    t.putenv("KRB5_CONFIG", '${PREFIX}/private/krb5.conf')
+
 def build_s4(t):
     '''build samba4'''
     t.info('Building s4')
@@ -51,7 +54,7 @@ def start_s4(t):
     t.port_wait("${INTERFACE_IP}", 139)
 
 def test_smbclient(t):
-    '''test smbclient'''
+    '''test smbclient against localhost'''
     t.info('Testing smbclient')
     t.chdir('${PREFIX}')
     t.cmd_contains("bin/smbclient --version", ["Version 4.0"])
@@ -115,21 +118,7 @@ def run_winjoin(t, vm):
     '''join a windows box to our domain'''
     t.setwinvars(vm)
 
-    t.info("Joining a windows box to the domain")
-    t.vm_poweroff("${WIN_VM}", checkfail=False)
-    t.vm_restore("${WIN_VM}", "${WIN_SNAPSHOT}")
-    child = t.open_telnet("${WIN_HOSTNAME}", "${WIN_USER}", "${WIN_PASS}", set_time=True, set_ip=True, set_noexpire=True)
-    child.sendline("ipconfig /flushdns")
-    child.expect("C:")
-    child.sendline("netdom join ${WIN_HOSTNAME} /Domain:${LCREALM} /PasswordD:${PASSWORD1} /UserD:administrator")
-    child.expect("The command completed successfully")
-    child.expect("C:")
-    child.sendline("shutdown /r -t 0")
-    t.wait_reboot()
-    child = t.open_telnet("${WIN_HOSTNAME}", "${WIN_USER}", "${WIN_PASS}", set_time=True, set_ip=True)
-    child.sendline("ipconfig /registerdns")
-    child.expect("Registration of the DNS resource records for all adapters of this computer has been initiated. Any errors will be reported in the Event Viewer")
-    child.expect("C:")
+    t.run_winjoin(t, "${LCREALM}")
 
 def test_winjoin(t, vm):
     t.info("Checking the windows join is OK")
@@ -143,7 +132,6 @@ def test_winjoin(t, vm):
     child = t.open_telnet("${WIN_HOSTNAME}", "${DOMAIN}\\administrator", "${PASSWORD1}")
     child.sendline("net use t: \\\\${HOSTNAME}.${LCREALM}\\test")
     child.expect("The command completed successfully")
-    t.vm_poweroff("${WIN_VM}")
 
 
 def run_dcpromo(t, vm):
@@ -151,8 +139,6 @@ def run_dcpromo(t, vm):
     t.setwinvars(vm)
 
     t.info("Joining a windows VM ${WIN_VM} to the domain as a DC using dcpromo")
-    t.vm_poweroff("${WIN_VM}", checkfail=False)
-    t.vm_restore("${WIN_VM}", "${WIN_SNAPSHOT}")
     child = t.open_telnet("${WIN_HOSTNAME}", "administrator", "${WIN_PASS}", set_ip=True, set_noexpire=True)
     child.sendline("copy /Y con answers.txt")
     child.sendline('''
@@ -389,12 +375,9 @@ def test_dcpromo_rodc(t, vm):
 
 def prep_join_as_dc(t, vm):
     '''start VM and shutdown Samba in preperation to join a windows domain as a DC'''
-    t.setwinvars(vm)
     t.info("Starting VMs for joining ${WIN_VM} as a second DC using samba-tool join DC")
     t.chdir('${PREFIX}')
     t.run_cmd('killall -9 -q samba smbd nmbd winbindd', checkfail=False)
-    t.vm_poweroff("${WIN_VM}", checkfail=False)
-    t.vm_restore("${WIN_VM}", "${WIN_SNAPSHOT}")
     t.rndc_cmd('flush')
     t.run_cmd("rm -rf etc/smb.conf private")
     child = t.open_telnet("${WIN_HOSTNAME}", "${WIN_DOMAIN}\\administrator", "${WIN_PASS}", set_time=True)
@@ -546,6 +529,7 @@ def test_join_as_rodc(t, vm):
 def test_howto(t):
     '''test the Samba4 howto'''
 
+    t.setvar("SAMBA_VERSION", "Version 4")
     t.check_prerequesites()
 
     # we don't need fsync safety in these tests
@@ -564,6 +548,8 @@ def test_howto(t):
     if not t.skip("provision"):
         provision_s4(t)
 
+    set_krb5_conf(t)
+
     if not t.skip("create-shares"):
         create_shares(t)
 
@@ -583,25 +569,37 @@ def test_howto(t):
         test_dyndns(t)
 
     if t.have_vm('WINDOWS7') and not t.skip("windows7"):
+        t.start_winvm("WINDOWS7")
+        t.test_remote_smbclient("WINDOWS7")
         run_winjoin(t, "WINDOWS7")
         test_winjoin(t, "WINDOWS7")
+        t.vm_poweroff("${WIN_VM}")
 
     if t.have_vm('WINXP') and not t.skip("winxp"):
+        t.start_winvm("WINXP")
         run_winjoin(t, "WINXP")
         test_winjoin(t, "WINXP")
+        t.test_remote_smbclient("WINXP", "administrator", "${PASSWORD1}")
+        t.vm_poweroff("${WIN_VM}")
 
     if t.have_vm('W2K8R2C') and not t.skip("dcpromo_rodc"):
         t.info("Testing w2k8r2 RODC dcpromo")
+        t.start_winvm("W2K8R2C")
+        t.test_remote_smbclient('W2K8R2C')
         run_dcpromo_rodc(t, "W2K8R2C")
         test_dcpromo_rodc(t, "W2K8R2C")
 
     if t.have_vm('W2K8R2B') and not t.skip("dcpromo_w2k8r2"):
         t.info("Testing w2k8r2 dcpromo")
+        t.start_winvm("W2K8R2B")
+        t.test_remote_smbclient('W2K8R2B')
         run_dcpromo(t, "W2K8R2B")
         test_dcpromo(t, "W2K8R2B")
 
     if t.have_vm('W2K8B') and not t.skip("dcpromo_w2k8"):
         t.info("Testing w2k8 dcpromo")
+        t.start_winvm("W2K8B")
+        t.test_remote_smbclient('W2K8B')
         run_dcpromo(t, "W2K8B")
         test_dcpromo(t, "W2K8B")
 
@@ -616,10 +614,13 @@ def test_howto(t):
         test_dns(t)
         test_kerberos(t)
         test_dyndns(t)
+        t.start_winvm("W2K3B")
+        t.test_remote_smbclient('W2K3B')
         run_dcpromo(t, "W2K3B")
         test_dcpromo(t, "W2K3B")
 
     if t.have_vm('W2K8R2A') and not t.skip("join_w2k8r2"):
+        t.start_winvm("W2K8R2A")
         prep_join_as_dc(t, "W2K8R2A")
         t.run_dcpromo_as_first_dc("W2K8R2A", func_level='2008r2')
         join_as_dc(t, "W2K8R2A")
@@ -629,6 +630,7 @@ def test_howto(t):
         test_join_as_dc(t, "W2K8R2A")
 
     if t.have_vm('W2K8R2A') and not t.skip("join_rodc"):
+        t.start_winvm("W2K8R2A")
         prep_join_as_dc(t, "W2K8R2A")
         t.run_dcpromo_as_first_dc("W2K8R2A", func_level='2008r2')
         join_as_rodc(t, "W2K8R2A")
index af4588f..10bc562 100644 (file)
@@ -57,6 +57,8 @@ class wintest():
             self.setvar("WIN_LCREALM", self.getvar("WIN_REALM").lower())
             dnsdomain = self.getvar("WIN_REALM")
             self.setvar("WIN_BASEDN", "DC=" + dnsdomain.replace(".", ",DC="))
+        if self.getvar("WIN_USER") is None:
+            self.setvar("WIN_USER", "administrator")
 
     def info(self, msg):
         '''print some information'''
@@ -343,7 +345,6 @@ nameserver %s
                          '''tkey-gssapi-credential "DNS/${LCREALM}";
                             tkey-domain "${LCREALM}";
                  ''')
-            self.putenv("KRB5_CONFIG", '${PREFIX}/private/krb5.conf')
             self.putenv('KEYTAB_FILE', '${PREFIX}/private/dns.keytab')
             self.putenv('KRB5_KTNAME', '${PREFIX}/private/dns.keytab')
 
@@ -621,8 +622,12 @@ options {
         '''resolve an IP given a hostname, assuming NBT'''
         while retries > 0:
             child = self.pexpect_spawn("bin/nmblookup %s" % hostname)
-            i = child.expect(['\d+.\d+.\d+.\d+', "Lookup failed"])
-            if i == 0:
+            i = 0
+            while i == 0:
+                i = child.expect(["querying", '\d+.\d+.\d+.\d+', hostname, "Lookup failed"])
+                if i == 0:
+                    child.expect("\r")
+            if i == 1:
                 return child.after
             retries -= 1
             time.sleep(delay)
@@ -802,6 +807,40 @@ RebootOnCompletion=No
         child.sendline("shutdown -r -t 0")
         self.port_wait("${WIN_IP}", 139, wait_for_fail=True)
         self.port_wait("${WIN_IP}", 139)
+        self.retry_cmd("host -t SRV _ldap._tcp.${WIN_REALM} ${WIN_IP}", ['has SRV record'] )
+
+
+    def start_winvm(self, vm):
+        '''start a Windows VM'''
+        self.setwinvars(vm)
+        
+        self.info("Joining a windows box to the domain")
+        self.vm_poweroff("${WIN_VM}", checkfail=False)
+        self.vm_restore("${WIN_VM}", "${WIN_SNAPSHOT}")
+
+    def run_winjoin(self, vm, domain, username="administrator", password="${PASSWORD1}"):
+        '''join a windows box to a domain'''
+        child = self.open_telnet("${WIN_HOSTNAME}", "${WIN_USER}", "${WIN_PASS}", set_time=True, set_ip=True, set_noexpire=True)
+        child.sendline("ipconfig /flushdns")
+        child.expect("C:")
+        child.sendline("netdom join ${WIN_HOSTNAME} /Domain:%s /UserD:%s /PasswordD:%s" % (domain, username, password))
+        child.expect("The command completed successfully")
+        child.expect("C:")
+        child.sendline("shutdown /r -t 0")
+        self.wait_reboot()
+        child = self.open_telnet("${WIN_HOSTNAME}", "${WIN_USER}", "${WIN_PASS}", set_time=True, set_ip=True)
+        child.sendline("ipconfig /registerdns")
+        child.expect("Registration of the DNS resource records for all adapters of this computer has been initiated. Any errors will be reported in the Event Viewer")
+        child.expect("C:")
+
+
+    def test_remote_smbclient(self, vm, username="${WIN_USER}", password="${WIN_PASS}", args=""):
+        '''test smbclient against remote server'''
+        self.setwinvars(vm)
+        self.info('Testing smbclient')
+        self.chdir('${PREFIX}')
+        self.cmd_contains("bin/smbclient --version", ["${SAMBA_VERSION}"])
+        self.retry_cmd('bin/smbclient -L ${WIN_HOSTNAME} -U%s%%%s %s' % (username, password, args), ["IPC"])
 
 
     def setup(self, testname, subdir):