From 8daa83a594a2e98f39d764422bfbdbc62c9efd44 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 19:20:00 +0200 Subject: Adding upstream version 2:4.20.0+dfsg. Signed-off-by: Daniel Baumann --- source3/script/count_80_col.pl | 16 + source3/script/creategroup | 25 + source3/script/fix_bool.pl | 19 + source3/script/format_indent.sh | 12 + source3/script/makeunicodecasemap.awk | 59 + source3/script/mknissmbpasswd.sh | 28 + source3/script/mknissmbpwdtbl.sh | 41 + source3/script/mksmbpasswd.sh | 6 + source3/script/mksyms.awk | 76 + source3/script/mksyms.sh | 46 + source3/script/samba-log-parser | 382 ++++ source3/script/scancvslog.pl | 112 + source3/script/smbaddshare | 32 + source3/script/smbchangeshare | 47 + source3/script/smbdeleteshare | 21 + source3/script/smbtar | 181 ++ source3/script/strip_trail_ws.pl | 18 + source3/script/tests/dlopen.sh | 90 + source3/script/tests/fake_snap.pl | 85 + source3/script/tests/full_audit_segfault/run.sh | 25 + .../script/tests/full_audit_segfault/vfstest.cmd | 3 + source3/script/tests/getset_quota.py | 154 ++ source3/script/tests/printing/modprinter.pl | 140 ++ .../tests/printing/printing_var_exp_lpr_cmd.sh | 9 + source3/script/tests/smbspool_argv_wrapper.c | 72 + source3/script/tests/stream-depot/run.sh | 36 + source3/script/tests/stream-depot/vfstest.cmd | 5 + source3/script/tests/test_acl_xattr.sh | 156 ++ source3/script/tests/test_aio_outstanding.sh | 99 + source3/script/tests/test_async_req.sh | 14 + source3/script/tests/test_bad_auditnames.sh | 29 + source3/script/tests/test_bug15435_widelink_dfs.sh | 28 + source3/script/tests/test_chdir_cache.sh | 122 + source3/script/tests/test_close_denied_share.sh | 78 + source3/script/tests/test_deadtime.sh | 67 + source3/script/tests/test_delete_stream.sh | 123 + .../tests/test_delete_veto_files_only_rmdir.sh | 182 ++ source3/script/tests/test_dfree_command.sh | 69 + source3/script/tests/test_dfree_quota.sh | 296 +++ source3/script/tests/test_dropbox.sh | 88 + .../script/tests/test_durable_handle_reconnect.sh | 36 + source3/script/tests/test_failure.sh | 34 + source3/script/tests/test_fakedircreatetimes.sh | 65 + source3/script/tests/test_fifo.sh | 83 + source3/script/tests/test_force_close_share.sh | 115 + source3/script/tests/test_force_create_mode.sh | 72 + source3/script/tests/test_force_group_change.sh | 73 + source3/script/tests/test_force_user_unlink.sh | 41 + source3/script/tests/test_forceuser_validusers.sh | 60 + source3/script/tests/test_fruit_resource_stream.sh | 41 + source3/script/tests/test_give_owner.sh | 147 ++ source3/script/tests/test_groupmap.sh | 217 ++ source3/script/tests/test_guest_auth.sh | 106 + source3/script/tests/test_homes.sh | 136 ++ source3/script/tests/test_inherit_owner.sh | 170 ++ source3/script/tests/test_large_acl.sh | 61 + source3/script/tests/test_libwbclient_threads.sh | 17 + source3/script/tests/test_list_nt4_trust.sh | 25 + source3/script/tests/test_local_s3.sh | 39 + source3/script/tests/test_net_cache_samlogon.sh | 43 + source3/script/tests/test_net_conf.sh | 1042 +++++++++ source3/script/tests/test_net_cred_change.sh | 17 + source3/script/tests/test_net_cred_change_at.sh | 33 + source3/script/tests/test_net_dom_join_fail_dc.sh | 22 + source3/script/tests/test_net_lookup.sh | 54 + source3/script/tests/test_net_machine_account.sh | 34 + source3/script/tests/test_net_misc.sh | 80 + source3/script/tests/test_net_registry.sh | 411 ++++ source3/script/tests/test_net_registry_check.sh | 145 ++ source3/script/tests/test_net_registry_import.sh | 192 ++ .../script/tests/test_net_registry_roundtrip.sh | 158 ++ source3/script/tests/test_net_rpc_join.sh | 25 + source3/script/tests/test_net_rpc_join_creds.sh | 30 + source3/script/tests/test_net_rpc_oldjoin.sh | 49 + .../tests/test_net_rpc_share_allowedusers.sh | 49 + source3/script/tests/test_net_tdb.sh | 104 + source3/script/tests/test_net_usershare.sh | 83 + source3/script/tests/test_netfileenum.sh | 84 + source3/script/tests/test_nt4_trust.sh | 31 + source3/script/tests/test_offline.sh | 33 + source3/script/tests/test_old_dirlisting.sh | 28 + source3/script/tests/test_open_eintr.sh | 77 + source3/script/tests/test_preserve_case.sh | 86 + source3/script/tests/test_printing_var_exp.sh | 93 + source3/script/tests/test_pthreadpool.sh | 20 + source3/script/tests/test_recycle.sh | 102 + source3/script/tests/test_registry_share.sh | 39 + source3/script/tests/test_registry_upgrade.sh | 192 ++ source3/script/tests/test_resolvconf.sh | 20 + source3/script/tests/test_rofs.sh | 34 + source3/script/tests/test_rpcclient.sh | 19 + source3/script/tests/test_rpcclient_dfs.sh | 45 + source3/script/tests/test_rpcclient_lookup.sh | 42 + source3/script/tests/test_rpcclient_netsessenum.sh | 55 + source3/script/tests/test_rpcclient_pw_nt_hash.sh | 27 + source3/script/tests/test_rpcclient_samlogon.sh | 32 + source3/script/tests/test_rpcclientsrvsvc.sh | 90 + source3/script/tests/test_sacl_set_get.sh | 45 + source3/script/tests/test_server_addresses.sh | 32 + source3/script/tests/test_shadow_copy.sh | 458 ++++ source3/script/tests/test_shadow_copy_torture.sh | 227 ++ source3/script/tests/test_shareenum.sh | 31 + source3/script/tests/test_sharesec.sh | 140 ++ .../script/tests/test_smb1_shadow_copy_torture.sh | 77 + source3/script/tests/test_smb1_system_security.sh | 44 + .../script/tests/test_smb2_not_casesensitive.sh | 81 + .../script/tests/test_smbXsrv_client_cross_node.sh | 92 + .../test_smbXsrv_client_ctdb_registered_ips.sh | 159 ++ .../script/tests/test_smbXsrv_client_dead_rec.sh | 76 + source3/script/tests/test_smbclient_auth.sh | 47 + source3/script/tests/test_smbclient_basic.sh | 47 + source3/script/tests/test_smbclient_encryption.sh | 72 + .../script/tests/test_smbclient_encryption_off.sh | 65 + source3/script/tests/test_smbclient_iconv.sh | 55 + source3/script/tests/test_smbclient_kerberos.sh | 80 + source3/script/tests/test_smbclient_krb5.sh | 21 + source3/script/tests/test_smbclient_large_file.sh | 62 + .../script/tests/test_smbclient_list_servers.sh | 45 + .../script/tests/test_smbclient_log_basename.sh | 36 + .../script/tests/test_smbclient_machine_auth.sh | 44 + source3/script/tests/test_smbclient_mget.sh | 47 + .../script/tests/test_smbclient_netbios_aliases.sh | 42 + source3/script/tests/test_smbclient_ntlm.sh | 80 + source3/script/tests/test_smbclient_s3.sh | 2364 ++++++++++++++++++++ source3/script/tests/test_smbclient_tarmode.pl | 1723 ++++++++++++++ source3/script/tests/test_smbclient_tarmode.sh | 197 ++ source3/script/tests/test_smbcquota.py | 244 ++ source3/script/tests/test_smbcquota.sh | 45 + source3/script/tests/test_smbd_error.sh | 66 + source3/script/tests/test_smbd_no_krb5.sh | 46 + source3/script/tests/test_smbget.sh | 619 +++++ source3/script/tests/test_smbpasswd.sh | 133 ++ source3/script/tests/test_smbspool.sh | 294 +++ source3/script/tests/test_smbspool_krb.sh | 90 + source3/script/tests/test_smbstatus.sh | 479 ++++ source3/script/tests/test_smbtorture_nocrash_s3.sh | 38 + source3/script/tests/test_smbtorture_s3.sh | 26 + source3/script/tests/test_stream_dir_rename.sh | 72 + source3/script/tests/test_substitutions.sh | 79 + source3/script/tests/test_success.sh | 21 + source3/script/tests/test_symlink_dosmode.sh | 74 + .../script/tests/test_symlink_rename_smb1_posix.sh | 185 ++ .../script/tests/test_symlink_traversal_smb1.sh | 262 +++ .../tests/test_symlink_traversal_smb1_posix.sh | 269 +++ .../script/tests/test_symlink_traversal_smb2.sh | 382 ++++ source3/script/tests/test_testparm_s3.sh | 150 ++ source3/script/tests/test_tevent_glib_glue.sh | 20 + source3/script/tests/test_timestamps.sh | 72 + source3/script/tests/test_user_in_sharelist.sh | 22 + source3/script/tests/test_usernamemap.sh | 28 + source3/script/tests/test_valid_users.sh | 70 + source3/script/tests/test_veto_files.sh | 279 +++ source3/script/tests/test_veto_rmdir.sh | 217 ++ source3/script/tests/test_virus_scanner.sh | 135 ++ source3/script/tests/test_volume_serial_number.sh | 37 + .../script/tests/test_wbinfo_lookuprids_cache.sh | 31 + source3/script/tests/test_wbinfo_sids2xids.sh | 12 + source3/script/tests/test_wbinfo_sids2xids_int.py | 147 ++ source3/script/tests/test_wbinfo_u_large_ad.sh | 28 + .../script/tests/test_winbind_call_depth_trace.sh | 113 + .../script/tests/test_winbind_ignore_domains.sh | 106 + source3/script/tests/test_worm.sh | 121 + source3/script/tests/test_zero_data.sh | 54 + source3/script/tests/test_zero_readsize.sh | 101 + source3/script/tests/timelimit.c | 102 + source3/script/tests/vfstest-acl/run.sh | 52 + source3/script/tests/vfstest-acl/vfstest.cmd | 15 + source3/script/tests/vfstest-catia/run.sh | 102 + source3/script/tests/vfstest-catia/vfstest.cmd | 2 + source3/script/tests/vfstest-catia/vfstest1.cmd | 2 + source3/script/tests/wb_pad.sh | 83 + source3/script/tests/xattr-tdb-1/run.sh | 52 + source3/script/tests/xattr-tdb-1/vfstest.cmd | 6 + source3/script/updatesmbpasswd.sh | 14 + source3/script/wscript_build | 13 + 175 files changed, 20448 insertions(+) create mode 100755 source3/script/count_80_col.pl create mode 100755 source3/script/creategroup create mode 100755 source3/script/fix_bool.pl create mode 100755 source3/script/format_indent.sh create mode 100644 source3/script/makeunicodecasemap.awk create mode 100755 source3/script/mknissmbpasswd.sh create mode 100755 source3/script/mknissmbpwdtbl.sh create mode 100755 source3/script/mksmbpasswd.sh create mode 100644 source3/script/mksyms.awk create mode 100755 source3/script/mksyms.sh create mode 100755 source3/script/samba-log-parser create mode 100755 source3/script/scancvslog.pl create mode 100755 source3/script/smbaddshare create mode 100755 source3/script/smbchangeshare create mode 100755 source3/script/smbdeleteshare create mode 100644 source3/script/smbtar create mode 100755 source3/script/strip_trail_ws.pl create mode 100755 source3/script/tests/dlopen.sh create mode 100755 source3/script/tests/fake_snap.pl create mode 100755 source3/script/tests/full_audit_segfault/run.sh create mode 100644 source3/script/tests/full_audit_segfault/vfstest.cmd create mode 100755 source3/script/tests/getset_quota.py create mode 100755 source3/script/tests/printing/modprinter.pl create mode 100755 source3/script/tests/printing/printing_var_exp_lpr_cmd.sh create mode 100644 source3/script/tests/smbspool_argv_wrapper.c create mode 100755 source3/script/tests/stream-depot/run.sh create mode 100644 source3/script/tests/stream-depot/vfstest.cmd create mode 100755 source3/script/tests/test_acl_xattr.sh create mode 100755 source3/script/tests/test_aio_outstanding.sh create mode 100755 source3/script/tests/test_async_req.sh create mode 100755 source3/script/tests/test_bad_auditnames.sh create mode 100755 source3/script/tests/test_bug15435_widelink_dfs.sh create mode 100755 source3/script/tests/test_chdir_cache.sh create mode 100755 source3/script/tests/test_close_denied_share.sh create mode 100755 source3/script/tests/test_deadtime.sh create mode 100755 source3/script/tests/test_delete_stream.sh create mode 100755 source3/script/tests/test_delete_veto_files_only_rmdir.sh create mode 100755 source3/script/tests/test_dfree_command.sh create mode 100755 source3/script/tests/test_dfree_quota.sh create mode 100755 source3/script/tests/test_dropbox.sh create mode 100755 source3/script/tests/test_durable_handle_reconnect.sh create mode 100755 source3/script/tests/test_failure.sh create mode 100755 source3/script/tests/test_fakedircreatetimes.sh create mode 100755 source3/script/tests/test_fifo.sh create mode 100755 source3/script/tests/test_force_close_share.sh create mode 100755 source3/script/tests/test_force_create_mode.sh create mode 100755 source3/script/tests/test_force_group_change.sh create mode 100755 source3/script/tests/test_force_user_unlink.sh create mode 100755 source3/script/tests/test_forceuser_validusers.sh create mode 100755 source3/script/tests/test_fruit_resource_stream.sh create mode 100755 source3/script/tests/test_give_owner.sh create mode 100755 source3/script/tests/test_groupmap.sh create mode 100755 source3/script/tests/test_guest_auth.sh create mode 100755 source3/script/tests/test_homes.sh create mode 100755 source3/script/tests/test_inherit_owner.sh create mode 100755 source3/script/tests/test_large_acl.sh create mode 100755 source3/script/tests/test_libwbclient_threads.sh create mode 100755 source3/script/tests/test_list_nt4_trust.sh create mode 100755 source3/script/tests/test_local_s3.sh create mode 100755 source3/script/tests/test_net_cache_samlogon.sh create mode 100755 source3/script/tests/test_net_conf.sh create mode 100755 source3/script/tests/test_net_cred_change.sh create mode 100755 source3/script/tests/test_net_cred_change_at.sh create mode 100755 source3/script/tests/test_net_dom_join_fail_dc.sh create mode 100755 source3/script/tests/test_net_lookup.sh create mode 100755 source3/script/tests/test_net_machine_account.sh create mode 100755 source3/script/tests/test_net_misc.sh create mode 100755 source3/script/tests/test_net_registry.sh create mode 100755 source3/script/tests/test_net_registry_check.sh create mode 100755 source3/script/tests/test_net_registry_import.sh create mode 100755 source3/script/tests/test_net_registry_roundtrip.sh create mode 100755 source3/script/tests/test_net_rpc_join.sh create mode 100755 source3/script/tests/test_net_rpc_join_creds.sh create mode 100755 source3/script/tests/test_net_rpc_oldjoin.sh create mode 100755 source3/script/tests/test_net_rpc_share_allowedusers.sh create mode 100755 source3/script/tests/test_net_tdb.sh create mode 100755 source3/script/tests/test_net_usershare.sh create mode 100755 source3/script/tests/test_netfileenum.sh create mode 100755 source3/script/tests/test_nt4_trust.sh create mode 100755 source3/script/tests/test_offline.sh create mode 100755 source3/script/tests/test_old_dirlisting.sh create mode 100755 source3/script/tests/test_open_eintr.sh create mode 100755 source3/script/tests/test_preserve_case.sh create mode 100755 source3/script/tests/test_printing_var_exp.sh create mode 100755 source3/script/tests/test_pthreadpool.sh create mode 100755 source3/script/tests/test_recycle.sh create mode 100755 source3/script/tests/test_registry_share.sh create mode 100755 source3/script/tests/test_registry_upgrade.sh create mode 100755 source3/script/tests/test_resolvconf.sh create mode 100755 source3/script/tests/test_rofs.sh create mode 100755 source3/script/tests/test_rpcclient.sh create mode 100755 source3/script/tests/test_rpcclient_dfs.sh create mode 100755 source3/script/tests/test_rpcclient_lookup.sh create mode 100755 source3/script/tests/test_rpcclient_netsessenum.sh create mode 100755 source3/script/tests/test_rpcclient_pw_nt_hash.sh create mode 100755 source3/script/tests/test_rpcclient_samlogon.sh create mode 100755 source3/script/tests/test_rpcclientsrvsvc.sh create mode 100755 source3/script/tests/test_sacl_set_get.sh create mode 100755 source3/script/tests/test_server_addresses.sh create mode 100755 source3/script/tests/test_shadow_copy.sh create mode 100755 source3/script/tests/test_shadow_copy_torture.sh create mode 100755 source3/script/tests/test_shareenum.sh create mode 100755 source3/script/tests/test_sharesec.sh create mode 100755 source3/script/tests/test_smb1_shadow_copy_torture.sh create mode 100755 source3/script/tests/test_smb1_system_security.sh create mode 100755 source3/script/tests/test_smb2_not_casesensitive.sh create mode 100755 source3/script/tests/test_smbXsrv_client_cross_node.sh create mode 100755 source3/script/tests/test_smbXsrv_client_ctdb_registered_ips.sh create mode 100755 source3/script/tests/test_smbXsrv_client_dead_rec.sh create mode 100755 source3/script/tests/test_smbclient_auth.sh create mode 100755 source3/script/tests/test_smbclient_basic.sh create mode 100755 source3/script/tests/test_smbclient_encryption.sh create mode 100755 source3/script/tests/test_smbclient_encryption_off.sh create mode 100755 source3/script/tests/test_smbclient_iconv.sh create mode 100755 source3/script/tests/test_smbclient_kerberos.sh create mode 100755 source3/script/tests/test_smbclient_krb5.sh create mode 100755 source3/script/tests/test_smbclient_large_file.sh create mode 100755 source3/script/tests/test_smbclient_list_servers.sh create mode 100755 source3/script/tests/test_smbclient_log_basename.sh create mode 100755 source3/script/tests/test_smbclient_machine_auth.sh create mode 100755 source3/script/tests/test_smbclient_mget.sh create mode 100755 source3/script/tests/test_smbclient_netbios_aliases.sh create mode 100755 source3/script/tests/test_smbclient_ntlm.sh create mode 100755 source3/script/tests/test_smbclient_s3.sh create mode 100755 source3/script/tests/test_smbclient_tarmode.pl create mode 100755 source3/script/tests/test_smbclient_tarmode.sh create mode 100755 source3/script/tests/test_smbcquota.py create mode 100755 source3/script/tests/test_smbcquota.sh create mode 100755 source3/script/tests/test_smbd_error.sh create mode 100755 source3/script/tests/test_smbd_no_krb5.sh create mode 100755 source3/script/tests/test_smbget.sh create mode 100755 source3/script/tests/test_smbpasswd.sh create mode 100755 source3/script/tests/test_smbspool.sh create mode 100755 source3/script/tests/test_smbspool_krb.sh create mode 100755 source3/script/tests/test_smbstatus.sh create mode 100755 source3/script/tests/test_smbtorture_nocrash_s3.sh create mode 100755 source3/script/tests/test_smbtorture_s3.sh create mode 100755 source3/script/tests/test_stream_dir_rename.sh create mode 100755 source3/script/tests/test_substitutions.sh create mode 100755 source3/script/tests/test_success.sh create mode 100755 source3/script/tests/test_symlink_dosmode.sh create mode 100755 source3/script/tests/test_symlink_rename_smb1_posix.sh create mode 100755 source3/script/tests/test_symlink_traversal_smb1.sh create mode 100755 source3/script/tests/test_symlink_traversal_smb1_posix.sh create mode 100755 source3/script/tests/test_symlink_traversal_smb2.sh create mode 100755 source3/script/tests/test_testparm_s3.sh create mode 100755 source3/script/tests/test_tevent_glib_glue.sh create mode 100755 source3/script/tests/test_timestamps.sh create mode 100755 source3/script/tests/test_user_in_sharelist.sh create mode 100755 source3/script/tests/test_usernamemap.sh create mode 100755 source3/script/tests/test_valid_users.sh create mode 100755 source3/script/tests/test_veto_files.sh create mode 100755 source3/script/tests/test_veto_rmdir.sh create mode 100755 source3/script/tests/test_virus_scanner.sh create mode 100755 source3/script/tests/test_volume_serial_number.sh create mode 100755 source3/script/tests/test_wbinfo_lookuprids_cache.sh create mode 100755 source3/script/tests/test_wbinfo_sids2xids.sh create mode 100755 source3/script/tests/test_wbinfo_sids2xids_int.py create mode 100755 source3/script/tests/test_wbinfo_u_large_ad.sh create mode 100755 source3/script/tests/test_winbind_call_depth_trace.sh create mode 100755 source3/script/tests/test_winbind_ignore_domains.sh create mode 100755 source3/script/tests/test_worm.sh create mode 100755 source3/script/tests/test_zero_data.sh create mode 100755 source3/script/tests/test_zero_readsize.sh create mode 100644 source3/script/tests/timelimit.c create mode 100755 source3/script/tests/vfstest-acl/run.sh create mode 100644 source3/script/tests/vfstest-acl/vfstest.cmd create mode 100755 source3/script/tests/vfstest-catia/run.sh create mode 100644 source3/script/tests/vfstest-catia/vfstest.cmd create mode 100644 source3/script/tests/vfstest-catia/vfstest1.cmd create mode 100755 source3/script/tests/wb_pad.sh create mode 100755 source3/script/tests/xattr-tdb-1/run.sh create mode 100644 source3/script/tests/xattr-tdb-1/vfstest.cmd create mode 100755 source3/script/updatesmbpasswd.sh create mode 100644 source3/script/wscript_build (limited to 'source3/script') diff --git a/source3/script/count_80_col.pl b/source3/script/count_80_col.pl new file mode 100755 index 0000000..8b22622 --- /dev/null +++ b/source3/script/count_80_col.pl @@ -0,0 +1,16 @@ +#!/usr/bin/perl -w + +open( INFILE, "$ARGV[0]" ) || die $@; + +$count = 0; +while ( ) { + next if ($_ =~ /^#define/); + $count++ if (length($_) > 80); +} + +close( INFILE ); +print "$ARGV[0]: $count lines > 80 characters\n" if ($count > 0); + +exit( 0 ); + + diff --git a/source3/script/creategroup b/source3/script/creategroup new file mode 100755 index 0000000..1e24867 --- /dev/null +++ b/source3/script/creategroup @@ -0,0 +1,25 @@ +#!/bin/sh + +# Example script for 'add group command'. Handle weird NT group +# names. First attempt to create the group directly, if that fails +# then create a random group and print the numeric group id. +# +# Note that this is only an example and assumes /dev/urandom. +# +# Volker + +GROUPNAME="$1" +ITERS=0 + +while ! /usr/sbin/groupadd "$GROUPNAME" >/dev/null 2>&1; do + # we had difficulties creating that group. Maybe the name was + # too weird, or it already existed. Create a random name. + GROUPNAME=nt-$(dd if=/dev/urandom bs=16 count=1 2>/dev/null | md5sum | cut -b 1-5) + ITERS=$(expr "$ITERS" + 1) + if [ "$ITERS" -gt 10 ]; then + # Too many attempts + exit 1 + fi +done + +getent group | grep ^"$GROUPNAME": | cut -d : -f 3 diff --git a/source3/script/fix_bool.pl b/source3/script/fix_bool.pl new file mode 100755 index 0000000..c09645d --- /dev/null +++ b/source3/script/fix_bool.pl @@ -0,0 +1,19 @@ +#!/usr/bin/perl -w + +open(INFILE, "$ARGV[0]") || die $@; +open(OUTFILE, ">$ARGV[0].new") || die $@; + +while () { + $_ =~ s/True/true/; + $_ =~ s/False/false/; + print OUTFILE "$_"; +} + +close(INFILE); +close(OUTFILE); + +rename("$ARGV[0].new", "$ARGV[0]") || die @_; + +exit(0); + + diff --git a/source3/script/format_indent.sh b/source3/script/format_indent.sh new file mode 100755 index 0000000..11ef285 --- /dev/null +++ b/source3/script/format_indent.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +# -npro Do no read the '.indent.pro' files. +# -kr Use K&R formatting rules +# -i8 Set indentation level to 8 spaces. +# -ts8 Set tab size to 8 spaces +# -sob Swallow optional blank lines. +# -l80 Set the maximum line length at 80 characters. +# -ss On one-line for and while statements, force a blank before the semicolon +# -ncs Do not put a space after cast operators. + +indent -npro -kr -i8 -ts8 -sob -l80 -ss -ncs "$@" diff --git a/source3/script/makeunicodecasemap.awk b/source3/script/makeunicodecasemap.awk new file mode 100644 index 0000000..8424b6c --- /dev/null +++ b/source3/script/makeunicodecasemap.awk @@ -0,0 +1,59 @@ +function reset_vals() { + upperstr = ""; + lowerstr = ""; + flagstr = "0"; +} + +function print_val() { + upperstr = $13; + lowerstr = $14; + if ( upperstr == "" ) + upperstr = strval; + if ( lowerstr == "" ) + lowerstr = strval; + + if ( $3 == "Lu" ) + flagstr = sprintf("%s|%s", flagstr, "UNI_UPPER"); + if ( $3 == "Ll" ) + flagstr = sprintf("%s|%s", flagstr, "UNI_LOWER"); + if ( val >= 48 && val <= 57) + flagstr = sprintf("%s|%s", flagstr, "UNI_DIGIT"); + if ((val >= 48 && val <= 57) || (val >= 65 && val <= 70) || (val >=97 && val <= 102)) + flagstr = sprintf("%s|%s", flagstr, "UNI_XDIGIT"); + if ( val == 32 || (val >=9 && val <= 13)) + flagstr = sprintf("%s|%s", flagstr, "UNI_SPACE"); + if( index(flagstr, "0|") == 1) + flagstr = substr(flagstr, 3, length(flagstr) - 2); + printf("{ 0x%s, 0x%s, %s }, \t\t\t/* %s %s */\n", lowerstr, upperstr, flagstr, strval, $2); + val++; + strval=sprintf("%04X", val); + reset_vals(); +} + +BEGIN { + val=0 + FS=";" + strval=sprintf("%04X", val); + reset_vals(); +} + +{ + if ( $1 == strval ) { + print_val(); + } else { + while ( $1 != strval) { + printf("{ 0x%04X, 0x%04X, 0 }, \t\t\t/* %s NOMAP */\n", val, val, strval); + val++; + strval=sprintf("%04X", val); + } + print_val(); + } +} + +END { + while ( val < 65536 ) { + printf("{ 0x%04X, 0x%04X, 0 }, \t\t\t/* %s NOMAP */\n", val, val, strval); + val++; + strval=sprintf("%04X", val); + } +} diff --git a/source3/script/mknissmbpasswd.sh b/source3/script/mknissmbpasswd.sh new file mode 100755 index 0000000..2fea32c --- /dev/null +++ b/source3/script/mknissmbpasswd.sh @@ -0,0 +1,28 @@ +#!/bin/sh +# +# Copyright (C) 1998 Benny Holmgren +# +# Script to import smbpasswd file into the smbpasswd NIS+ table. Reads +# from stdin the smbpasswd file. +# +while true; do + read row + if [ -z "$row" ]; then + break + fi + + if [ "$(echo $row | cut -c1)" = "#" ]; then + continue + fi + + nistbladm -a \ + name=\"$(echo $row | cut -d: -f1)\" \ + uid=\"$(echo $row | cut -d: -f2)\" \ + lmpwd=\"$(echo $row | cut -d: -f3)\" \ + ntpwd=\"$(echo $row | cut -d: -f4)\" \ + acb=\"$(echo $row | cut -d: -f5)\" \ + pwdlset_t=\"$(echo $row | cut -d: -f6)\" \ + gcos=\"$(echo $row | cut -d: -f7)\" \ + home=\"$(echo $row | cut -d: -f8)\" \ + shell=\"$(echo $row | cut -d: -f9)\" smbpasswd.org_dir.$(nisdefaults -d) +done diff --git a/source3/script/mknissmbpwdtbl.sh b/source3/script/mknissmbpwdtbl.sh new file mode 100755 index 0000000..d7291bb --- /dev/null +++ b/source3/script/mknissmbpwdtbl.sh @@ -0,0 +1,41 @@ +#!/bin/sh +# +# Copyright (C) 1998 Benny Holmgren +# +# Creates smbpasswd table and smb group in NIS+ +# + +nistbladm \ + -D access=og=rmcd,nw= -c \ + -s : smbpasswd_tbl \ + name=S,nogw=r \ + uid=S,nogw=r \ + user_rid=S,nogw=r \ + smb_grpid=,nw+r \ + group_rid=,nw+r \ + acb=,nw+r \ + \ + lmpwd=C,nw=,g=r,o=rm \ + ntpwd=C,nw=,g=r,o=rm \ + \ + logon_t=,nw+r \ + logoff_t=,nw+r \ + kick_t=,nw+r \ + pwdlset_t=,nw+r \ + pwdlchg_t=,nw+r \ + pwdmchg_t=,nw+r \ + \ + full_name=,nw+r \ + home_dir=,nw+r \ + dir_drive=,nw+r \ + logon_script=,nw+r \ + profile_path=,nw+r \ + acct_desc=,nw+r \ + workstations=,nw+r \ + \ + hours=,nw+r \ + smbpasswd.org_dir.$(nisdefaults -d) + +nisgrpadm -c smb.$(nisdefaults -d) + +nischgrp smb.$(nisdefaults -d) smbpasswd.org_dir.$(nisdefaults -d) diff --git a/source3/script/mksmbpasswd.sh b/source3/script/mksmbpasswd.sh new file mode 100755 index 0000000..119a556 --- /dev/null +++ b/source3/script/mksmbpasswd.sh @@ -0,0 +1,6 @@ +#!/bin/sh +awk 'BEGIN {FS=":" + printf("#\n# SMB password file.\n#\n") + } +{ printf( "%s:%s:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:[UD ]:LCT-00000000:%s\n", $1, $3, $5) } +' diff --git a/source3/script/mksyms.awk b/source3/script/mksyms.awk new file mode 100644 index 0000000..94a405c --- /dev/null +++ b/source3/script/mksyms.awk @@ -0,0 +1,76 @@ +# +# mksyms.awk +# +# Extract symbols to export from C-header files. +# output in version-script format for linking shared libraries. +# +# Copyright (C) 2008 Michael Adam +# +BEGIN { + inheader=0; + current_file=""; + print "#" + print "# This file is automatically generated with \"make symbols\". DO NOT EDIT " + print "#" + print "{" + print "\tglobal:" +} + +END { + print"" + print "\tlocal: *;" + print "};" +} + +{ + if (FILENAME!=current_file) { + print "\t\t# The following definitions come from",FILENAME + current_file=FILENAME + } + if (inheader) { + if (match($0,"[)][^()]*[;][ \t]*$")) { + inheader = 0; + } + next; + } +} + +/^static/ || /^[ \t]*typedef/ || !/^[a-zA-Z\_]/ { + next; +} + +/^extern[ \t]+[^()]+[;][ \t]*$/ { + gsub(/[^ \t]+[ \t]+/, ""); + sub(/[;][ \t]*$/, ""); + printf "\t\t%s;\n", $0; + next; +} + +# look for function headers: +{ + gotstart = 0; + if ($0 ~ /^[A-Za-z_][A-Za-z0-9_]+/) { + gotstart = 1; + } + if(!gotstart) { + next; + } +} + +/[_A-Za-z0-9]+[ \t]*[(].*[)][^()]*;[ \t]*$/ { + sub(/[(].*$/, ""); + gsub(/[^ \t]+[ \t]+/, ""); + gsub(/^[*]+/, ""); + printf "\t\t%s;\n",$0; + next; +} + +/[_A-Za-z0-9]+[ \t]*[(]/ { + inheader=1; + sub(/[(].*$/, ""); + gsub(/[^ \t]+[ \t]+/, ""); + gsub(/^[*]/, ""); + printf "\t\t%s;\n",$0; + next; +} + diff --git a/source3/script/mksyms.sh b/source3/script/mksyms.sh new file mode 100755 index 0000000..9a08685 --- /dev/null +++ b/source3/script/mksyms.sh @@ -0,0 +1,46 @@ +#! /bin/sh + +# +# mksyms.sh +# +# Extract symbols to export from C-header files. +# output in version-script format for linking shared libraries. +# +# This is the shell wrapper for the mksyms.awk core script. +# +# Copyright (C) 2008 Michael Adam +# + +LANG=C +export LANG +LC_ALL=C +export LC_ALL +LC_COLLATE=C +export LC_COLLATE + +if [ $# -lt 2 ]; then + echo "Usage: $0 awk output_file header_files" + exit 1 +fi + +awk="$1" +shift + +symsfile="$1" +shift +symsfile_tmp="$symsfile.$$.tmp~" + +proto_src="$(echo "$@" | tr ' ' '\n' | sort | uniq)" + +echo creating $symsfile + +mkdir -p $(dirname $symsfile) + +${awk} -f $(dirname $0)/mksyms.awk $proto_src >$symsfile_tmp + +if cmp -s $symsfile $symsfile_tmp 2>/dev/null; then + echo "$symsfile unchanged" + rm $symsfile_tmp +else + mv $symsfile_tmp $symsfile +fi diff --git a/source3/script/samba-log-parser b/source3/script/samba-log-parser new file mode 100755 index 0000000..a07dfdb --- /dev/null +++ b/source3/script/samba-log-parser @@ -0,0 +1,382 @@ +#!/usr/bin/env python3 +# +####################################################################### +# +# A script to parse samba (especially winbind) logfiles. +# Trace files should be in a non-syslog format (debug syslog format = no). +# +# --traceid ... Specify the traceid of the request to parse +# --pid ... Specify the pid +# --breakdown ... Break to separate files per each traceid +# --merge-by-timestamp ... Merge logs by timestamp +# --flow ... Show the request/sub-request call flow +# --flow-compact ... Show the request/sub-request call flow without dcerpc +# +# +# Copyright (c) 2023 Andreas Schneider +# Copyright (c) 2023 Pavel Filipenský +# +# 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 . +# +####################################################################### +# +# Requires: ??? + +import sys +import os +import re +from argparse import ArgumentParser +from collections import defaultdict + +# Trace record consists of a trace header followed by one or more text lines. +# +# This tool expects trace header format based on these smb.conf parameters: +# +# debug syslog format = no +# debug hires timestamp = yes +# winbind debug traceid = yes +# +# If 'winbind debug traceid = no' is set, then the option --merge-by-timestamp +# still can be used. +# +# Each trace header contains a traceid, which is the main identifier for this +# tool. A single traceid is either provided via command line option --traceid +# or a list of traceids is derived from the PID specified via option --pid. +# Creating and evaluating list of traceids from PID can be tricky: +# The traceid can appear in a trace record before trace record containing the +# PID is processed. So when we see a new traceid we are not sure if it belongs +# to the traced PID. +# The PID appears only in the main winbind process (log.winbind). If a +# directory with many log files should be processed, we process the files in +# random order. +# It might happen that e.g. log.wb-ADDOMAIN is processed before log.winbind so +# we do not know the list of traceids yet. +# To make all this easy we put into memory all trace records and do the final +# traceid filtering only after all files are read. This can require lot of +# memory if files are big. + + +def process_file_no_traceid(record_list, fname): + with open(fname, "r") as infile: + data = infile.readlines() + date = "" + record_lines = [] + + RE_HEADER_NO_TRACEID = re.compile( + r"^\[(\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}\.\d{6}).*") + for line in data: + header = RE_HEADER_NO_TRACEID.search(line) + if header: + # Append all previous trace lines of a record + if record_lines: + record_list.append((date, None, record_lines, fname)) + record_lines = [] + # Remember the new date + date = header.group(1) + record_lines.append(line) + + +def process_file(record_list, traceid_set, fname, opid, otraceid): + with open(fname, "r") as infile: + data = infile.readlines() + pid = None + traceid = 0 + traceid_prev = None + undecided_traceid = False + date = "" + record_lines = [] + + # If traceid option was provided the traceid_set will contain just it + if otraceid: + traceid_set.add(otraceid) + + RE_HEADER = re.compile( + r"^\[(\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}\.\d{6}).*?, .*, " + r"traceid=([0-9]+).*\]") + RE_INTERFACE_VERSION = re.compile( + r"^\s+winbindd_interface_version: \[\S* \((\d+)\)\]") + RE_ASYNC_REQUEST = re.compile( + r"^\s+process_request_send: " + r"\[\S* \((\d+)\)\] Handling async request:") + # Example of a header line + # [2023/05/01 07:40:45.439049, 3, pid=418844, effective(0, 0), real(0, 0), class=winbind, traceid=37] ../../source3/winbindd/winbindd_misc.c:355(winbindd_interface_version) + for line in data: + header = RE_HEADER.search(line) + if header: + # Append all previous trace lines of a record if the traceid is in + # the list. + if record_lines: + record_list.append((date, traceid, record_lines, fname)) + record_lines = [] + # Remember the new date and the new traceid + date = header.group(1) + traceid = header.group(2) + if traceid != traceid_prev: + traceid_prev = traceid + undecided_traceid = True + if opid: + # Search for lines that identify a new winbind client and the + # client PID + + # winbindd_interface_version: [nss_winbind (500725)]: request interface version (version = 32) + # process_request_send: [nss_winbind (500725)] Handling async request: SETPWENT + interface_version = RE_INTERFACE_VERSION.search(line) + async_request = RE_ASYNC_REQUEST.search(line) + if interface_version: + pid = interface_version.group(1) + if undecided_traceid: + if pid == opid: + traceid_set.add(traceid) + undecided_traceid = False + if async_request: + pid = async_request.group(1) + if undecided_traceid: + if pid == opid: + traceid_set.add(traceid) + undecided_traceid = False + # For --breakdown add every traceid + if not opid and not otraceid: + traceid_set.add(traceid) + + record_lines.append(line) + + +def filter_traceids(record_list, traceid_set): + llist = [] + for (d, t, li, f) in record_list: + if t in traceid_set: + llist.append((d, t, li, f)) + return llist + + +def filter_flow(record_list): + local_list = [] + for (date, traceid, lines, filename) in record_list: + for line in lines: + isflow = re.search(r"^(\s+)flow: (.*)", line) + if isflow: + local_list.append(isflow.group(1) + isflow.group(2)) + return local_list + + +def filter_flowcompact(flist): + local_list = [] + end_marker = None + for fl in flist: + if not end_marker: + local_list.append(fl) + dcerpc_start = re.search(r"^(\s+)-> dcerpc_", fl) + if dcerpc_start: + end_marker = dcerpc_start.group(1) + else: + dcerpc_end = re.search(r"^" + end_marker + "<- dcerpc_", fl) + if dcerpc_end: + end_marker = None + local_list.append(fl) + return local_list + + +def print_record_list(record_list, file): + f_prev = None + for (date, traceid, lines, filename) in record_list: + # Inform about filename change + if filename != f_prev: + print("-" * 72, file=file) + print("FILE: ", filename, file=file) + print("-" * 72, file=file) + for line in lines: + print(line, end='', file=file) + f_prev = filename + +# record_list ... list of quadruplets +# flow_list ... lines from record_list with 'flow' traces +# traceid_set ... list of traceids we want to trace +# with --traceid ... there is a single traceids +# with --pid ... there are all traceids for the PID +# with --breakdown ... there are all traceids + + +def setup_parser(): + parser = ArgumentParser() + + parser.add_argument( + "path", + type=str, + help="logfile or directory" + ) + parser.add_argument( + "--traceid", + dest="traceid", + help="specify the traceid of the trace records", + metavar="ID" + ) + parser.add_argument( + "--pid", + dest="pid", + help="specify the pid of winbind client", + metavar="PID" + ) + parser.add_argument( + "--breakdown", + action="store_true", + dest="breakdown", + default=False, + help="breakdown the traces into per traceid files" + ) + parser.add_argument( + "--merge-by-timestamp", + action="store_true", + dest="merge", + default=False, + help="merge logs by timestamp" + ) + parser.add_argument( + "--flow", + action="store_true", + dest="flow", + default=False, + help="show the request/sub-request flow traces" + ) + parser.add_argument( + "--flow-compact", + action="store_true", + dest="flowcompact", + default=False, + help="show the request/sub-request flow traces without dcerpc details" + ) + return parser + + +def main(): # noqa + record_list = [] + flow_list = [] + traceid_set = set() + + parser = setup_parser() + options = parser.parse_args() + + if (not options.traceid and not options.pid and not options.breakdown + and not options.merge): + print("One of --traceid or --pid is needed" + " or --breakdown or --merge-by-timestamp.") + sys.exit(1) + elif options.traceid and options.pid: + print("Only one of --traceid or --pid is allowed.") + sys.exit(1) + elif options.breakdown and (options.traceid or options.pid): + print("--breakdown cannot be combined with --traceid and --pid.") + sys.exit(1) + + if options.flow and not options.traceid: + print("Option --flow can be used only together with --traceid.") + sys.exit(1) + + if options.flowcompact and not options.traceid: + print("Option --flow-compact can be used only together with " + "--traceid.") + sys.exit(1) + + if options.flow and options.flowcompact: + print("Only one of --flow or --flow-compact is allowed.") + sys.exit(1) + + if not options.path: + print("Path to logfile or directory with logs is needed.") + sys.exit(1) + + merge_with_no_traceid = (not options.traceid and not options.pid + and not options.breakdown) and options.merge + + path = options.path + if os.path.isdir(path): + for root, dirs, files in os.walk(path): + for name in files: + if merge_with_no_traceid: + process_file_no_traceid( + record_list, + os.path.join(root, name) + ) + else: + process_file( + record_list, + traceid_set, + os.path.join(root, name), + options.pid, + options.traceid, + ) + elif os.path.isfile(path): + if merge_with_no_traceid: + process_file_no_traceid( + record_list, + path + ) + else: + process_file( + record_list, + traceid_set, + path, + options.pid, + options.traceid + ) + else: + print(path, "Path is neither file or directory.") + sys.exit(1) + + # Sort only using timestamps, no use of traceid + if merge_with_no_traceid: + record_list.sort() + print_record_list(record_list, sys.stdout) + sys.exit(0) + + # Keep only records with matching traceids + if not options.breakdown: + record_list = filter_traceids(record_list, traceid_set) + + if options.breakdown: + for traceid in traceid_set: + # Full + with open("%s.full" % traceid, "w") as full_f: + full_l = filter_traceids(record_list, {traceid}) + if options.merge: + full_l.sort() + print_record_list(full_l, full_f) + # Flow + with open("%s.flow" % traceid, "w") as flow_f: + flow_l = filter_flow(full_l) + for fl in flow_l: + print(fl, file=flow_f) + # Flow compact + with open("%s.flowcompact" % traceid, "w") as flowcompact_f: + flowcompact_l = filter_flowcompact(flow_l) + for fl in flowcompact_l: + print(fl, file=flowcompact_f) + elif options.flow: + flow_list = filter_flow(record_list) + for fl in flow_list: + print(fl) + elif options.flowcompact: + flow_list = filter_flow(record_list) + flow_list = filter_flowcompact(flow_list) + for fl in flow_list: + print(fl) + else: + if options.merge: + record_list.sort() + print_record_list(record_list, sys.stdout) + + sys.exit(0) + + +if __name__ == "__main__": + main() diff --git a/source3/script/scancvslog.pl b/source3/script/scancvslog.pl new file mode 100755 index 0000000..c39f911 --- /dev/null +++ b/source3/script/scancvslog.pl @@ -0,0 +1,112 @@ +#!/usr/bin/perl +require"timelocal.pl"; + +# +# usage scancvslog.pl logfile starttime tag +# +# this will extract all entries from the specified cvs log file +# that have a date later than or equal to starttime and a tag +# value of tag. If starttime is not specified, all entries are +# extracted. If tag is not specified then entries for all +# branches are extracted. starttime must be specified as +# "monthname day, year" +# +# Example to extract all entries for SAMBA_2_2 branch from the +# log file named cvs.log +# +# scancvslog.pl cvs.log "" SAMBA_2_2 +# +# +# To extract all log entries after Jan 10, 1999 (Note month name +# must be spelled out completely). +# +# scancvslog.pl cvs.log "January 10, 1999" +# + +open(INFILE,@ARGV[0]) || die "Unable to open @ARGV[0]\n"; + +%Monthnum = ( + "January", 0, + "February", 1, + "March", 2, + "April", 3, + "May", 4, + "June", 5, + "July", 6, + "August", 7, + "September", 8, + "October", 9, + "November", 10, + "December", 11, + "Jan", 0, + "Feb", 1, + "Mar", 2, + "Apr", 3, + "May", 4, + "Jun", 5, + "Jul", 6, + "Aug", 7, + "Sep", 8, + "Oct", 9, + "Nov", 10, + "Dec", 11 +); + +$Starttime = (@ARGV[1]) ? &make_time(@ARGV[1]) : 0; +$Tagvalue = @ARGV[2]; + +while (&get_entry) { + $_=$Entry[0]; +# get rid of extra white space + s/\s+/ /g; +# get rid of any time string in date + s/ \d\d:\d\d:\d\d/,/; + s/^Date:\s*\w*\s*(\w*)\s*(\w*),\s*(\w*).*/$1 $2 $3/; + $Testtime = &make_time($_); + $Testtag = &get_tag; + if (($Testtime >= $Starttime) && ($Tagvalue eq $Testtag)) { + print join("\n",@Entry),"\n"; + } +} +close(INFILE); + +sub make_time { + $_ = @_[0]; + s/,//; + ($month, $day, $year) = split(" ",$_); + if (($year < 1900)||($day < 1)||($day > 31)||not length($Monthnum{$month})) { + print "Bad date format @_[0]\n"; + print "Date needs to be specified as \"Monthname day, year\"\n"; + print "eg: \"January 10, 1999\"\n"; + exit 1; + } + $year = ($year == 19100) ? 2000 : $year; + $month = $Monthnum{$month}; + $Mytime=&timelocal((0,0,0,$day,$month,$year)); +} + +sub get_tag { + @Mytag = grep (/Tag:/,@Entry); + $_ = @Mytag[0]; + s/^.*Tag:\s*(\w*).*/$1/; + return $_; +} + +sub get_entry { + @Entry=(); + if (not eof(INFILE)) { + while (not eof(INFILE)) { + $_ = ; + chomp $_; + next if (not ($_)); + if (/^\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/) { + next if ($#Entry == -1); + push(Entry,$_); + return @Entry; + } else { + push(Entry,$_); + } + } + } + return @Entry; +} diff --git a/source3/script/smbaddshare b/source3/script/smbaddshare new file mode 100755 index 0000000..704c9f4 --- /dev/null +++ b/source3/script/smbaddshare @@ -0,0 +1,32 @@ +#!/bin/sh +# +# smbaddshare +# +# Copyright (C) 2015 Christof Schmitt +# +# Example script that can be used with the 'add share command' config +# option. This is mainly intended for use in the Samba selftest suite, +# please review and adapt it before using elsewhere. +# + +CONF="$1" +SHARENAME="$2" +SHAREPATH="$3" +COMMENT="$4" +MAX_CONN="$5" + +NETCONF="$BINDIR/net --configfile=$CONF conf" + +$NETCONF addshare "$SHARENAME" "$SHAREPATH" writeable=no guest_ok=no "$COMMENT" +RC=$? +if [ $RC -ne 0 ]; then + echo Failure during addshare: rc=$RC + exit $RC +fi + +$NETCONF setparm "$SHARENAME" 'max connections' "$MAX_CONN" +RC=$? +if [ $RC -ne 0 ]; then + echo Failure during setparm for max connections: rc=$RC + exit $RC +fi diff --git a/source3/script/smbchangeshare b/source3/script/smbchangeshare new file mode 100755 index 0000000..098e968 --- /dev/null +++ b/source3/script/smbchangeshare @@ -0,0 +1,47 @@ +#!/bin/sh +# +# smbchangeshare +# +# Copyright (C) 2015 Christof Schmitt +# +# Example script that can be used with the 'change share command' +# config option. This is mainly intended for use in the Samba selftest +# suite, please review and adapt it before using elsewhere. +# + +CONF="$1" +SHARENAME="$2" +SHAREPATH="$3" +COMMENT="$4" +MAX_CONN="$5" +CSC_POLICY="$6" + +NETCONF="$BINDIR/net --configfile=$CONF conf" + +$NETCONF setparm "$SHARENAME" 'path' "$SHAREPATH" +RC=$? +if [ $RC -ne 0 ]; then + echo Failure during setparm for path: rc=$RC + exit $RC +fi + +$NETCONF setparm "$SHARENAME" 'comment' "$COMMENT" +RC=$? +if [ $RC -ne 0 ]; then + echo Failed during setparm for comment: rc=$RC + exit $RC +fi + +$NETCONF setparm "$SHARENAME" 'max connections' "$MAX_CONN" +RC=$? +if [ $RC -ne 0 ]; then + echo Failure during setparm for max connections: rc=$RC + exit $RC +fi + +$NETCONF setparm "$SHARENAME" 'csc policy' "$CSC_POLICY" +RC=$? +if [ $RC -ne 0 ]; then + echo Failure during setparm for csc policy: rc=$RC + exit $RC +fi diff --git a/source3/script/smbdeleteshare b/source3/script/smbdeleteshare new file mode 100755 index 0000000..8f70678 --- /dev/null +++ b/source3/script/smbdeleteshare @@ -0,0 +1,21 @@ +#!/bin/sh +# +# smbdeleteshare +# +# Copyright (C) 2015 Christof Schmitt +# +# Example script that can be used with the 'delete share command' +# config option. This is mainly intended for use in the Samba selftest +# suite, please review and adapt it before using elsewhere. +# + +CONF="$1" +SHARENAME="$2" + +NETCONF="$BINDIR/net --configfile=$CONF conf" +$NETCONF delshare "$SHARENAME" +RC=$? +if [ $RC -ne 0 ]; then + echo Failure during delshare command: rc=$RC + exit $RC +fi diff --git a/source3/script/smbtar b/source3/script/smbtar new file mode 100644 index 0000000..439d085 --- /dev/null +++ b/source3/script/smbtar @@ -0,0 +1,181 @@ +#!/bin/sh +# +# smbtar script - front end to smbclient +# +# Authors: Martin.Kraemer +# and Ricky Poulten (ricky@logcam.co.uk) +# +# (May need to change shell to ksh for HPUX or OSF for better getopts) +# +# sandy nov 3 '98 added -a flag +# +# Richard Sharpe, added -c 'tarmode full' so that we back up all files to +# fix a bug in clitar when a patch was added to stop system and hidden files +# being backed up. + +case $0 in +# when called by absolute path, assume smbclient is in the same directory +/*) + SMBCLIENT="$(dirname $0)/smbclient" + ;; +*) # you may need to edit this to show where your smbclient is + SMBCLIENT="smbclient" ;; +esac + +# These are the default values. You could fill them in if you know what +# you're doing, but beware: better not store a plain text password! +server="" +service="backup" # Default: a service called "backup" +password="" +username=$LOGNAME # Default: same user name as in *nix +verbose="2>/dev/null" # Default: no echo to stdout +log="-d 2" +newer="" +newerarg="" +blocksize="" +blocksizearg="" +clientargs="-c 'tarmode full'" +tarcmd="c" +tarargs="" +cdcmd="\\" +tapefile=${TAPE-tar.out} + +Usage() +{ + ex=$1 + shift + echo >&2 "Usage: $(basename $0) [] [] +Function: backup/restore a Windows PC directories to a local tape file +Options: (Description) (Default) + -r Restore from tape file to PC Save from PC to tapefile + -i Incremental mode Full backup mode + -a Reset archive bit mode Don't reset archive bit + -v Verbose mode: echo command Don't echo anything + -s Specify PC Server $server + -p Specify PC Password $password + -x Specify PC Share $service + -X Exclude mode Include + -N File for date comparison $( + set -- $newer + echo $2 + ) + -b Specify tape's blocksize $( + set -- $blocksize + echo $2 + ) + -d Specify a directory in share $cdcmd + -l Specify a Samba Log Level $( + set -- $log + echo $2 + ) + -u Specify User Name $username + -t Specify Tape device $tapefile +" + echo >&2 "$@" + exit $ex +} + +# echo Params count: $# + +# DEC OSF AKA Digital UNIX does not seem to return a value in OPTIND if +# there are no command line params, so protect us against that ... +if [ $# = 0 ]; then + + Usage 2 "Please enter a command line parameter!" + +fi + +while getopts riavl:b:d:N:s:p:x:u:Xt: c; do + case $c in + r) # [r]estore to Windows (instead of the default "Save from Windows") + tarcmd="x" + ;; + i) # [i]ncremental + tarargs=${tarargs}ga + clientargs="-c 'tarmode inc'" + ;; + a) # [a]rchive + tarargs=${tarargs}a + ;; + l) # specify [l]og file + log="-d $OPTARG" + case "$OPTARG" in + [0-9]*) ;; + *) + echo >&2 "$0: Error, log level not numeric: -l $OPTARG" + exit 1 + ;; + esac + ;; + d) # specify [d]irectory to change to in server's share + cdcmd="$OPTARG" + ;; + N) # compare with a file, test if [n]ewer + if [ -f $OPTARG ]; then + newer=$OPTARG + newerarg="N" + else + echo >&2 $0: Warning, $OPTARG not found + fi + ;; + X) # Add exclude flag + tarargs=${tarargs}X + ;; + s) # specify [s]erver's share to connect to - this MUST be given. + server="$OPTARG" + ;; + b) # specify [b]locksize + blocksize="$OPTARG" + case "$OPTARG" in + [0-9]*) ;; + *) + echo >&2 "$0: Error, block size not numeric: -b $OPTARG" + exit 1 + ;; + esac + blocksizearg="b" + ;; + p) # specify [p]assword to use + password="$OPTARG" + ;; + x) # specify windows [s]hare to use + service="$OPTARG" + ;; + t) # specify [t]apefile on local host + tapefile="$OPTARG" + ;; + u) # specify [u]sername for connection + username="$OPTARG" + ;; + v) # be [v]erbose and display what's going on + verbose="" + tarargs=${tarargs}v + ;; + '?') # any other switch + Usage 2 "Invalid switch specified - abort." + ;; + esac +done + +shift $(expr $OPTIND - 1) + +if [ "$server" = "" ] || [ "$service" = "" ]; then + Usage 1 "No server or no service specified - abort." +fi + +# if the -v switch is set, the echo the current parameters +if [ -z "$verbose" ]; then + echo "server is $server" +# echo "share is $service" + echo "share is $service\\$cdcmd" + echo "tar args is $tarargs" +# echo "password is $password" # passwords should never be sent to screen + echo "tape is $tapefile" + echo "blocksize is $blocksize" +fi + +tarargs=${tarargs}${blocksizearg}${newerarg} + +eval $SMBCLIENT "'\\\\$server\\$service'" "'$password'" -U "'$username'" \ + -E $log -D "'$cdcmd'" ${clientargs} \ + -T${tarcmd}${tarargs} $blocksize $newer $tapefile '${1+"$@"}' $verbose diff --git a/source3/script/strip_trail_ws.pl b/source3/script/strip_trail_ws.pl new file mode 100755 index 0000000..c2c39e2 --- /dev/null +++ b/source3/script/strip_trail_ws.pl @@ -0,0 +1,18 @@ +#!/usr/bin/perl -w + +open( INFILE, "$ARGV[0]" ) || die $@; +open( OUTFILE, ">$ARGV[0].new" ) || die $@; + +while ( ) { + $_ =~ s/[ \t\r]*$//; + print OUTFILE "$_"; +} + +close( INFILE ); +close( OUTFILE ); + +rename( "$ARGV[0].new", "$ARGV[0]" ) || die @_; + +exit( 0 ); + + diff --git a/source3/script/tests/dlopen.sh b/source3/script/tests/dlopen.sh new file mode 100755 index 0000000..a1299b2 --- /dev/null +++ b/source3/script/tests/dlopen.sh @@ -0,0 +1,90 @@ +#!/bin/sh +# +# Copyright (C) Nalin Dahyabhai 2003 +# +# 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 . + +tempdir=$(mktemp -d /tmp/dlopenXXXXXX) +test -n "$tempdir" || exit 1 +cat >>$tempdir/dlopen.c <<_EOF +#include +#include +#include +#include +/* Simple program to see if dlopen() would succeed. */ +int main(int argc, char **argv) +{ + int i; + struct stat st; + char buf[PATH_MAX]; + for (i = 1; i < argc; i++) { + if (dlopen(argv[i], RTLD_NOW)) { + fprintf(stdout, "dlopen() of \"%s\" succeeded.\n", + argv[i]); + } else { + snprintf(buf, sizeof(buf), "./%s", argv[i]); + if ((stat(buf, &st) == 0) && dlopen(buf, RTLD_NOW)) { + fprintf(stdout, "dlopen() of \"./%s\" " + "succeeded.\n", argv[i]); + } else { + fprintf(stdout, "dlopen() of \"%s\" failed: " + "%s\n", argv[i], dlerror()); + return 1; + } + } + } + return 0; +} +_EOF + +for arg in "$@"; do + case "$arg" in + "") ;; + + -I* | -D* | -f* | -m* | -g* | -O* | -W*) + cflags="$cflags $arg" + ;; + -l* | -L*) + ldflags="$ldflags $arg" + ;; + /*) + modules="$modules $arg" + ;; + *) + modules="$modules $arg" + ;; + esac +done + +${CC:-gcc} $RPM_OPT_FLAGS $CFLAGS -o $tempdir/dlopen $cflags $tempdir/dlopen.c $ldflags + +retval=0 +for module in $modules; do + case "$module" in + "") ;; + + /*) + $tempdir/dlopen "$module" + retval=$? + ;; + *) + $tempdir/dlopen ./"$module" + retval=$? + ;; + esac +done + +rm -f $tempdir/dlopen $tempdir/dlopen.c +rmdir $tempdir +exit $retval diff --git a/source3/script/tests/fake_snap.pl b/source3/script/tests/fake_snap.pl new file mode 100755 index 0000000..d88307e --- /dev/null +++ b/source3/script/tests/fake_snap.pl @@ -0,0 +1,85 @@ +#!/usr/bin/perl -w + +use strict; + +use File::Path qw(rmtree); +use POSIX (); + +sub _untaint_path +{ + my ($path) = @_; + + if ($path =~ /^(.*)$/) { + return $1; + } + die "bad path"; +} + +sub _create_snapshot +{ + my ($base_path) = _untaint_path(shift); + my $time_str = POSIX::strftime("%Y.%m.%d-%H.%M.%S" , localtime()); + my $snap_path = $base_path . "/.snapshots/\@GMT-" . $time_str; + my $ret; + + delete @ENV{'BASH_ENV'}; + + $ENV{'PATH'} = '/bin:/usr/bin'; # untaint PATH + POSIX::mkdir($base_path . "/.snapshots", 0755); + + # add trailing slash to src path to ensure that only contents is copied + $ret = system("rsync", "-a", "--exclude=.snapshots/", "${base_path}/", + $snap_path); + if ($ret != 0) { + print STDERR "rsync failed with $ret\n"; + } else { + print "$snap_path\n"; + } + + return $ret; +} + +sub _delete_snapshot +{ + my $base_path = _untaint_path(shift); + my $snap_path = _untaint_path(shift); + + # we're doing a recursive delete, so do some sanity checks + if ((index($snap_path, $base_path) != 0) || (index($snap_path, ".snapshots") == -1)) { + print STDERR "invalid snap_path: $snap_path\n"; + return -1; + } + + $ENV{'PATH'} = '/bin:/usr/bin'; # untaint PATH + rmtree($snap_path, {error => \my $err}); + if (@$err) { + for my $diag (@$err) { + my ($file, $message) = %$diag; + if ($file eq '') { + print STDERR "rmtree error: $message\n"; + } else { + print STDERR "rmtree error $file: $message\n"; + } + } + return -1; + } + + return 0; +} + +my $ret; +my $num_args = $#ARGV + 1; +my $cmd = shift; + +if (($num_args == 2) && ($cmd eq "--check")) { + $ret = 0; +} elsif (($num_args == 2) && ($cmd eq "--create")) { + $ret = _create_snapshot($ARGV[0]); +} elsif (($num_args == 3) && ($cmd eq "--delete")) { + $ret = _delete_snapshot($ARGV[0], $ARGV[1]); +} else { + print STDERR "invalid script argument\n"; + $ret = -1; +} + +exit $ret; diff --git a/source3/script/tests/full_audit_segfault/run.sh b/source3/script/tests/full_audit_segfault/run.sh new file mode 100755 index 0000000..a2ba43f --- /dev/null +++ b/source3/script/tests/full_audit_segfault/run.sh @@ -0,0 +1,25 @@ +#!/bin/sh +if [ $# -lt 1 ]; then + cat <. + +import sys +import traceback +import logging +import os + +USER_QUOTAS = 1 +USER_DEFAULT_QUOTAS = 2 +GROUP_QUOTAS = 3 +GROUP_DEFAULT_QUOTAS = 4 + +#Quota model + +class Quota: + def __init__(self): + self.flags = 0 + self.quotatype = USER_DEFAULT_QUOTAS + self.uid = 0 + self.usedblocks = 0 + self.softlimit = 0 + self.hardlimit = 0 + self.hardlimit = 0 + self.usedinodes = 0 + self.slimitinodes = 0 + self.hlimitinodes = 0 + +def quota_to_str(item): + result = str(item.flags) + " " + str(item.usedblocks) + " " + str(item.softlimit) + " " + str(item.hardlimit) + " " + str(item.usedinodes) + " " + str(item.slimitinodes) + " " + str(item.hlimitinodes) + return result + +def quota_to_db_str(item): + result = item.uid + " " + str(item.usedblocks) + " " + str(item.softlimit) + " " + str(item.hardlimit) + " " + str(item.usedinodes) + " " + str(item.slimitinodes) + " " + str(item.hlimitinodes) + return result + +def load_quotas(input_file): + fileContents = open(input_file,"r") + lineno = 0 + quotas = [] + for line in fileContents: + if line.strip().startswith("#"): + continue + content = line.strip().split() + quota = Quota() + if len(content) < 7: + logging.debug("ignoring line %d, doesn't have enough fields\n"%lineno) + else: + quota.flags = 2 + quota.uid = content[0] + quota.usedblocks = content[1] + quota.softlimit = content[2] + quota.hardlimit = content[3] + quota.usedinodes = content[4] + quota.slimitinodes = content[5] + quota.hlimitinodes = content[6] + quotas.append(quota) + + fileContents.close() + return quotas + +def set_quotas(quota_list, output_file): + filecontents = open(output_file,"w+") + if filecontents == None: + return False + lines = "" + for quota in quota_list: + next_line = quota_to_db_str(quota) + if next_line: + lines = lines + next_line + "\n" + filecontents.write(lines) + filecontents.close() + return True + +def get_quotas(uid, quota_list): + logging.debug("in get_quotas\n") + for quota in quota_list: + if quota.uid == uid: + return quota + return None + +def main(): + logging.basicConfig(format='%(asctime)s %(message)s', level=logging.DEBUG) + logging.debug("system args passed are %s\n"% str(sys.argv)) + quota_file_dir = os.path.dirname(sys.argv[0]) + quota_file_db = os.path.join(quota_file_dir,"quotas.db") + logging.debug("quota db is located %s\n", quota_file_db) + quota_list = load_quotas(quota_file_db) + logging.debug("quotas loaded have %s entries\n", len(quota_list)) + result = None + if len(sys.argv) == 4: + # Get Quota + directory = sys.argv[1] + if sys.argv[2] == "1": + query_type = USER_QUOTAS + elif sys.argv[2] == "2": + query_type = USER_DEFAULT_QUOTAS + elif sys.argv[2] == "3": + query_type = GROUP_QUOTAS + elif sys.argv[2] == "4": + query_type = GROUP_DEFAULT_QUOTAS + uid = sys.argv[3] + quota = get_quotas(uid, quota_list) + if quota is None: + logging.debug("no result for uid %s"%uid) + else: + result = quota_to_str(quota) + logging.debug("got result for uid %s\n"%uid) + if result is None: + result = "0 0 0 0 0 0 0" + logging.debug("for uid %s returning quotas %s\n"%(uid,result)) + print("%s"%result) + elif len(sys.argv) > 8: + # Set Quota + quota = Quota() + directory = sys.argv[1] + quota.query_type = sys.argv[2] + quota.uid = sys.argv[3] + quota.flags = sys.argv[4] + quota.softlimit = sys.argv[5] + quota.hardlimit = sys.argv[6] + quota.slimitinodes = sys.argv[7] + quota.hlimitinodes = sys.argv[8] + found = get_quotas(quota.uid, quota_list) + if found: + found.query_type = quota.query_type + found.uid = quota.uid + found.flags = quota.flags + found.softlimit = quota.softlimit + found.hardlimit = quota.hardlimit + found.slimitinodes = quota.slimitinodes + found.hlimitinodes = quota.hlimitinodes + else: + quota_list.append(quota) + if set_quotas(quota_list,quota_file_db): + print ("%s\n"%quota_to_str(quota_list[-1])) + return +if __name__ == '__main__': + main() diff --git a/source3/script/tests/printing/modprinter.pl b/source3/script/tests/printing/modprinter.pl new file mode 100755 index 0000000..28817db --- /dev/null +++ b/source3/script/tests/printing/modprinter.pl @@ -0,0 +1,140 @@ +#!/usr/bin/perl -w + +use strict; + +use Getopt::Long; +use Cwd qw(abs_path); + +my $opt_help = 0; +my $opt_smb_conf = undef; +my $opt_add = 0; +my $opt_delete = 0; + +my $result = GetOptions( + 'help|h|?' => \$opt_help, + 'smb_conf|s=s' => \$opt_smb_conf, + 'add|a' => \$opt_add, + 'delete|d' => \$opt_delete +); + +sub usage($;$) +{ + my ($ret, $msg) = @_; + + print $msg."\n\n" if defined($msg); + + print "usage: + + --help|-h|-? Show this help. + + --smb_conf|-s Path of the 'smb.conf' file. + + --add|-a 'add' a printer. + --delete|-d 'delete' a printer. + + printer_name share_name port_name driver_name location XX remote_machine +"; + exit($ret); +} + +usage(1) if (not $result); + +usage(0) if ($opt_help); + +if (!$opt_add && !$opt_delete) { + usage(1, "invalid: neither --add|-a nor --delete|-d set"); +} + +if (!$opt_smb_conf) { + usage(1, "invalid: no smb.conf file set"); +} + +my @argv = @ARGV; + +my $printer_name = shift(@argv); +my $share_name = shift(@argv); +my $port_name = shift(@argv); +my $driver_name = shift(@argv); +my $location = shift(@argv); +my $win9x_driver_location = shift(@argv); +my $remote_machine = shift(@argv); + +if (!defined($share_name) || length($share_name) == 0) { + $share_name = $printer_name; +} + +if (!defined($share_name)) { + die "share name not defined"; +} + +my $smb_conf_file = $opt_smb_conf; +if ($smb_conf_file =~ /^(.*)$/) { + $smb_conf_file = $1; # untaint file name +} else { + die "Invalid file name $smb_conf_file"; +} + +my $tmp = $smb_conf_file.$$; + +my $section = undef; +my $within_section = 0; +my $found_section = 0; + +open(CONFIGFILE_NEW, "+>$tmp") || die "Unable top open conf file $tmp"; + +open (CONFIGFILE, "+<$smb_conf_file") || die "Unable to open config file $smb_conf_file"; +while () { + my $line = $_; + chomp($_); + $_ =~ s/^\s*//; + $_ =~ s/\s*$//; + if (($_ =~ /^#/) || ($_ =~ /^;/)) { + print CONFIGFILE_NEW $line; + next; + } + if ($_ =~ /^\[.*\]$/) { + $_ = substr($_, 1, length($_)-2); + if (length($_)) { + $section = $_; + } else { + die "invalid section found"; + } + if ($section eq $share_name) { + $found_section = 1; + if ($opt_add) { + exit 0; +# die("share $share_name already exists\n"); + } + if ($opt_delete) { + $within_section = 1; + next; + } + } else { + print CONFIGFILE_NEW $line; + $within_section = 0; + } + next; + } else { + if ($within_section == 1) { + next; + } + print CONFIGFILE_NEW $line; + } +} +if ($opt_add) { + print CONFIGFILE_NEW "[$share_name]\n\tprintable = yes\n\tpath = /tmp\n"; +} +close (CONFIGFILE); +close (CONFIGFILE_NEW); + +if ($opt_delete && ($found_section == 0)) { + die "share $share_name not found"; +} + +delete @ENV{"BASH_ENV"}; + +$ENV{'PATH'} = '/bin:/usr/bin'; # untaint PATH +system("cp", "$tmp", "$smb_conf_file"); +unlink $tmp; + +exit 0; diff --git a/source3/script/tests/printing/printing_var_exp_lpr_cmd.sh b/source3/script/tests/printing/printing_var_exp_lpr_cmd.sh new file mode 100755 index 0000000..c25b49a --- /dev/null +++ b/source3/script/tests/printing/printing_var_exp_lpr_cmd.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +logfile="${SELFTEST_TMPDIR}/${USER}_printing_var_exp.log" + +rm -f "$logfile" + +for i in $(seq 1 $#); do + eval echo "arg $i: \$$i" >>"$logfile" +done diff --git a/source3/script/tests/smbspool_argv_wrapper.c b/source3/script/tests/smbspool_argv_wrapper.c new file mode 100644 index 0000000..6f84f3b --- /dev/null +++ b/source3/script/tests/smbspool_argv_wrapper.c @@ -0,0 +1,72 @@ +/* + Wrapper for smbspool to test Device URI in argv[0] + + Copyright (C) Bryan Mason 2019 + + 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 . +*/ + +#include +#include +#include + +/* + * Before calling a backend like smbspool, CUPS will set argv[0] to + * the Device URI. This program wraps a program like smbspool and + * sets argv[0] to the device URI before exec()ing the actual backend + * program. + */ + +int main(int argc, char *argv[], char *envp[]) +{ + char **new_argv; + char *exec_path; + int a; + int rv; +/* + * Expected parameters: + * + * smbspool_argv_wrapper smbspool uri job user title copies opts file(s) + * argv[0] 1 2 3 4 5 6 7 8 + * + */ + /* Allocate memory for the new arguments (exit on failure). */ + new_argv = calloc(argc, sizeof(char *)); + if (new_argv == 0) { + exit(ENOMEM); + } + + /* Save the path to the smbspool executable */ + exec_path = argv[1]; + + /* + * Shift the rest of the args so smbspool is called with: + * + * uri job user title copies opts file(s) + * argv[0] 1 2 3 4 5 6 + */ + + for (a = 2; a < argc; a++) { + new_argv[a-2] = argv[a]; + } + + /* Execute smbspool with new arguments */ + rv = execve(exec_path, new_argv, envp); + if (rv == -1) { + exit(errno); + } + + /* Avoid compiler error/warning */ + return 0; +} diff --git a/source3/script/tests/stream-depot/run.sh b/source3/script/tests/stream-depot/run.sh new file mode 100755 index 0000000..bcc85b6 --- /dev/null +++ b/source3/script/tests/stream-depot/run.sh @@ -0,0 +1,36 @@ +#!/bin/sh +if [ $# -lt 2 ]; then + cat </dev/null) || exit 1 + $SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD -a "ACL:$SERVER\force_user:ALLOWED/0x0/READ" 2>/dev/null || exit 1 + af=$($SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "posix; getfacl $fname" 2>/dev/null) || exit 1 + echo "before: $b4" + echo "after: $af" + echo "${b4}" | grep -q "^# owner:" || exit 1 + echo "${af}" | grep -q "^# owner:" || exit 1 + if test "$expected" = "true"; then + test "$b4" != "$af" + else + test "$b4" = "$af" + fi +} + +nt_affects_chown() +{ + local share=$1 + local b4_expected + local af_expected + local b4_actual + local af_actual + local fname="$share.$$" + + echo -n "determining uid of $USERNAME..." + b4_expected=$(getent passwd $USERNAME) || exit 1 + b4_expected=$(echo "$b4_expected" | awk -F: '{print $3}') + echo "$b4_expected" + + echo -n "determining uid of force_user..." + af_expected=$(getent passwd force_user) || exit 1 + af_expected=$(echo "$af_expected" | awk -F: '{print $3}') + echo "$af_expected" + + #basic sanity... + test "$b4_expected != $af_expected" || exit 1 + + b4_actual=$($SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "posix; getfacl $fname" 2>/dev/null) || exit 1 + echo "${b4_actual}" | grep -q "^# owner:" || exit 1 + b4_actual=$(echo "$b4_actual" | sed -rn 's/^# owner: (.*)/\1/p') + $SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD -a "ACL:$SERVER\force_user:ALLOWED/0x0/FULL" || exit 1 + $SMBCACLS //$SERVER/$share $fname -U force_user%$PASSWORD -C force_user 2>/dev/null || exit 1 + af_actual=$($SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "posix; getfacl $fname" 2>/dev/null) || exit 1 + echo "${af_actual}" | grep -q "^# owner:" || exit 1 + af_actual=$(echo "$af_actual" | sed -rn 's/^# owner: (.*)/\1/p') + echo "before: $b4_actual" + echo "after: $af_actual" + test "$b4_expected" = "$b4_actual" && test "$af_expected" = "$af_actual" +} + +nt_affects_chgrp() +{ + local share=$1 + local b4_expected + local af_expected + local b4_actual + local af_actual + local fname="$share.$$" + + echo -n "determining gid of domusers..." + b4_expected=$(getent group domusers) || exit 1 + b4_expected=$(echo "$b4_expected" | awk -F: '{print $3}') + echo "$b4_expected" + + echo -n "determining gid of domadmins..." + af_expected=$(getent group domadmins) || exit 1 + af_expected=$(echo "$af_expected" | awk -F: '{print $3}') + echo "$af_expected" + + #basic sanity... + test "$b4_expected" != "$af_expected" || exit 1 + + b4_actual=$($SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "posix; getfacl $fname" 2>/dev/null) || exit 1 + echo "${b4_actual}" | grep -q "^# group:" || exit 1 + b4_actual=$(echo "$b4_actual" | sed -rn 's/^# group: (.*)/\1/p') + $SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD -G domadmins 2>/dev/null || exit 1 + af_actual=$($SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "posix; getfacl $fname" 2>/dev/null) || exit 1 + echo "${af_actual}" | grep -q "^# group:" || exit 1 + af_actual=$(echo "$af_actual" | sed -rn 's/^# group: (.*)/\1/p') + echo "before: $b4_actual" + echo "after: $af_actual" + test "$af_expected" != "$b4_actual" && test "$af_expected" = "$af_actual" +} + +testit "setup remote file tmp" setup_remote_file tmp +testit "setup remote file ign_sysacls" setup_remote_file ign_sysacls +testit "smbcacls -x" smbcacls_x tmp +testit "nt_affects_posix tmp" nt_affects_posix tmp "true" +testit "nt_affects_posix ign_sysacls" nt_affects_posix ign_sysacls "false" +testit "setup remote file tmp" setup_remote_file tmp +testit "setup remote file ign_sysacls" setup_remote_file ign_sysacls +testit "nt_affects_chown tmp" nt_affects_chown tmp +testit "nt_affects_chown ign_sysacls" nt_affects_chown ign_sysacls +testit "setup remote file tmp" setup_remote_file tmp +testit "setup remote file ign_sysacls" setup_remote_file ign_sysacls +testit "nt_affects_chgrp tmp" nt_affects_chgrp tmp +testit "nt_affects_chgrp ign_sysacls" nt_affects_chgrp ign_sysacls diff --git a/source3/script/tests/test_aio_outstanding.sh b/source3/script/tests/test_aio_outstanding.sh new file mode 100755 index 0000000..a497181 --- /dev/null +++ b/source3/script/tests/test_aio_outstanding.sh @@ -0,0 +1,99 @@ +#!/usr/bin/env bash +# +# Test terminating an smbclient connection with outstanding +# aio requests. +# +# Note this is designed to be run against +# the aio_delay_inject share which is preconfigured +# with 2 second delays on pread/pwrite. + +if [ $# -lt 4 ]; then + echo Usage: test_aio_outstanding.sh \ + SERVERCONFFILE SMBCLIENT IP aio_delay_inject_sharename + exit 1 +fi + +CONF=$1 +SMBCLIENT=$2 +SERVER=$3 +SHARE=$4 + +# Do not let deprecated option warnings muck this up +SAMBA_DEPRECATED_SUPPRESS=1 +export SAMBA_DEPRECATED_SUPPRESS + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +cd $SELFTEST_TMPDIR || exit 1 + +# +# Note if we already have any panics in the smbd log. +# +panic_count_0=$(grep -c PANIC $SMBD_TEST_LOG) + +# Create the smbclient communication pipes. +rm -f smbclient-stdin smbclient-stdout smbclient-stderr +mkfifo smbclient-stdin smbclient-stdout smbclient-stderr + +# Create a large-ish testfile +rm aio_outstanding_testfile +head -c 20MB /dev/zero >aio_outstanding_testfile + +CLI_FORCE_INTERACTIVE=1 +export CLI_FORCE_INTERACTIVE + +${SMBCLIENT} //${SERVER}/${SHARE} ${CONF} -U${USER}%${PASSWORD} \ + smbclient-stdout 2>smbclient-stderr & +CLIENT_PID=$! + +sleep 1 + +exec 100>smbclient-stdin 101&100 +echo "put aio_outstanding_testfile" >&100 + +sleep 2 + +# Terminate the smbclient write to the aio_delay_inject share whilst +# we have outstanding writes. +kill $CLIENT_PID + +sleep 1 + +# Ensure the panic count didn't change. +# +# BUG: https://bugzilla.samba.org/show_bug.cgi?id=14301 +# + +panic_count_1=$(grep -c PANIC $SMBD_TEST_LOG) + +# Rerun smbclient to remove the testfile on the server. +rm -f smbclient-stdin smbclient-stdout smbclient-stderr aio_outstanding_testfile +mkfifo smbclient-stdin smbclient-stdout + +${SMBCLIENT} //${SERVER}/${SHARE} ${CONF} -U${USER}%${PASSWORD} \ + smbclient-stdout & + +sleep 1 + +exec 100>smbclient-stdin 101&100 +echo "exit" >&100 + +sleep 2 + +rm -f smbclient-stdin smbclient-stdout aio_outstanding_testfile + +testit "check_panic" test $panic_count_0 -eq $panic_count_1 || + failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_async_req.sh b/source3/script/tests/test_async_req.sh new file mode 100755 index 0000000..27b4680 --- /dev/null +++ b/source3/script/tests/test_async_req.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +SOCKET_WRAPPER_IPV4_NETWORK="127.0.0.0" +export SOCKET_WRAPPER_IPV4_NETWORK + +testit "async_connect_send" $VALGRIND $BINDIR/async_connect_send_test || + failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_bad_auditnames.sh b/source3/script/tests/test_bad_auditnames.sh new file mode 100755 index 0000000..69ddf14 --- /dev/null +++ b/source3/script/tests/test_bad_auditnames.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +# this tests a full audit share with bad VFS +# names will not allow connection. +# BUG: https://bugzilla.samba.org/show_bug.cgi?id=15098 + +if [ $# -lt 5 ]; then + cat </dev/null 2>&1 +} + +testit "Cannot connect to share $SHARE" can_connect || failed=$((failed + 1)) diff --git a/source3/script/tests/test_bug15435_widelink_dfs.sh b/source3/script/tests/test_bug15435_widelink_dfs.sh new file mode 100755 index 0000000..f0705ca --- /dev/null +++ b/source3/script/tests/test_bug15435_widelink_dfs.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +# regression test for dfs access with wide links enabled on dfs share + +if [ $# -lt 5 ]; then + cat < +EOF + exit 1 +fi + +SERVER="$1" +SERVER_IP="$2" +USERNAME="$3" +PASSWORD="$4" +smbclient="$5" +CONFIGURATION="$6" +shift 6 +ADDARGS="$@" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +. $incdir/common_test_fns.inc + +# TEST +test_smbclient "smbclient as $DOMAIN\\$USERNAME" 'ls' "//$SERVER/msdfs-share-wl" -U$DOMAIN\\$USERNAME%$PASSWORD $ADDARGS -c 'cd msdfs-src1' || failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/test_chdir_cache.sh b/source3/script/tests/test_chdir_cache.sh new file mode 100755 index 0000000..29f54d1 --- /dev/null +++ b/source3/script/tests/test_chdir_cache.sh @@ -0,0 +1,122 @@ +#!/usr/bin/env bash +# +# Ensure we get a chdir_current_service error if CHDIR fails with EACCESS +# for an SMB2 request. +# +# BUG:https://bugzilla.samba.org/show_bug.cgi?id=14682 +# +# Copyright (C) 2021 Jeremy Allison + +if [ $# -lt 5 ]; then + echo Usage: test_chdir_cache.sh \ + --configfile=SERVERCONFFILE SMBCLIENT SMBCONTROL SERVER SHARE PREFIX TESTENV + exit 1 +fi + +CONF=$1 +shift 1 +SMBCLIENT=$1 +shift 1 +SMBCONTROL=$1 +shift 1 +SERVER=$1 +shift 1 +SHARE=$1 +shift 1 +PREFIX=${1} +shift 1 +TESTENV=${1} +shift 1 + +PREFIX_ABS="$(readlink -f "${PREFIX}")" + +# Do not let deprecated option warnings muck this up +SAMBA_DEPRECATED_SUPPRESS=1 +export SAMBA_DEPRECATED_SUPPRESS + +conf_dir=$(dirname ${SERVERCONFFILE}) + +error_inject_conf=${conf_dir}/error_inject.conf +rm -f ${error_inject_conf} + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +cd $SELFTEST_TMPDIR || exit 1 + +rm -f smbclient-stdin smbclient-stdout smbclient-stderr +mkfifo smbclient-stdin smbclient-stdout smbclient-stderr + +CLI_FORCE_INTERACTIVE=1 +export CLI_FORCE_INTERACTIVE + +${SMBCLIENT} //${SERVER}/${SHARE} ${CONF} -U${USER}%${PASSWORD} \ + smbclient-stdout 2>smbclient-stderr & +CLIENT_PID=$! + +log_file="${PREFIX_ABS}/${TESTENV}/smbd_test.log" +# Add support for "SMBD_DONT_LOG_STDOUT=1" +if [ -r "${PREFIX_ABS}/${TESTENV}/logs/log.smbd" ]; then + log_file="${PREFIX_ABS}/${TESTENV}/logs/log.smbd" +fi + +# Count the number of chdir_current_service: vfs_ChDir.*failed: Permission denied +# errors that are already in the log (should be zero). +num_errs=$(grep "chdir_current_service: vfs_ChDir.*failed: Permission denied" ${log_file} | wc -l) + +sleep 1 + +exec 100>smbclient-stdin 101&100 + +# consume the smbclient output +head -n 4 <&101 + +# Now change user to user2, and connect to the share. +# This should leave us in the same share directory. +echo "logon user2 ${PASSWORD}" >&100 +echo "tcon ${SHARE}" >&100 + +# consume the smbclient output +head -n 4 <&101 + +# Ensure any chdir will give EACCESS. +echo "error_inject:chdir = EACCES" >${error_inject_conf} +testit "reload config 1" \ + "${SMBCONTROL}" "${CONF}" smbd reload-config || + failed=$((failed + 1)) + +sleep 1 + +# Do an 'ls' as user2. Changing users should have +# deleted the CHDIR cache, so we should now see +# a chdir_current_service: vfs_ChDir.*failed: Permission denied +# error message in the log. +echo 'ls' >&100 + +kill ${CLIENT_PID} +rm -f smbclient-stdin smbclient-stdout smbclient-stderr + +# Remove the chdir inject. +rm -f ${error_inject_conf} +testit "reload config 2" \ + "${SMBCONTROL}" "${CONF}" smbd reload-config || + failed=$((failed + 1)) + +# Now look for chdir_current_service: vfs_ChDir.*failed: Permission denied +# in the smb log. There should be one more than before. + +num_errs1=$(grep "chdir_current_service: vfs_ChDir.*failed: Permission denied" ${log_file} | wc -l) + +testit "Verify we got at least one chdir error" \ + test $num_errs1 -gt $num_errs || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_close_denied_share.sh b/source3/script/tests/test_close_denied_share.sh new file mode 100755 index 0000000..2e6e285 --- /dev/null +++ b/source3/script/tests/test_close_denied_share.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash +# +# Test smbcontrol close-denied-share command. +# +# Copyright (C) 2020 Volker Lendecke + +if [ $# -lt 6 ]; then + echo Usage: test_close_denied_share.sh \ + SERVERCONFFILE SHARESEC SMBCLIENT SMBCONTROL IP SHARE + exit 1 +fi + +CONF=$1 +SHARESEC=$2 +SMBCLIENT=$3 +SMBCONTROL=$4 +SERVER=$5 +SHARE=$6 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +cd $SELFTEST_TMPDIR || exit 1 + +rm -f smbclient-stdin smbclient-stdout +mkfifo smbclient-stdin smbclient-stdout + +CLI_FORCE_INTERACTIVE=1 +export CLI_FORCE_INTERACTIVE + +${SMBCLIENT} //${SERVER}/${SHARE} ${CONF} -U${USER}%${PASSWORD} \ + smbclient-stdout & +CLIENT_PID=$! + +sleep 1 + +exec 100>smbclient-stdin 101&100 + +COUNT=$(head -n 2 <&101 | + grep NT_STATUS_NETWORK_NAME_DELETED | + wc -l) +testit "Verify close-denied-share did not kill valid client" \ + test $COUNT -eq 0 || failed=$(expr $failed + 1) + +testit "Deny access" ${SHARESEC} ${CONF} --replace S-1-1-0:DENIED/0x0/FULL \ + ${SHARE} || failed=$(expr $failed + 1) + +testit "smbcontrol" ${SMBCONTROL} ${CONF} smbd close-denied-share ${SHARE} || + failed=$(expr $failed + 1) +sleep 1 + +echo dir >&100 + +COUNT=$(head -n 2 <&101 | + grep NT_STATUS_NETWORK_NAME_DELETED | + wc -l) +testit "Verify close-denied-share did kill now-invalid client" \ + test $COUNT -eq 1 || failed=$(expr $failed + 1) + +kill ${CLIENT_PID} +rm -f smbclient-stdin smbclient-stdout + +testit "Allow access" ${SHARESEC} ${CONF} --replace S-1-1-0:ALLOWED/0x0/FULL \ + ${SHARE} || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_deadtime.sh b/source3/script/tests/test_deadtime.sh new file mode 100755 index 0000000..3d6368e --- /dev/null +++ b/source3/script/tests/test_deadtime.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash +# +# Test deadtime parameter +# + +if [ $# -lt 1 ]; then + echo Usage: test_deadtime.sh IP + exit 1 +fi + +server=$1 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +. $incdir/common_test_fns.inc + +failed=0 + +smbclient="$BINDIR/smbclient" +smbcontrol="$BINDIR/smbcontrol" + +global_inject_conf=$(dirname $SMB_CONF_PATH)/global_inject.conf + +echo "deadtime = 1" >$global_inject_conf +$smbcontrol smbd reload-config + +cd $SELFTEST_TMPDIR || exit 1 + +# Create the smbclient communication pipes. +rm -f smbclient-stdin smbclient-stdout smbclient-stderr +mkfifo smbclient-stdin smbclient-stdout smbclient-stderr + +export CLI_FORCE_INTERACTIVE=1 +export SAMBA_DEPRECATED_SUPPRESS=1 + +# This gets inherited by smbclient and is required to smbclient doesn't get +# killed by an unhandled SIGPIPE when writing an SMB2 KEEPALIVE packet to the +# connection fd that was already closed by the server. +trap "" SIGPIPE + +$smbclient //$server/tmp -U${USER}%${PASSWORD} \ + smbclient-stdout 2>smbclient-stderr & +client_pid=$! + +sleep 1 + +exec 100>smbclient-stdin 101$global_inject_conf +$smbcontrol smbd reload-config + +rm -f smbclient-stdin smbclient-stdout smbclient-stderr + +testok $0 $failed diff --git a/source3/script/tests/test_delete_stream.sh b/source3/script/tests/test_delete_stream.sh new file mode 100755 index 0000000..43d591e --- /dev/null +++ b/source3/script/tests/test_delete_stream.sh @@ -0,0 +1,123 @@ +#!/bin/sh +# +# this verifies that deleting a stream uses the correct ACL +# when using vfs_acl_xattr. +# + +if [ $# -lt 9 ]; then + echo "Usage: $0 SERVER SERVER_IP USERNAME PASSWORD PREFIX SMBCLIENT SMBCACLS NET SHARE" + exit 1 +fi + +SERVER="$1" +SERVER_IP="$2" +USERNAME="$3" +PASSWORD="$4" +PREFIX="$5" +SMBCLIENT="$6" +SMBCACLS="$7" +NET="$8" +SHARE="$9" + +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +SMBCACLS="$VALGRIND ${SMBCACLS}" +NET="$VALGRIND ${NET}" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + + +setup_testfile() +{ + touch $PREFIX/file + echo stream > $PREFIX/stream + + $SMBCLIENT //$SERVER/$SHARE -U $USERNAME%$PASSWORD -c "mkdir dir" || return 1 + $SMBCLIENT //$SERVER/$SHARE -U $USERNAME%$PASSWORD -c "lcd $PREFIX; put file dir/file" || return 1 + $SMBCLIENT //$SERVER/$SHARE -U $USERNAME%$PASSWORD -c "lcd $PREFIX; put stream dir/file:stream" || return 1 + + rm $PREFIX/file + rm $PREFIX/stream + + # + # Add full control ACE to the file and an ACL without "DELETE" on the + # parent directory + # + + $SMBCACLS //$SERVER/$SHARE -U $USERNAME%$PASSWORD -S "ACL:Everyone:ALLOWED/0x0/0x1bf" dir || return 1 + $SMBCACLS //$SERVER/$SHARE -U $USERNAME%$PASSWORD -a "ACL:Everyone:ALLOWED/0x0/0x101ff" dir/file || return 1 +} + +remove_testfile() +{ + $SMBCACLS //$SERVER/$SHARE -U $USERNAME%$PASSWORD -S "ACL:Everyone:ALLOWED/0x0/0x101ff" dir/file || return 1 + $SMBCACLS //$SERVER/$SHARE -U $USERNAME%$PASSWORD -S "ACL:Everyone:ALLOWED/0x0/0x101ff" dir || return 1 + $SMBCLIENT //$SERVER/$SHARE -U $USERNAME%$PASSWORD -c "rm dir/file" || return 1 + $SMBCLIENT //$SERVER/$SHARE -U $USERNAME%$PASSWORD -c "rmdir dir" || return 1 +} + +set_win_owner() +{ + local owner=$1 + + $SMBCACLS //$SERVER/$SHARE dir/file -U $USERNAME%$PASSWORD -C "$owner" || return 1 +} + +delete_stream() +{ + # + # Setup a file with a stream where we're not the owner and + # have delete rights. Bug 15126 would trigger a fallback to + # "acl_xattr:default acl style" because fetching the stored + # ACL would fail. The stored ACL allows deleting the stream + # but the synthesized default ACL does not, so the deletion + # of the stream should work, but it fails if we have the bug. + # + + # Now try deleting the stream + out=$($SMBCLIENT //$SERVER/$SHARE -U $USERNAME%$PASSWORD -c "wdel 0x20 dir/file:stream") || return 1 + + # + # Bail out in case we get any sort of NT_STATUS_* error, should be + # NT_STATUS_ACCESS_DENIED, but let's not slip through any other error. + # + echo "$out" | grep NT_STATUS_ && return 1 + + return 0 +} + +win_owner_is() +{ + local expected_owner=$1 + local actual_owner + + $SMBCACLS //$SERVER/$SHARE dir/file -U $USERNAME%$PASSWORD + actual_owner=$($SMBCACLS //$SERVER/$SHARE dir/file -U $USERNAME%$PASSWORD | sed -rn 's/^OWNER:(.*)/\1/p') + echo "actual_owner = $actual_owner" + if ! test "x$actual_owner" = "x$expected_owner"; then + echo "Actual owner of dir/file is $actual_owner', expected $expected_owner" + return 1 + fi + return 0 +} + +# Create a testfile +testit "create testfile" setup_testfile $SHARE || exit 1 + +# Grant SeRestorePrivilege to the user so we can change the owner +testit "grant SeRestorePrivilege" $NET rpc rights grant $USERNAME SeRestorePrivilege -U $USERNAME%$PASSWORD -I $SERVER_IP || exit 1 + +# We have SeRestorePrivilege, so both give and take ownership must succeed +testit "give owner with SeRestorePrivilege" set_win_owner "$SERVER\user1" || exit 1 +testit "verify owner" win_owner_is "$SERVER/user1" || exit 1 + +# Now try to remove the stream on the testfile +testit "delete stream" delete_stream $SHARE afile || exit 1 + +# Remove testfile +testit "remove testfile" remove_testfile $SHARE || exit 1 + +# Revoke SeRestorePrivilege, give ownership must fail now with NT_STATUS_INVALID_OWNER +testit "revoke SeRestorePrivilege" $NET rpc rights revoke $USERNAME SeRestorePrivilege -U $USERNAME%$PASSWORD -I $SERVER_IP || exit 1 + +exit 0 diff --git a/source3/script/tests/test_delete_veto_files_only_rmdir.sh b/source3/script/tests/test_delete_veto_files_only_rmdir.sh new file mode 100755 index 0000000..08f257f --- /dev/null +++ b/source3/script/tests/test_delete_veto_files_only_rmdir.sh @@ -0,0 +1,182 @@ +#!/bin/sh +# +# Check smbclient can (or cannot) delete a directory containing dangling symlinks. +# BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879 +# + +if [ $# -lt 6 ]; then + cat <"$tmpfile" <"$tmpfile" <"$tmpfile" <"$tmpfile" <&1) + status=$? + if [ x$status = x0 ]; then + received=$(echo "$output" | awk '/blocks of size/ {print $1, $5, $6}') + if [ "$expected" = "$received" ]; then + subunit_pass_test "$name" + return 0 + else + echo "$output" | subunit_fail_test "$name" + return 1 + fi + else + echo "$output" | subunit_fail_test "$name" + return $status + fi +} + +if [ $protocol = "SMB3" ]; then + test_smbclient_dfree "Test dfree command share root SMB3" dfree "l" "2000 1024. 20" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) + test_smbclient_dfree "Test dfree command subdir1 SMB3" dfree "cd subdir1; l" "8000 1024. 80" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) + test_smbclient_dfree "Test dfree command subdir2 SMB3" dfree "cd subdir2; l" "32000 1024. 320" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) + +elif [ $protocol = "NT1" ]; then + test_smbclient_dfree "Test dfree command share root NT1" dfree "l" "2000 1024. 20" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=NT1 || failed=$(expr $failed + 1) + #SMB1 queries disk usage stat on the share's root, regardless of working directory + test_smbclient_dfree "Test dfree command subdir1 NT1" dfree "cd subdir1; l" "2000 1024. 20" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=NT1 || failed=$(expr $failed + 1) + +else + echo "unsupported protocol $protocol" | subunit_fail_test "Test dfree command" + failed=$(expr $failed + 1) +fi +exit $failed diff --git a/source3/script/tests/test_dfree_quota.sh b/source3/script/tests/test_dfree_quota.sh new file mode 100755 index 0000000..9151016 --- /dev/null +++ b/source3/script/tests/test_dfree_quota.sh @@ -0,0 +1,296 @@ +#!/bin/sh +# +# Blackbox test for disk-free, quota, and their interaction +# + +if [ $# -lt 6 ]; then + cat <>$CONFFILE + shift + shift + done + sighup_smbd + #let it load... + sleep .5 +} + +test_smbclient_dfree() +{ + name="$1" + share="$2" + dir="$3" + confs="$4" + expected="$5" + shift + shift + shift + shift + subunit_start_test "$name" + setup_conf $confs + output=$($VALGRIND $smbclient //$SERVER/$share -c "cd $dir; l" "$@" 2>&1) + status=$? + if [ "$status" = "0" ]; then + received=$(echo "$output" | awk '/blocks of size/ {print $1, $5, $6}') + if [ "$expected" = "$received" ]; then + subunit_pass_test "$name" + return 0 + else + echo "$output" | subunit_fail_test "$name" + return 1 + fi + else + echo "$output" | subunit_fail_test "$name" + return $status + fi +} + +# Issue two queries to different directories in one session to test +# caching effects +test_smbclient_dfree_2() +{ + name="$1" + share="$2" + dir1="$3" + dir2="$4" + confs="$5" + expected="$6" + subunit_start_test "$name" + setup_conf $confs + output=$($VALGRIND $smbclient //$SERVER/$share \ + -c "cd $dir1; du; cd ..; cd $dir2 ; du" "$@" 2>&1) + status=$? + if [ "$status" = "0" ]; then + received=$(echo "$output" | + awk '/blocks of size/ {print $1, $5, $6}' | + tr '\n' ' ') + if [ "$expected" = "$received" ]; then + subunit_pass_test "$name" + return 0 + else + echo "$output" | subunit_fail_test "$name" + return 1 + fi + else + echo "$output" | subunit_fail_test "$name" + return $status + fi +} + +test_smbcquotas() +{ + name="$1" + conf="$2" + user="$3" + expected="$4" + proto="$5" + shift + shift + shift + shift + shift + subunit_start_test "$name" + setup_conf "$conf" "." + if [ "$proto" = "smb2" ]; then + mproto="-m SMB2" + else + mproto="-m SMB1" + fi + + output=$($VALGRIND $smbcquotas $mproto //$SERVER/dfq "$@" 2>/dev/null | tr '\\' '/') + status=$? + if [ "$status" = "0" ]; then + received=$(echo "$output" | awk "/$SERVER\\/$user/ {printf \"%s%s%s\", \$3, \$4, \$5}") + if [ "$expected" = "$received" ]; then + subunit_pass_test "$name" + return 0 + else + echo "$output" | subunit_fail_test "$name" + return 1 + fi + else + echo "$output" | subunit_fail_test "$name" + return $status + fi +} + +if [ $protocol != "SMB3" ] && [ $protocol != "NT1" ]; then + echo "unsupported protocol $protocol" | subunit_fail_test "Test dfree quota" + failed=$(expr $failed + 1) +fi + +if [ $protocol = "NT1" ]; then + setup_conf + #basic quota test (SMB1 only) + test_smbcquotas "Test user quota" confq1 $USERNAME "40960/4096000/3072000" "smb1" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=NT1 || failed=$(expr $failed + 1) + exit $failed +fi + +#basic disk-free tests +test_smbclient_dfree "Test dfree share root SMB3 no quota" dfq "." "conf1 ." "10 1024. 5" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +test_smbclient_dfree "Test dfree subdir SMB3 no quota" dfq "subdir1" "conf1 . conf2 subdir1" "20 1024. 10" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +test_smbclient_dfree "Test large disk" dfq "." "conf3 ." "1125899906842624 1024. 3000" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +#basic quota test (SMB2 only) +test_smbcquotas "Test user quota" confq1 $USERNAME "40960/4096000/3072000" "smb2" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB2 || failed=$(expr $failed + 1) + +# Test dfree cache through queries in two different directories +test_smbclient_dfree_2 "Test dfree cache" dfq_cache "." "subdir1" \ + "conf1 . conf2 subdir1" "10 1024. 5 20 1024. 10 " \ + -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || + failed=$(expr $failed + 1) + +#quota limit > disk size, remaining quota > disk free +test_smbclient_dfree "Test dfree share root df vs quota case 1" dfq "." "confdfq1 ." "80 1024. 40" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +#quota limit > disk size, remaining quota < disk free +test_smbclient_dfree "Test dfree share root df vs quota case 2" dfq "." "confdfq2 ." "80 1024. 12" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +#quota limit < disk size, remaining quota > disk free +test_smbclient_dfree "Test dfree share root df vs quota case 3" dfq "." "confdfq3 ." "160 1024. 40" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +#quota limit < disk size, remaining quota < disk free +test_smbclient_dfree "Test dfree share root df vs quota case 4" dfq "." "confdfq4 ." "160 1024. 12" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +test_smbclient_dfree "Test dfree subdir df vs quota case 4" dfq "subdir1" "confdfq4 subdir1" "160 1024. 12" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) + +#quota-->disk free special cases +test_smbclient_dfree "Test quota->dfree soft limit" dfq "subdir1" "slimit subdir1" "168 1024. 0" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +test_smbclient_dfree "Test quota->dfree hard limit" dfq "subdir1" "hlimit subdir1" "180 1024. 0" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +test_smbclient_dfree "Test quota->dfree inode soft limit" dfq "subdir1" "islimit subdir1" "148 1024. 0" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +test_smbclient_dfree "Test quota->dfree inode hard limit" dfq "subdir1" "ihlimit subdir1" "148 1024. 0" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +test_smbclient_dfree "Test quota->dfree err try group" dfq "subdir1" "trygrp1 subdir1" "240 1024. 20" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +test_smbclient_dfree "Test quota->dfree no-quota try group" dfq "subdir1" "trygrp2 subdir1" "240 1024. 16" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) + +# sgid on directory +test_smbclient_dfree "Test quota on sgid directory" dfq "subdir1" \ + "sgid subdir1" "200 1024. 40" -U$USERNAME%$PASSWORD \ + --option=clientmaxprotocol=SMB3 || + failed=$(expr $failed + 1) + +#block size different in quota and df systems +test_smbclient_dfree "Test quota->dfree different block size" dfq "subdir1" "blksize subdir1" "307200 1024. 307200" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) + +#quota configured but not enforced +test_smbclient_dfree "Test dfree share root quota not enforced" dfq "." "notenforce ." "320 1024. 40" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) + +#FS quota not implemented (NFS case) +test_smbclient_dfree "Test dfree share root FS quota not implemented" dfq "." "nfs ." "160 1024. 12" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) + +#test for dfree when owner is inherited +#setup two folders with different owners +rm -rf $WORKDIR/subdir3/* +for d in / subdir3; do + $VALGRIND $smbcacls -U$USERNAME%$PASSWORD -D "ACL:$SERVER\user1:ALLOWED/0x0/FULL" //$SERVER/dfq $d >/dev/null 2>&1 + $VALGRIND $smbcacls -U$USERNAME%$PASSWORD -a "ACL:$SERVER\user1:ALLOWED/0x0/FULL" //$SERVER/dfq $d || failed=$(expr $failed + 1) + $VALGRIND $smbcacls -U$USERNAME%$PASSWORD -D "ACL:$SERVER\user2:ALLOWED/0x0/FULL" //$SERVER/dfq $d >/dev/null 2>&1 + $VALGRIND $smbcacls -U$USERNAME%$PASSWORD -a "ACL:$SERVER\user2:ALLOWED/0x0/FULL" //$SERVER/dfq $d || failed=$(expr $failed + 1) +done + +$VALGRIND $smbclient //$SERVER/dfq -c "cd subdir3; mkdir user1" -Uuser1%$PASSWORD --option=clientmaxprotocol=SMB3 >/dev/null 2>&1 || failed=$(expr $failed + 1) +$VALGRIND $smbclient //$SERVER/dfq -c "cd subdir3; mkdir user2" -Uuser2%$PASSWORD --option=clientmaxprotocol=SMB3 >/dev/null 2>&1 || failed=$(expr $failed + 1) +#test quotas +test_smbclient_dfree "Test dfree without inherit owner - user1 at user1" \ + dfq "subdir3/user1" "confdfqp subdir3/user1 confdfqp subdir3/user2" "160 1024. 16" \ + -Uuser1%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +test_smbclient_dfree "Test dfree without inherit owner - user1 at user2" \ + dfq "subdir3/user2" "confdfqp subdir3/user1 confdfqp subdir3/user2" "160 1024. 16" \ + -Uuser1%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +test_smbclient_dfree "Test dfree with inherit owner - user1 at user1" \ + dfq_owner "subdir3/user1" "confdfqp subdir3/user1 confdfqp subdir3/user2" "160 1024. 16" \ + -Uuser1%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +test_smbclient_dfree "Test dfree with inherit owner - user1 at user2" \ + dfq_owner "subdir3/user2" "confdfqp subdir3/user1 confdfqp subdir3/user2" "164 1024. 20" \ + -Uuser1%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) + +setup_conf +exit $failed diff --git a/source3/script/tests/test_dropbox.sh b/source3/script/tests/test_dropbox.sh new file mode 100755 index 0000000..a920c27 --- /dev/null +++ b/source3/script/tests/test_dropbox.sh @@ -0,0 +1,88 @@ +#!/bin/sh +# +# Blackbox test for valid users. +# + +if [ $# -lt 7 ]; then + cat <$filename_path + + cat >$tmpfile <$delay_inject_conf + +testit "durable_v2_delay.durable_v2_reconnect_delay" $VALGRIND \ + $BINDIR/smbtorture //$SERVER_IP/delay_inject \ + -U$USERNAME%$PASSWORD \ + smb2.durable-v2-delay.durable_v2_reconnect_delay || + failed=$(expr $failed + 1) + +SMBD_LOG_FILES="$SMBD_TEST_LOG" +if [ $SMBD_DONT_LOG_STDOUT -eq 1 ]; then + _SMBD_LOG_FILE=$(dirname $SMBD_TEST_LOG)/logs/log.smbd + SMBD_LOG_FILES="$SMBD_LOG_FILES $_SMBD_LOG_FILE" +fi + +testit "durable_v2_delay.durable_v2_reconnect_delay_msec" $VALGRIND \ + $BINDIR/smbtorture //$SERVER_IP/durable \ + -U$USERNAME%$PASSWORD \ + smb2.durable-v2-delay.durable_v2_reconnect_delay_msec || + failed=$(expr $failed + 1) + +rm $delay_inject_conf + +testok $0 $failed diff --git a/source3/script/tests/test_failure.sh b/source3/script/tests/test_failure.sh new file mode 100755 index 0000000..7a2c9ae --- /dev/null +++ b/source3/script/tests/test_failure.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# +# Blackbox test that should fail one of three subtests. +# +# Copyright (C) 2011 Michael Adam + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +test_failure() +{ + false +} + +test_success() +{ + true +} + +testit "success" \ + test_success || + failed=$(expr $failed + 1) + +testit "failure" \ + test_failure || + failed=$(expr $failed + 1) + +testit "success" \ + test_success || + failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_fakedircreatetimes.sh b/source3/script/tests/test_fakedircreatetimes.sh new file mode 100755 index 0000000..4ce2bcf --- /dev/null +++ b/source3/script/tests/test_fakedircreatetimes.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +if [ $# -lt 7 ]; then + cat <$tmpfile </dev/null + +# Create the smbclient communication pipes. +mkfifo $FIFO_STDIN $FIFO_STDOUT $FIFO_STDERR +if [ $? -ne 0 ]; then + echo "Failed to create fifos" + exit 1 +fi + +# Create a large-ish testfile +head -c 100MB /dev/zero >$TESTFILE + +CLI_FORCE_INTERACTIVE=1 +export CLI_FORCE_INTERACTIVE + +${smbclient} //${SERVER}/${SHARE} ${CONFIGURATION} -U${USER}%${PASSWORD} \ + <$FIFO_STDIN >$FIFO_STDOUT 2>$FIFO_STDERR & +CLIENT_PID=$! + +count=0 +while [ 1 ]; do + if [ $count -ge 20 ]; then + echo "Failed to start smbclient" + exit 1 + fi + kill -0 $CLIENT_PID + if [ $? -eq 0 ]; then + break + fi + sleep 0.5 + count=$((count + 1)) +done + +exec 100>$FIFO_STDIN 101<$FIFO_STDOUT 102<$FIFO_STDERR + +# consume the smbclient startup messages +head -n 1 <&101 + +# Ensure we're putting a fresh file. +echo "lcd $(dirname $TESTFILE)" >&100 +echo "del testfile" >&100 +echo "put testfile" >&100 + +sleep 0.2 + +# Close the aio_delay_inject share whilst we have outstanding writes. + +testit "smbcontrol" ${SMBCONTROL} ${CONFIGURATION} smbd close-share ${SHARE} || + failed=$(expr $failed + 1) + +sleep 0.5 + +# If we get one or more NT_STATUS_NETWORK_NAME_DELETED +# or NT_STATUS_INVALID_HANDLE on stderr from the writes we +# know the server stayed up and didn't crash when the +# close-share removed the share. +# +# BUG: https://bugzilla.samba.org/show_bug.cgi?id=14301 +# +COUNT=$(head -n 2 <&102 | + grep -e NT_STATUS_NETWORK_NAME_DELETED -e NT_STATUS_INVALID_HANDLE | + wc -l) + +testit "Verify close-share did cancel the file put" \ + test $COUNT -ge 1 || failed=$(expr $failed + 1) + +kill ${CLIENT_PID} + +# Remove the testfile from the server +test_smbclient "remove_testfile" \ + 'del testfile; quit' //${SERVER}/${SHARE} -U${USER}%${PASSWORD} || + failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_force_create_mode.sh b/source3/script/tests/test_force_create_mode.sh new file mode 100755 index 0000000..289f219 --- /dev/null +++ b/source3/script/tests/test_force_create_mode.sh @@ -0,0 +1,72 @@ +#!/bin/sh +# +# Blackbox test for 'force create mode' +# + +if [ $# -lt 7 ]; then + cat <$filename_path + + cat >$tmpfile < +# License: GPLv3 +# Regression test for BUG:https://bugzilla.samba.org/show_bug.cgi?id=13690 + +if [ $# -lt 6 ]; then + echo "Usage: test_force_group_change.sh SERVER USERNAME PASSWORD LOCAL_PATH SMBCLIENT SMBCONTROL" + exit 1 +fi + +SERVER="${1}" +USERNAME="${2}" +PASSWORD="${3}" +LOCAL_PATH="${4}" +SMBCLIENT="${5}" +SMBCONTROL="${6}" +shift 6 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +test_force_group_change() +{ + # + # A SMB_CONF variable passed in here is the client smb.conf. + # We need to convert to the server.conf file from + # the LOCAL_PATH variable. + # + SERVER_CONFIG=$(dirname $LOCAL_PATH)/lib/server.conf + SERVER_CONFIG_SAVE=${SERVER_CONFIG}.bak + SERVER_CONFIG_NEW=${SERVER_CONFIG}.new + cp $SERVER_CONFIG $SERVER_CONFIG_SAVE + + sed -e 's/#\tforce group = everyone/\tforce group = everyone/' <${SERVER_CONFIG} >${SERVER_CONFIG_NEW} + + tmpfile=$PREFIX/smbclient_force_group_change_commands + cat >$tmpfile <${error_inject_conf} + +$smbclient -U $DOMAIN/$USERNAME%$PASSWORD //$SERVER_IP/force_user_error_inject -c "mkdir dir" || failed=$(expr $failed + 1) +$smbclient -U $DOMAIN/$USERNAME%$PASSWORD //$SERVER_IP/force_user_error_inject -c "put WHATSNEW.txt dir/file" || failed=$(expr $failed + 1) + +testit "test_forced_user_can_delete" test_forced_user_can_delete || failed=$(expr $failed + 1) + +rm ${error_inject_conf} + +# Clean up after ourselves. +$smbclient -U $DOMAIN/$USERNAME%$PASSWORD //$SERVER_IP/force_user_error_inject -c "del dir/file; rmdir dir" + +testok $0 $failed diff --git a/source3/script/tests/test_forceuser_validusers.sh b/source3/script/tests/test_forceuser_validusers.sh new file mode 100755 index 0000000..11c1a5b --- /dev/null +++ b/source3/script/tests/test_forceuser_validusers.sh @@ -0,0 +1,60 @@ +#!/bin/sh +# +# Blackbox test for share with force user settings +# + +if [ $# -lt 6 ]; then + cat < +EOF + exit 1 +fi + +SERVER="$1" +DOMAIN="$2" +USERNAME="force_user" +PASSWORD="$4" +LOCAL_PATH="$5" +SMBCLIENT="$6" +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +shift 6 +ADDARGS="$*" +failed=0 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +cd $SELFTEST_TMPDIR || exit 1 + +run_cmd_nooutput() +{ + CMD="$1" + + out=$(eval ${CMD} >TESTOUT 2>&1) + if [ $? != 0 ]; then + cat TESTOUT + rm -f TESTOUT + echo "command failed" + false + return + fi + + rm -f TESTOUT + true + return +} + +test_force_user_valid_users() +{ + SMB_SHARE="force_user_valid_users" + run_cmd_nooutput "${SMBCLIENT} //${SERVER}/${SMB_SHARE} -U$USERNAME%$PASSWORD -c 'ls'" +} + +# Test +testit "force user not works when combined with valid users" \ + test_force_user_valid_users || failed=$(expr $failed + 1) + +# Cleanup + +# Results +testok $0 $failed diff --git a/source3/script/tests/test_fruit_resource_stream.sh b/source3/script/tests/test_fruit_resource_stream.sh new file mode 100755 index 0000000..7e99ea3 --- /dev/null +++ b/source3/script/tests/test_fruit_resource_stream.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +# this tests copying a file and then deleting it +# to a share using fruit:resource = stream +# BUG: https://bugzilla.samba.org/show_bug.cgi?id=15099 + +if [ $# -lt 6 ]; then + cat </dev/null 2>&1 +} + +rm -f "$LOCAL_PATH/src" +rm -f "$LOCAL_PATH/dst" +touch "$LOCAL_PATH/src" + +testit "resource_stream" put_then_delete_file || failed=$((failed + 1)) + +rm -f "$LOCAL_PATH/src" +rm -f "$LOCAL_PATH/dst" + +testok "$0" "$failed" diff --git a/source3/script/tests/test_give_owner.sh b/source3/script/tests/test_give_owner.sh new file mode 100755 index 0000000..9d00918 --- /dev/null +++ b/source3/script/tests/test_give_owner.sh @@ -0,0 +1,147 @@ +#!/bin/sh +# +# this verifies that SEC_STD_WRITE_OWNER only effectively grants take-ownership +# permissions but NOT give-ownership. +# + +if [ $# -lt 9 ]; then + echo "Usage: $0 SERVER SERVER_IP USERNAME PASSWORD PREFIX SMBCLIENT SMBCACLS NET SHARE" + exit 1 +fi + +SERVER="$1" +SERVER_IP="$2" +USERNAME="$3" +PASSWORD="$4" +PREFIX="$5" +SMBCLIENT="$6" +SMBCACLS="$7" +NET="$8" +SHARE="$9" + +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +SMBCACLS="$VALGRIND ${SMBCACLS}" +NET="$VALGRIND ${NET}" +failed=0 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +setup_testfile() +{ + local share=$1 + local fname=$2 + touch $PREFIX/$fname + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "rm $fname" + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "ls" | grep "$fname" && return 1 + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "lcd $PREFIX; put $fname" || return 1 +} + +remove_testfile() +{ + local share=$1 + local fname=$2 + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "rm $fname" +} + +set_win_owner() +{ + local share=$1 + local fname=$2 + local owner=$3 + echo "$SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD -C '$owner'" + $SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD -C "$owner" || return 1 +} + +win_owner_is() +{ + local share=$1 + local fname=$2 + local expected_owner=$3 + local actual_owner + + echo "$SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD" + $SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD + actual_owner=$($SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD | sed -rn 's/^OWNER:(.*)/\1/p') + echo "actual_owner = $actual_owner" + if ! test "x$actual_owner" = "x$expected_owner"; then + echo "Actual owner of $share/$fname is [$actual_owner] expected [$expected_owner]" + return 1 + fi + return 0 +} + +add_ace() +{ + local share=$1 + local fname=$2 + local ace=$3 + + local_ace=$(printf '%s' "$ace" | sed 's|\\|/|') + + # avoid duplicate + out=$($SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD) + if [ $? -ne 0 ]; then + echo "get acl failed" + echo "$out" + return 1 + fi + echo "Original ACL" + echo $out + echo "$out" | grep "$local_ace" && return 0 + + # add it + $SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD -a "$ace" + if [ $? -ne 0 ]; then + echo "add acl failed" + return 1 + fi + + # check it's there + out=$($SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD) + if [ $? -ne 0 ]; then + echo "get new acl failed" + echo "$out" + return 1 + fi + echo "New ACL" + echo $out + echo "Checking if new ACL has \"$local_ace\"" + echo "$out" | grep "$local_ace" || return 1 + echo "ok" +} + +chown_give_fails() +{ + local share=$1 + local fname=$2 + local user=$3 + local expected_error=$4 + + # this must fail + out=$($SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD -C "$user") && return 1 + # it failed, now check it returned the expected error code + echo "$out" | grep $expected_error || return 1 +} + +# Create a testfile +testit "create testfile" setup_testfile $SHARE afile || failed=$(expr $failed + 1) +testit "verify owner" win_owner_is $SHARE afile "$SERVER/$USERNAME" || failed=$(expr $failed + 1) + +# Grant SeRestorePrivilege to the user and full rights on the file +testit "grant SeRestorePrivilege" $NET rpc rights grant $USERNAME SeRestorePrivilege -U $USERNAME%$PASSWORD -I $SERVER_IP || failed=$(expr $failed + 1) +testit "grant full rights" add_ace $SHARE afile "ACL:$SERVER\\$USERNAME:ALLOWED/0x0/FULL" || failed=$(expr $failed + 1) + +# We have SeRestorePrivilege, so both give and take ownership must succeed +testit "give owner with SeRestorePrivilege" set_win_owner $SHARE afile "$SERVER\user1" || failed=$(expr $failed + 1) +testit "verify owner" win_owner_is $SHARE afile "$SERVER/user1" || failed=$(expr $failed + 1) +testit "take owner" set_win_owner $SHARE afile "$SERVER\\$USERNAME" || failed=$(expr $failed + 1) +testit "verify owner" win_owner_is $SHARE afile "$SERVER/$USERNAME" || failed=$(expr $failed + 1) + +# Revoke SeRestorePrivilege, give ownership must fail now with NT_STATUS_INVALID_OWNER +testit "revoke SeRestorePrivilege" $NET rpc rights revoke $USERNAME SeRestorePrivilege -U $USERNAME%$PASSWORD -I $SERVER_IP || failed=$(expr $failed + 1) +testit "give owner without SeRestorePrivilege" chown_give_fails $SHARE afile "$SERVER\user1" NT_STATUS_INVALID_OWNER || failed=$(expr $failed + 1) + +testit "delete testfile" remove_testfile $SHARE afile || failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/test_groupmap.sh b/source3/script/tests/test_groupmap.sh new file mode 100755 index 0000000..a1e9a08 --- /dev/null +++ b/source3/script/tests/test_groupmap.sh @@ -0,0 +1,217 @@ +#!/bin/sh +# test groupmap code tridge@samba.org September 2006 +# note that this needs root access to add unix groups, +# so this cannot be run on the build farm + +testone() +{ + echo $* + $VALGRIND bin/net groupmap $* +} + +tstart() +{ + TBASE=$(date '+%s') +} + +treport() +{ + TNOW=$(date '+%s') + echo "Took $(expr $TNOW - $TBASE) seconds" + TBASE=$TNOW +} + +rm -f $PREFIX_ABS/var/locks/group_mapping.?db + +NLOCAL=12 +NGROUP=11 +NBUILTIN=10 +DOMSID=$(bin/net getlocalsid | awk '{print $6}') +FORSID="S-1-2-3-4-5" + +echo "DOMSID $DOMSID" +echo "FORSID $FORSID" + +tstart +echo "Creating unix groups" +for i in $(seq 1 1 $NLOCAL); do + unixgroup=testlocal$i + gid=$(expr 30000 + $i) + groupdel $unixgroup 2>/dev/null + groupadd -g $gid $unixgroup || exit 1 +done +for i in $(seq 1 1 $NGROUP); do + unixgroup=testgrp$i + gid=$(expr 40000 + $i) + groupdel $unixgroup 2>/dev/null + groupadd -g $gid $unixgroup || exit 1 +done +for i in $(seq 1 1 $NBUILTIN); do + unixgroup=testb$i + gid=$(expr 50000 + $i) + groupdel $unixgroup 2>/dev/null + groupadd -g $gid $unixgroup || exit 1 +done +date + +treport + +echo "Creating local groups" +for i in $(seq 1 1 $NLOCAL); do + unixgroup=testlocal$i + ntgroup=ntlgrp$i + rid=$(expr 10000 + $i) + testone add rid=$rid unixgroup=$unixgroup ntgroup=$ntgroup type=local || exit 1 +done + +echo "trying a duplicate add" +testone add rid=10001 unixgroup=testlocal1 ntgroup=foo type=local && exit 1 + +treport + +echo "Creating domain groups" +for i in $(seq 1 1 $NGROUP); do + unixgroup=testgrp$i + ntgroup=ntgrp$i + rid=$(expr 20000 + $i) + testone add rid=$rid unixgroup=$unixgroup ntgroup=$ntgroup type=domain || exit 1 +done + +treport + +echo "Creating builtin groups" +for i in $(seq 1 1 $NBUILTIN); do + unixgroup=testb$i + ntgroup=ntbgrp$i + rid=$(expr 30000 + $i) + testone add rid=$rid unixgroup=$unixgroup ntgroup=$ntgroup type=builtin || exit 1 +done + +treport + +echo "Adding domain groups to local groups" +for i in $(seq 1 1 $NLOCAL); do + for j in $(seq 1 1 $i); do + + lrid=$(expr 10000 + $i) + drid=$(expr 20000 + $j) + + testone addmem $DOMSID-$lrid $DOMSID-$drid || exit 1 + (testone listmem $DOMSID-$lrid | sort -r) || exit 1 + done +done + +echo "trying a duplicate addmem" +testone addmem $DOMSID-10001 $DOMSID-20001 && exit 1 + +echo "Adding foreign SIDs to local groups" +for i in $(seq 1 1 $NLOCAL); do + for j in $(seq 1 1 $i); do + + lrid=$(expr 10000 + $i) + frid=$(expr 70000 + $j) + + testone addmem $DOMSID-$lrid $FORSID-$frid || exit 1 + (testone listmem $DOMSID-$lrid | sort -r) || exit 1 + done +done + +echo "trying a duplicate foreign addmem" +testone addmem $DOMSID-10001 $FORSID-70001 && exit 1 + +treport + +echo "Listing local group memberships of domain groups" +for i in $(seq 1 1 $NGROUP); do + rid=$(expr 20000 + $i) + (testone memberships $DOMSID-$rid | sort -r) || exit 1 +done + +echo "Trying memberships on bogus sid" +testone memberships $DOMSID-999999 || exit 1 + +treport + +testone list | sort + +echo "Deleting some domain groups" +for i in $(seq 2 2 $NGROUP); do + drid=$(expr 20000 + $i) + testone delete sid=$DOMSID-$drid || exit 1 +done + +echo "Trying duplicate domain group delete" +testone delete sid=$DOMSID-20002 && exit 1 + +treport + +echo "Deleting some local groups" +for i in $(seq 2 4 $NLOCAL); do + lrid=$(expr 10000 + $i) + testone delete sid=$DOMSID-$lrid || exit 1 +done + +echo "Trying duplicate local group delete" +testone delete sid=$DOMSID-10002 && exit 1 + +treport + +echo "Modifying some domain groups" +for i in $(seq 3 2 $NGROUP); do + drid=$(expr 20000 + $i) + testone modify sid=$DOMSID-$drid comment="newcomment-$i" type=domain || exit 1 +done + +treport + +testone list | sort + +echo "Listing local group memberships" +for i in $(seq 1 1 $NLOCAL); do + rid=$(expr 20000 + $i) + (testone memberships $DOMSID-$rid | sort -r) || exit 1 +done + +treport + +echo "Removing some domain groups from local groups" +for i in $(seq 1 2 $NLOCAL); do + for j in $(seq 1 3 $i); do + + lrid=$(expr 10000 + $i) + drid=$(expr 20000 + $j) + + testone delmem $DOMSID-$lrid $DOMSID-$drid || exit 1 + done +done + +echo "Trying duplicate delmem" +testone delmem $DOMSID-10001 $DOMSID-20001 && exit 1 + +treport + +echo "Listing local group memberships" +for i in $(seq 1 1 $NLOCAL); do + rid=$(expr 20000 + $i) + (testone memberships $DOMSID-$rid | sort -r) || exit 1 +done + +treport + +echo "Deleting unix groups" +for i in $(seq 1 1 $NLOCAL); do + unixgroup=testlocal$i + groupdel $unixgroup 2>/dev/null +done +for i in $(seq 1 1 $NGROUP); do + unixgroup=testgrp$i + groupdel $unixgroup 2>/dev/null +done +for i in $(seq 1 1 $NBUILTIN); do + unixgroup=testb$i + groupdel $unixgroup 2>/dev/null +done + +treport + +echo "ALL DONE" diff --git a/source3/script/tests/test_guest_auth.sh b/source3/script/tests/test_guest_auth.sh new file mode 100755 index 0000000..fc18114 --- /dev/null +++ b/source3/script/tests/test_guest_auth.sh @@ -0,0 +1,106 @@ +#!/bin/sh +# +# Test guest authentication +# +# Copyright (C) 2019 Ralph Boehme +# + +if [ $# -lt 5 ]; then + cat <&1) + bg_exists=$? + if [ $bg_exists != 0 ]; then + printf "Group map for BUILTIN\\Guests must exist for test\n" + return 1 + fi + + SIDS=$($NET $CONFIGURATION groupmap listmem S-1-5-32-546) + if [ $? != 0 ]; then + printf "$NET $CONFIGURATION groupmap listmem S-1-5-32-546 failed. Returned:\n" + printf "$SIDS\n" + return 1 + fi + printf "Got S-1-5-32-546 members:\n$SIDS\n" + + if [ "$SIDS" != "" ]; then + for SID in $SIDS; do + printf "Deleting member $SID from S-1-5-32-546\n" + $NET $CONFIGURATION groupmap delmem S-1-5-32-546 $SID || return 1 + done + fi + + return 0 +} + +add_local_guest_to_builtin_guests() +{ + if [ "$SIDS" != "" ]; then + for SID in $SIDS; do + printf "Adding $SID as member to S-1-5-32-546\n" + $NET $CONFIGURATION groupmap addmem S-1-5-32-546 $SID || return 1 + done + fi +} + +test_smbclient() +{ + $SMBCLIENT -U foo%bar //$SERVER/tmpguest -c exit + if [ $? != 0 ]; then + printf "smbclient failed\n" + return 1 + fi + return 0 +} + +testit "smbclient_guest_at_startup" \ + test_smbclient || + failed=$(expr $failed + 1) + +printf "Prepare BUILTIN\\Guests group mapping without members\n" + +prepare_empty_builtin_guests || { + printf "Setting up BUILTIN\\Guests without members failed\n" + exit 1 +} + +$SMBCONTROL $CONFIGURATION smbd reload-config || { + printf "Reloading parent smbd guest info failed\n" + exit 1 +} + +testit "smbclient_guest_auth_without_members" \ + test_smbclient || + failed=$(expr $failed + 1) + +# restore config +add_local_guest_to_builtin_guests + +$SMBCONTROL $CONFIGURATION smbd reload-config || { + printf "Reloading parent smbd guest info failed\n" + exit 1 +} + +testit "smbclient_works_after_restored_setup" \ + test_smbclient || + failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_homes.sh b/source3/script/tests/test_homes.sh new file mode 100755 index 0000000..be8e9b2 --- /dev/null +++ b/source3/script/tests/test_homes.sh @@ -0,0 +1,136 @@ +#!/bin/sh + +# Copyright (c) Andreas Schneider +# License: GPLv3 + +if [ $# -lt 7 ]; then + echo "Usage: test_homes.sh SERVER USERNAME PASSWORD LOCAL_PATH PREFIX SMBCLIENT CONFIGURATION" + exit 1 +fi + +SERVER="${1}" +USERNAME="${2}" +PASSWORD="${3}" +LOCAL_PATH="${4}" +PREFIX="${5}" +SMBCLIENT="${6}" +CONFIGURATION="${7}" +shift 7 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +test_gooduser_home() +{ + tmpfile=$PREFIX/smbclient_homes_gooduser_commands + cat >$tmpfile <$tmpfile <$tmpfile < +EOF + exit 1 +fi + +SERVER="$1" +USERNAME="$2" +PASSWORD="$3" +PREFIX="$4" +SMBCLIENT="$5" +SMBCACLS="$6" +NET="$7" +SHARE="$8" +INH_WIN="$9" +INH_UNIX="${10}" +shift 10 +ADDARGS="$*" +SMBCLIENT="$VALGRIND ${SMBCLIENT} ${ADDARGS}" +SMBCACLS="$VALGRIND ${SMBCACLS} ${ADDARGS}" +NET="$VALGRIND ${NET}" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +create_file() +{ + local share=$1 + local fname=$2 + local rem_dirname=$(dirname $fname) + local bname=$(basename $fname) + touch $PREFIX/$bname + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "cd $rem_dirname; rm $bname" 2>/dev/null + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "cd $rem_dirname; allinfo $bname" 2>/dev/null | grep "NT_STATUS_OBJECT_NAME_NOT_FOUND" || exit 1 + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "lcd $PREFIX; cd $rem_dirname; put $bname" 2>/dev/null || exit 1 +} + +create_dir() +{ + local share=$1 + local dname=$2 + local rem_dirname=$(dirname $dname) + local bname=$(basename $dname) + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "cd $rem_dirname; rmdir $bname" 2>/dev/null + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "cd $rem_dirname; allinfo $bname" 2>/dev/null | grep "NT_STATUS_OBJECT_NAME_NOT_FOUND" || exit 1 + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "cd $rem_dirname; mkdir $bname" 2>/dev/null || exit 1 +} + +cleanup_file() +{ + local share=$1 + local fname=$2 + local rem_dirname=$(dirname $fname) + local bname=$(basename $fname) + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "cd $rem_dirname; rm $bname" 2>/dev/null || exit 1 +} + +cleanup_dir() +{ + local share=$1 + local dname=$2 + local rem_dirname=$(dirname $dname) + local bname=$(basename $dname) + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "cd $rem_dirname; rmdir $bname" 2>/dev/null || exit 1 +} + +set_win_owner() +{ + local share=$1 + local fname=$2 + local owner=$3 + $SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD -C $owner 2>/dev/null || exit 1 +} + +unix_owner_id_is() +{ + local share=$1 + local fname=$2 + local expected_id=$3 + local actual_id + actual_id=$($SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "posix; getfacl $fname" 2>/dev/null | sed -rn 's/^# owner: (.*)/\1/p') + if ! test "x$actual_id" = "x$expected_id"; then + echo "Actual uid of $share/$fname is [$actual_id] expected [$expected_id]" + exit 1 + fi +} + +get_unix_id() +{ + local user=$1 + local ent + ent=$(getent passwd $user) || exit 1 + echo "$ent" | awk -F: '{print $3}' +} + +win_owner_is() +{ + local share=$1 + local fname=$2 + local expected_owner=$3 + local actual_owner + actual_owner=$($SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD 2>/dev/null | sed -rn 's/^OWNER:(.*)/\1/p') + if ! test "x$actual_owner" = "x$expected_owner"; then + echo "Actual owner of $share/$fname is [$actual_owner] expected [$expected_owner]" + exit 1 + fi +} + +default_uid=$(get_unix_id $USERNAME) +alt_uid=$(get_unix_id force_user) + +if [ "$INH_WIN" = "0" ] && [ "$INH_UNIX" = "0" ]; then + #default - file owned by creator, change-owner modifies both + WIN_OWNER_AFTER_CREATE="$SERVER/$USERNAME" + UNIX_OWNER_AFTER_CREATE=$(get_unix_id $USERNAME) + WIN_OWNER_AFTER_CHOWN="$SERVER/smbget_user" + UNIX_OWNER_AFTER_CHOWN=$(get_unix_id smbget_user) + TEST_LABEL="default" +elif [ "$INH_WIN" = "1" ] && [ "$INH_UNIX" = "1" ]; then + #inherit owner=windows and unix - file owned by parent + #owner, change-owner modifies both + WIN_OWNER_AFTER_CREATE="$SERVER/force_user" + UNIX_OWNER_AFTER_CREATE=$(get_unix_id force_user) + WIN_OWNER_AFTER_CHOWN="$SERVER/smbget_user" + UNIX_OWNER_AFTER_CHOWN=$(get_unix_id smbget_user) + TEST_LABEL="both" +elif [ "$INH_WIN" = "0" ] && [ "$INH_UNIX" = "1" ]; then + #inherit owner=unix only - windows owner is creator, + #unix owner inherited, upon change-owner only windows + #owner is changed + WIN_OWNER_AFTER_CREATE="$SERVER/$USERNAME" + UNIX_OWNER_AFTER_CREATE=$(get_unix_id force_user) + WIN_OWNER_AFTER_CHOWN="$SERVER/smbget_user" + UNIX_OWNER_AFTER_CHOWN=$(get_unix_id force_user) + TEST_LABEL="unix" +else + echo "Unknown combination INH_WIN=$INH_WIN INH_UNIX=$INH_UNIX" + exit 1 +fi + +# SETUP +testit "$TEST_LABEL - setup root dir" create_dir tmp tmp.$$ +testit "grant SeRestorePrivilege" $NET rpc rights grant $USERNAME SeRestorePrivilege -U $USERNAME%$PASSWORD -I $SERVER || exit 1 +testit "$TEST_LABEL - assign default ACL" $SMBCACLS //$SERVER/tmp tmp.$$ -U $USERNAME%$PASSWORD -S "REVISION:1,OWNER:$SERVER\force_user,GROUP:$SERVER\domusers,ACL:Everyone:ALLOWED/0x3/FULL" 2>/dev/null +# END SETUP + +testit "$TEST_LABEL - create subdir under root" create_dir $SHARE tmp.$$/subdir +testit "$TEST_LABEL - verify subdir win owner" win_owner_is $SHARE tmp.$$/subdir "$WIN_OWNER_AFTER_CREATE" +testit "$TEST_LABEL - verify subdir unix owner" unix_owner_id_is $SHARE tmp.$$/subdir $UNIX_OWNER_AFTER_CREATE +testit "$TEST_LABEL - create file under root" create_file $SHARE tmp.$$/afile +testit "$TEST_LABEL - verify file win owner" win_owner_is $SHARE tmp.$$/afile "$WIN_OWNER_AFTER_CREATE" +testit "$TEST_LABEL - verify file unix owner" unix_owner_id_is $SHARE tmp.$$/afile $UNIX_OWNER_AFTER_CREATE +testit "$TEST_LABEL - change dir owner" set_win_owner $SHARE tmp.$$/subdir "$SERVER\smbget_user" +testit "$TEST_LABEL - verify subdir win owner after change" win_owner_is $SHARE tmp.$$/subdir "$WIN_OWNER_AFTER_CHOWN" +testit "$TEST_LABEL - verify subdir unix owner after change" unix_owner_id_is $SHARE tmp.$$/subdir $UNIX_OWNER_AFTER_CHOWN +testit "$TEST_LABEL - change file owner" set_win_owner $SHARE tmp.$$/afile "$SERVER\smbget_user" +testit "$TEST_LABEL - verify file win owner after change" win_owner_is $SHARE tmp.$$/afile "$WIN_OWNER_AFTER_CHOWN" +testit "$TEST_LABEL - verify file unix owner after change" unix_owner_id_is $SHARE tmp.$$/afile $UNIX_OWNER_AFTER_CHOWN +testit "$TEST_LABEL - cleanup subdir" cleanup_dir $SHARE tmp.$$/subdir +testit "$TEST_LABEL - cleanup file" cleanup_file $SHARE tmp.$$/afile +testit "$TEST_LABEL - cleanup root" cleanup_dir $SHARE tmp.$$ + +testit "revoke SeRestorePrivilege" $NET rpc rights revoke $USERNAME SeRestorePrivilege -U $USERNAME%$PASSWORD -I $SERVER || exit 1 diff --git a/source3/script/tests/test_large_acl.sh b/source3/script/tests/test_large_acl.sh new file mode 100755 index 0000000..4e98c2e --- /dev/null +++ b/source3/script/tests/test_large_acl.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +# +# Blackbox test for fetching a large ACL +# + +if [ $# -lt 5 ]; then + cat </dev/null 2>&1 + rm -rf large_acl >/dev/null +} + +cleanup() +{ + $SMBCLIENT //$SERVER/acl_xattr_ign_sysacl_windows -U $USERNAME%$PASSWORD -c 'rm large_acl' >/dev/null 2>&1 +} + +build_files + +test_large_acl() +{ + #An ACL with 200 entries, ~7K + new_acl=$(seq 1001 1200 | sed -r -e '1 i\D:(A;;FA;;;WD)' -e 's/(.*)/(A;;FA;;;S-1-5-21-11111111-22222222-33333333-\1)/' | tr -d '\n') + $SMBCACLS //$SERVER/acl_xattr_ign_sysacl_windows -U $USERNAME%$PASSWORD --sddl -S $new_acl large_acl + actual_acl=$($SMBCACLS //$SERVER/acl_xattr_ign_sysacl_windows -U $USERNAME%$PASSWORD --sddl --numeric large_acl 2>/dev/null | sed -rn 's/.*(D:.*)/\1/p' | tr -d '\n') + if [ ! "$new_acl" = "$actual_acl" ]; then + echo -e "expected:\n$new_acl\nactual:\n$actual_acl\n" + return 1 + fi +} + +failed=0 + +testit "able to retrieve a large ACL if VFS supports it" test_large_acl || failed=$(expr $failed + 1) + +cleanup + +exit $failed diff --git a/source3/script/tests/test_libwbclient_threads.sh b/source3/script/tests/test_libwbclient_threads.sh new file mode 100755 index 0000000..4f7ac12 --- /dev/null +++ b/source3/script/tests/test_libwbclient_threads.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +if [ $# -lt 2 ]; then + cat < + +if [ $# -lt 3 ]; then + cat <>$LOG + echo "RC: $RC" >>$LOG + return $RC + # echo -n . +} + +test_conf_addshare() +{ + echo '\nTesting conf addshare' >>$LOG + echo ------------------------- >>$LOG + echo '\nDropping existing configuration' >>$LOG + + $NETCMD conf drop + log_print $NETCMD conf drop + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + #create a lot of shares + for i in $(seq 1 100); do + if [ $(($i % 2)) -eq 0 ]; then + $NETCMD conf addshare share$i /tmp "writeable=y" "guest_ok=n" \ + "test comment" >>$DIR/addshare_exp \ + 2>>$DIR/addshare_exp + log_print $NETCMD conf addshare share$i /tmp "writeable=y" "guest_ok=n" \ + "test comment" + else + $NETCMD conf addshare share$i /tmp "writeable=n" "guest_ok=y" \ + "test comment" >>$DIR/addshare_exp \ + 2>>$DIR/addshare_exp + log_print $NETCMD conf addshare share$i /tmp "writeable=n" "guest_ok=y" \ + "test comment" + fi + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + done + + $NETCMD conf listshares >$DIR/listshares_out + log_print $NETCMD conf listshares + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + for i in $(seq 1 100); do + grep "share$i" $DIR/listshares_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: share not found" | tee -a $LOG + return 1 + fi + done + + #check the integrity of the shares + #if it fails, it can also point to an error in showshare + for i in $(seq 1 100); do + $NETCMD conf showshare share$i >$DIR/showshare_out + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + grep "path" $DIR/showshare_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: share not found" | tee -a $LOG + return 1 + fi + + if [ $(($i % 2)) -eq 0 ]; then + grep "read only *= *no" $DIR/showshare_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: share not set correctly" | tee -a $LOG + return 1 + fi + else + grep "read only *= *yes" $DIR/showshare_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: share not set correctly" | tee -a $LOG + return 1 + fi + fi + + if [ $(($i % 2)) -eq 0 ]; then + grep "guest ok *= *no" $DIR/showshare_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: share not set correctly" | tee -a $LOG + return 1 + fi + else + grep "guest ok *= *yes" $DIR/showshare_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: share not set correctly" | tee -a $LOG + return 1 + fi + fi + + grep "comment *= *test comment" $DIR/showshare_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: share not set correctly" | tee -a $LOG + return 1 + fi + done + + echo '\nTaking a conf snapshot for later use' >>$LOG + $NETCMD conf list >$DIR/conf_import_in + log_print $NETCMD conf list + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } +} + +test_conf_addshare_existing() +{ + #try adding an already existing share + echo '\nAdding an already existing share' >>$LOG + $NETCMD conf addshare share1 /tmp "writeable=n" "guest_ok=y" \ + "test comment" >>$DIR/addshare_exp \ + 2>>$DIR/addshare_exp + log_print $NETCMD conf addshare share1 /tmp "writeable=n" "guest_ok=y" \ + "test comment" + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + test -z $(cat $DIR/addshare_exp) && { + echo "ERROR: addshare output does not match" >>$LOG + return 1 + } + + return 0 +} + +test_conf_addshare_usage() +{ + #check to see if command prints usage + echo '\nChecking usage' >>$LOG + $NETCMD conf addshare >$DIR/addshare_usage_exp + log_print $NETCMD conf addshare + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 255' | tee -a $LOG + return 1 + } + + grep "$RPC *conf addshare" $DIR/addshare_usage_exp >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: no/wrong usage message printed" | tee -a $LOG + return 1 + fi +} + +test_conf_delshare() +{ + echo '\nTesting conf delshare' >>$LOG + echo ------------------------- >>$LOG + echo -n '\n' >>$LOG + + $NETCMD conf delshare share1 + log_print $NETCMD conf delshare share1 + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf listshares >$DIR/listshares_out + log_print $NETCMD conf listshares + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + grep "share1$" $DIR/listshares_out >/dev/null 2>>$LOG + if [ "$?" = "0" ]; then + echo "ERROR: delshare did not delete 'share1'" | tee -a $LOG + return 1 + fi +} + +test_conf_delshare_empty() +{ + echo '\nAttempting to delete non_existing share' + $NETCMD conf delshare share1 + log_print $NETCMD conf delshare share1 + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 255' | tee -a $LOG + return 1 + } + +} + +test_conf_delshare_usage() +{ + echo '\nChecking usage' >>$LOG + $NETCMD conf delshare >$DIR/delshare_usage_exp + log_print $NETCMD conf delshare + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 255' | tee -a $LOG + return 1 + } + + grep "$RPC *conf delshare" $DIR/delshare_usage_exp >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: no/wrong usage message printed" | tee -a $LOG + return 1 + fi +} + +test_conf_showshare_case() +{ + echo '\nChecking case in net conf shareshare' >>$LOG + + echo '\nDropping existing configuration' >>$LOG + $NETCMD conf drop + log_print $NETCMD conf drop + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + for share in UPPERCASE lowercase; do + + log_print $NETCMD conf addshare $share /tmp + $NETCMD conf addshare $share /tmp \ + >>$DIR/case_addshare_exp \ + 2>>$DIR/case_addshare_exp + + # Lookup share in different case, check that output has + # share name in correct case. + switch_case=$(echo $share | tr 'A-Za-z' 'a-zA-Z') + log_print $NETCMD conf showshare $switch_case + $NETCMD conf showshare $switch_case >$DIR/showshare_out + test "x$?" = "x0" || { + echo 'ERROR: net conf showshare failed.' | tee -a $LOG + return 1 + } + + grep "\[$share\]" $DIR/showshare_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: share not found" | tee -a $LOG + return 1 + fi + done + +} + +test_conf_drop() +{ + + echo '\nTesting conf drop' >>$LOG + echo ------------------------- >>$LOG + echo '\nDropping existing configuration' >>$LOG + + $NETCMD conf drop + log_print $NETCMD conf drop + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + #check to see if listing the configuration yields a blank file + $NETCMD conf list 1>>$DIR/list_out + log_print $NETCMD conf list + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + test -z "$(cat $DIR/list_out)" || { + echo "ERROR: Expected list output did not match" | tee -a $LOG + return 1 + } +} + +test_conf_drop_empty() +{ + #Drop an empty config, see if conf drop fails + echo '\nAttempting to drop an empty configuration' >>$LOG + + $NETCMD conf drop + log_print $NETCMD conf drop + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + #check to see if listing the configuration yields a blank file + $NETCMD conf list 1>>$DIR/list_out + log_print $NETCMD conf list + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + test -z "$(cat $DIR/list_out)" || { + echo ERROR:Expected list output did not match >>$LOG + return 1 + } +} + +test_conf_drop_usage() +{ + #check to see if command prints usage + echo '\nChecking usage' >>$LOG + $NETCMD conf drop extra_arg >$DIR/drop_usage_exp + log_print $NETCMD conf drop extra_arg + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + grep "$RPC *conf drop" $DIR/drop_usage_exp >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: no/wrong usage message printed" | tee -a $LOG + return 1 + fi +} + +test_conf_setparm() +{ + echo '\nTesting conf setparm' >>$LOG + echo ------------------------- >>$LOG + + echo '\nDropping existing configuration' >>$LOG + $NETCMD conf drop + log_print $NETCMD conf drop + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf setparm share1 "read only" yes + log_print $NETCMD conf setparm share1 "read only" yes + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf setparm share1 "path" /tmp/test_path + log_print $NETCMD conf setparm share1 "path" /tmp/test_path + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf showshare share1 >$DIR/setparm_showshare_out + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + grep "read only *= *yes" $DIR/setparm_showshare_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: setparm did not set correctly" | tee -a $LOG + return 1 + fi + + grep "path *= */tmp/test_path" $DIR/setparm_showshare_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: setparm did not set correctly" | tee -a $LOG + return 1 + fi +} + +test_conf_setparm_existing() +{ + + echo '\nSetting already existing param with the same value' + $NETCMD conf setparm share1 "read only" yes + log_print $NETCMD conf setparm share1 "read only" yes + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf setparm share1 "read only" yes + log_print $NETCMD conf setparm share1 "read only" yes + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf showshare share1 >$DIR/setparm_existing_showshare_out + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + grep "read only *= *yes" $DIR/setparm_existing_showshare_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: setparm did not set correctly" | tee -a $LOG + return 1 + fi + + $NETCMD conf setparm share1 "read only" no + log_print $NETCMD conf setparm share1 "read only" no + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf showshare share1 >$DIR/setparm_existing_showshare_out + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + grep "read only *= *no" $DIR/setparm_existing_showshare_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: setparm did not set correctly" | tee -a $LOG + return 1 + fi +} + +test_conf_setparm_forbidden() +{ + FORBIDDEN_PARAMS="state directory +lock directory +lock dir +config backend +include" + + echo '\nTrying to set forbidden parameters' >>$LOG + + echo '\nDropping existing configuration' >>$LOG + $NETCMD conf drop + log_print $NETCMD conf drop + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + OLD_IFS="$IFS" + IFS=' +' + for PARAM in $FORBIDDEN_PARAMS; do + IFS="$OLD_IFS" + echo "Trying to set parameter '$PARAM'" | tee -a $LOG + $NETCMD conf setparm global "$PARAM" "value" >$DIR/setparm_forbidden_out 2>&1 + log_print $NETCMD conf setparm global \""$PARAM"\" "value" + test "x$?" = "x0" && { + echo "ERROR: setting forbidden parameter '$PARAM' succeeded" | tee -a $LOG + return 1 + } + + echo "output of net command: " | tee -a $LOG + cat $DIR/setparm_forbidden_out | tee -a $LOG + + SEARCH="Parameter '$PARAM' not allowed in registry." + grep "$SEARCH" $DIR/setparm_forbidden_out >/dev/null 2>>$LOG + test "x$?" = "x0" || { + echo "ERROR: expected '$SEARCH'" | tee -a $LOG + return 1 + } + done + + IFS="$OLD_IFS" + return 0 +} + +test_conf_setparm_usage() +{ + echo '\nChecking usage' >>$LOG + $NETCMD conf setparm >$DIR/setparm_usage_exp + log_print $NETCMD conf setparm + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + grep "$RPC *conf setparm" $DIR/setparm_usage_exp >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: setparm no/wrong usage message printed" | tee -a $LOG + return 1 + fi +} + +test_conf_delparm_delete_existing() +{ + echo '\nTesting conf delparm' >>$LOG + echo ------------------------- >>$LOG + echo -n '\n' >>$LOG + + $NETCMD conf drop + log_print $NETCMD conf drop + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf addshare share1 /tmp "writeable=y" "guest_ok=n" \ + "test comment" + log_print $NETCMD conf addshare share$i /tmp "writeable=y" "guest_ok=n" \ + "test comment" + + $NETCMD conf delparm share1 "path" + log_print $NETCMD conf delparm share1 "path" + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf showshare share1 >$DIR/delparm_showshare_out + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + #test to see what delparm did delete and how + grep "read only *= *no" $DIR/delparm_showshare_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: delparm did not delete correctly" | tee -a $LOG + return 1 + fi + + grep "path *= */tmp" $DIR/delparm_showshare_out >/dev/null 2>>$LOG + if [ "$?" = "0" ]; then + echo "ERROR: delparm did not delete correctly" | tee -a $LOG + return 1 + fi +} + +test_conf_delparm_delete_non_existing() +{ + echo '\nDelete non existing share' >>$LOG + + $NETCMD conf drop + log_print $NETCMD conf drop + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf delparm share1 "path" + log_print $NETCMD conf delparm share1 "path" + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 255' | tee -a $LOG + return 1 + } +} + +test_conf_delparm_usage() +{ + + echo '\nChecking usage' >>$LOG + $NETCMD conf delparm >$DIR/delparm_usage_exp + log_print $NETCMD conf delparm + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 255' | tee -a $LOG + return 1 + } + + grep "$RPC *conf delparm" $DIR/delparm_usage_exp >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: delparm no/wrong usage message printed" | tee -a $LOG + return 1 + fi + +} + +test_conf_getparm() +{ + + echo '\nTesting conf getparm' >>$LOG + echo ------------------------- >>$LOG + echo -n '\n' >>$LOG + + $NETCMD conf drop + log_print $NETCMD conf drop + test "x$?" = "x0" || { + return 1 + } + + $NETCMD conf addshare share1 /tmp/path_test "writeable=n" "guest_ok=n" \ + "test comment" + log_print $NETCMD conf addshare share$i /tmp/path_test "writeable=n" "guest_ok=n" \ + "test comment" + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf getparm share1 "read only" >$DIR/getparm_out + log_print $NETCMD conf getparm share1 "read only" + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf getparm share1 "read only" >$DIR/getparm_out + log_print $NETCMD conf getparm share1 "read only" + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + echo yes >$DIR/getparm_exp + diff -q $DIR/getparm_out $DIR/getparm_exp >>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: getparm did not print correctly" | tee -a $LOG + return 1 + fi + + $NETCMD conf getparm share1 "path" >$DIR/getparm_out + log_print $NETCMD conf getparm share1 "path" + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + echo /tmp/path_test >$DIR/getparm_exp + diff -q $DIR/getparm_out $DIR/getparm_exp >>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: getparm did not print correctly" | tee -a $LOG + return 1 + fi +} + +test_conf_getparm_usage() +{ + echo '\nChecking usage' >>$LOG + $NETCMD conf getparm >$DIR/getparm_usage_exp + log_print $NETCMD conf getparm + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 255' | tee -a $LOG + return 1 + } + + grep "$RPC *conf getparm" $DIR/getparm_usage_exp >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: getparm no/wrong usage message printed" | tee -a $LOG + return 1 + fi + +} + +test_conf_getparm_non_existing() +{ + echo '\nTesting getparm non existing' >>$LOG + $NETCMD conf getparm fictional_share fictional_param + log_print $NETCMD conf getparm fictional_share fictional_param + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 255' | tee -a $LOG + return 1 + } + + $NETCMD conf getparm share1 fictional_param + log_print $NETCMD conf getparm share1 fictional_param + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 255' | tee -a $LOG + return 1 + } +} + +test_conf_setincludes() +{ + echo '\nTesting conf setincludes' >>$LOG + echo ------------------------- >>$LOG + echo '\nDropping existing configuration' >>$LOG + + $NETCMD conf drop + log_print $NETCMD conf drop + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf addshare tmp_share /tmp + log_print $NETCMD conf addshare tmp_share /tmp + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf setincludes tmp_share /tmp/include1 /tmp/include2 /tmp/include3 + log_print $NETCMD conf setincludes tmp_share /tmp/include1 /tmp/include2 /tmp/include3 + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf list >$DIR/setincludes_list_out + log_print $NETCMD conf list + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + grep "include *= */tmp/include1$" $DIR/setincludes_list_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: setincludes did not set correctly" | tee -a $LOG + return 1 + fi + + grep "include *= */tmp/include2$" $DIR/setincludes_list_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: setincludes did not set correctly" | tee -a $LOG + return 1 + fi + + grep "include *= */tmp/include3$" $DIR/setincludes_list_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: setincludes did not set correctly" | tee -a $LOG + return 1 + fi + +} + +test_conf_setincludes_usage() +{ + echo '\nChecking usage' >>$LOG + $NETCMD conf setincludes >$DIR/setincludes_usage_exp + log_print $NETCMD conf setincludes + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 255' | tee -a $LOG + return 1 + } + + grep "$RPC *conf setincludes" $DIR/setincludes_usage_exp >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: no/wrong usage message printed" | tee -a $LOG + return 1 + fi +} + +test_conf_getincludes() +{ + $NETCMD conf getincludes tmp_share >$DIR/getincludes_out + log_print $NETCMD conf getincludes tmp_share + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + grep "include *= */tmp/include1$" $DIR/getincludes_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: getincludes did not print correctly" | tee -a $LOG + return 1 + fi + + grep "include *= */tmp/include2$" $DIR/getincludes_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: getincludes did not print correctly" | tee -a $LOG + return 1 + fi + grep "include *= */tmp/include3$" $DIR/getincludes_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: getincludes did not print correctly" | tee -a $LOG + return 1 + fi +} + +test_conf_getincludes_usage() +{ + $NETCMD conf getincludes >$DIR/getincludes_usage_exp + log_print $NETCMD conf getincludes + + grep "$RPC *conf getincludes" $DIR/getincludes_usage_exp >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: no/wrong usage message printed" | tee -a $LOG + return 1 + fi +} + +test_conf_delincludes() +{ + echo '\nTesting conf delincludes' >>$LOG + echo ------------------------- >>$LOG + + $NETCMD conf delincludes tmp_share + log_print $NETCMD conf delincludes tmp_share + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf list >$DIR/delincludes_list_out + log_print $NETCMD conf list + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + grep "include" $DIR/delincludes_list_out >/dev/null 2>>$LOG + if [ "$?" = "0" ]; then + echo "ERROR: delincludes did not delete correctly" | tee -a $LOG + return 1 + fi +} + +test_conf_delincludes_empty() +{ + $NETCMD conf delincludes tmp_share + log_print $NETCMD conf delincludes tmp_share + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf delincludes fictional_share + log_print $NETCMD conf delincludes fictional_share + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 255' | tee -a $LOG + return 1 + } + return 0 +} + +test_conf_delincludes_usage() +{ + echo '\nChecking usage' >>$LOG + $NETCMD conf delincludes >$DIR/delincludes_usage_exp + log_print $NETCMD conf delincludes + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 255' | tee -a $LOG + return 1 + } + + grep "$RPC *conf delincludes" $DIR/delincludes_usage_exp >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: no/wrong usage message printed" | tee -a $LOG + return 1 + fi +} + +test_conf_import() +{ + echo '\nTesting conf import' >>$LOG + echo ------------------------- >>$LOG + echo '\nDropping existing configuration' >>$LOG + + $NETCMD conf drop + log_print $NETCMD conf drop + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf import $DIR/conf_import_in + log_print $NETCMD conf drop + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf list >$DIR/conf_import_out + log_print $NETCMD conf list + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + diff -q $DIR/conf_import_in $DIR/conf_import_out >>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: import failed" | tee -a $LOG + return 1 + fi +} + +test_conf_import_usage() +{ + echo '\nChecking usage' >>$LOG + $NETCMD conf import >$DIR/import_usage_exp + log_print $NETCMD conf import + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 255' | tee -a $LOG + return 1 + } + + grep "$RPC *conf import" $DIR/import_usage_exp >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: conf import no/wrong usage message printed" | tee -a $LOG + return 1 + fi +} + +CONF_FILES=$SERVERCONFFILE + +testit "conf_drop" \ + test_conf_drop || + failed=$(expr $failed + 1) + +testit "conf_drop_empty" \ + test_conf_drop_empty || + failed=$(expr $failed + 1) + +testit "conf_drop_usage" \ + test_conf_drop_usage || + failed=$(expr $failed + 1) + +testit "conf_addshare" \ + test_conf_addshare || + failed=$(expr $failed + 1) + +testit "conf_addshare_existing" \ + test_conf_addshare_existing || + failed=$(expr $failed + 1) + +testit "conf_addshare_usage" \ + test_conf_addshare_usage || + failed=$(expr $failed + 1) + +testit "conf_delshare" \ + test_conf_delshare || + failed=$(expr $failed + 1) + +testit "conf_delshare_empty" \ + test_conf_delshare_empty || + failed=$(expr $failed + 1) + +testit "conf_delshare_usage" \ + test_conf_delshare_usage || + failed=$(expr $failed + 1) + +testit "test_conf_showshare_case" \ + test_conf_showshare_case || + failed=$(expr $failed + 1) + +testit "conf_setparm" \ + test_conf_setparm || + failed=$(expr $failed + 1) + +testit "conf_setparm_existing" \ + test_conf_setparm_existing || + failed=$(expr $failed + 1) + +testit "conf_setparm_forbidden" \ + test_conf_setparm_forbidden || + failed=$(expr $failed + 1) + +testit "conf_setparm_usage" \ + test_conf_setparm_usage || + failed=$(expr $failed + 1) + +testit "conf_delparm_delete_existing" \ + test_conf_delparm_delete_existing || + failed=$(expr $failed + 1) + +testit "conf_delparm_delete_non_existing" \ + test_conf_delparm_delete_non_existing || + failed=$(expr $failed + 1) + +testit "conf_delparm_delete_usage" \ + test_conf_delparm_usage || + failed=$(expr $failed + 1) + +testit "conf_getparm" \ + test_conf_getparm || + failed=$(expr $failed + 1) + +testit "conf_getparm_usage" \ + test_conf_getparm_usage || + failed=$(expr $failed + 1) + +testit "conf_setincludes" \ + test_conf_setincludes || + failed=$(expr $failed + 1) + +testit "conf_setincludes_usage" \ + test_conf_setincludes_usage || + failed=$(expr $failed + 1) + +testit "conf_getincludes" \ + test_conf_getincludes || + failed=$(expr $failed + 1) + +testit "conf_getincludes_usage" \ + test_conf_getincludes_usage || + failed=$(expr $failed + 1) + +testit "conf_delincludes" \ + test_conf_delincludes || + failed=$(expr $failed + 1) + +testit "conf_delincludes_empty" \ + test_conf_delincludes_usage || + failed=$(expr $failed + 1) + +testit "conf_delincludes_usage" \ + test_conf_delincludes_empty || + failed=$(expr $failed + 1) + +testit "conf_import" \ + test_conf_import || + failed=$(expr $failed + 1) + +testit "conf_import_usage" \ + test_conf_import_usage || + failed=$(expr $failed + 1) + +if [ $failed -eq 0 ]; then + rm -r $DIR +fi + +testok $0 $failed diff --git a/source3/script/tests/test_net_cred_change.sh b/source3/script/tests/test_net_cred_change.sh new file mode 100755 index 0000000..7b01673 --- /dev/null +++ b/source3/script/tests/test_net_cred_change.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +if [ $# -lt 1 ]; then + cat < +# Copyright (C) 2010 Gregor Beck +# +# rpc tests are chose by specifying "rpc" as commandline parameter. + +if [ $# -lt 3 ]; then + cat < + +if [ $# -lt 5 ]; then + echo "Usage: test_net_registry_check.sh SCRIPTDIR SERVERCONFFILE NET CONFIGURATION DBWRAP_TOOL" + exit 1 +fi + +SCRIPTDIR="$1" +SERVERCONFFILE="$2" +NET="$3" +CONFIGURATION="$4" +DBWRAP_TOOL="$5 --persistent" + +NET="$VALGRIND ${NET:-$BINDIR/net} $CONFIGURATION" + +NETREG="${NET} registry" +REGORIG="$(grep 'state directory = ' $SERVERCONFFILE | sed 's/[^=]*=//')/registry.tdb" +REG=$REGORIG.wip + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +# run registry check and filter allowed errors +regcheck() +{ + ALLOWEDERR="Check database:|INFO: version =" + ERRSTR=$(${NETREG} check $REG "$@" 2>&1 | egrep -v "$ALLOWEDERR") +} + +# try to repair registry +regrepair() +{ + regcheck -a +} + +# check if $ERRSTR contains expected error +checkerr() +{ + EXPERR=$1 + + ERRCNT=$(echo "$ERRSTR" | grep "$EXPERR" | wc -l) + return $ERRCNT +} + +regchecknrepair() +{ + EXPERR="$1" + EXPERRCNT="$2" + + regcheck + checkerr "$EXPERR" + test "$?" -eq "$ERRCNT" || { + echo "Expected $EXPERRCNT of error $EXPERR. Received $ERRCNT" + return 1 + } + + regrepair + regcheck + test "x$ERRSTR" = "x" || { + echo "Error: Can't repair database" + return 1 + } +} + +test_simple() +( + ERRSTR="" + cp $REGORIG $REG + + regcheck + test "x$ERRSTR" = "x" || { + echo $ERRSTR + return 1 + } +) + +test_damage() +{ + diff $REGORIG $REG +} + +test_duplicate() +( + ERRSTR="" + $DBWRAP_TOOL $REG store 'HKLM/SOFTWARE' hex '02000000534F4654574152450053595354454D00' + + regchecknrepair "Duplicate subkeylist" 1 +) + +test_slashes() +( + ERRSTR="" + $DBWRAP_TOOL $REG store 'HKLM/SOFTWARE' hex '02000000534F4654574152450053595354454D00' + + regchecknrepair "Unnormal key:" 1 +) + +test_uppercase() +( + ERRSTR="" + $DBWRAP_TOOL $REG store 'HKLM\Software' hex '02000000534F4654574152450053595354454D00' + + regchecknrepair "Unnormal key:" 1 +) + +test_strangeletters() +( + ERRSTR="" + $DBWRAP_TOOL $REG store 'HKLM\SOFTWARE' hex '02000000534F4654574FABFABFABFAB354454D00' + + regchecknrepair "Conversion error: Incomplete multibyte sequence" 1 +) + +testit "simple" \ + test_simple || + failed=$(expr $failed + 1) + +testit "damages_registry" \ + test_damage || + failed=$(expr $failed + 1) + +testit "duplicate" \ + test_duplicate || + failed=$(expr $failed + 1) + +testit "slashes" \ + test_slashes || + failed=$(expr $failed + 1) + +testit "uppercase" \ + test_uppercase || + failed=$(expr $failed + 1) + +#Can't repair this atm +#testit "strangeletters" \ +# test_strangeletters || \ +# failed=`expr $failed + 1` + +testok $0 $failed diff --git a/source3/script/tests/test_net_registry_import.sh b/source3/script/tests/test_net_registry_import.sh new file mode 100755 index 0000000..cca566f --- /dev/null +++ b/source3/script/tests/test_net_registry_import.sh @@ -0,0 +1,192 @@ +#!/bin/sh + +if [ $# -lt 4 ]; then + cat <&1) + ret=$? + + if [ $ret != 0 ]; then + echo "$out" + echo "command failed with output $ret" + false + return + fi + + echo "$out" | grep 'Found Byte Order Mark for : UTF-16LE' + ret=$? + + if [ $ret -ne 0 ]; then + echo "$out" + echo "$samba_net rpc registry import $LOCAL_PATH/case3b45ccc3b.dat failed - should get 'Found Byte Order Mark for : UTF-16LE'" + false + return + fi + + # + # Expect: + # reg_parse_fd: smb_iconv error in file at line 0: <77><41> + # + cmd='$VALGRIND $samba_net rpc registry import $LOCAL_PATH/casecbe8c2427.dat -S$SERVER -U$USERNAME%$PASSWORD $ADDARGS' + + eval echo "$cmd" + out=$(eval $cmd 2>&1) + ret=$? + + if [ $? != 0 ]; then + echo "$out" + echo "command failed with output $ret" + false + return + fi + + echo "$out" | grep 'reg_parse_fd: smb_iconv error in file at line 0: <77><41>' + ret=$? + + if [ $ret -ne 0 ]; then + echo "$out" + echo "$samba_net rpc registry import $LOCAL_PATH/case3b45ccc3b.dat failed - should get 'reg_parse_fd: smb_iconv error in file at line 0: <77><41>'" + false + return + fi + + # + # For test3.dat, the parse of the first part of the file is successful, + # but fails on upload as we're writing to an unwriteable registry. + # Expect: + # setval ProductType failed: WERR_REGISTRY_IO_FAILED + # reg_parse_fd: reg_parse_line line 21 fail -2 + # This counts as a success test as the file is parsed, but + # the upload failed. + # + cmd='$VALGRIND $samba_net rpc registry import $LOCAL_PATH/regtest3.dat -S$SERVER -U$USERNAME%$PASSWORD $ADDARGS' + + eval echo "$cmd" + out=$(eval $cmd 2>&1) + ret=$? + + if [ $? != 0 ]; then + echo "$out" + echo "command failed with output $ret" + false + return + fi + + echo "$out" | grep 'setval ProductType failed: WERR_REGISTRY_IO_FAILED' + ret=$? + + if [ $ret -ne 0 ]; then + echo "$out" + echo "$samba_net rpc registry import $LOCAL_PATH/regtest3.dat failed - should get 'setval ProductType failed: WERR_REGISTRY_IO_FAILED'" + false + return + fi + + echo "$out" | grep 'reg_parse_fd: reg_parse_line 20 fail -2' + ret=$? + + if [ $ret -ne 0 ]; then + echo "$out" + echo "$samba_net rpc registry import $LOCAL_PATH/regtest3.dat failed - should get 'reg_parse_fd: reg_parse_line 20 fail -2'" + false + return + fi + + true + return +} + +########################################################### +# Check net rpc registry import doesn't crash +########################################################### + +rm -f $LOCAL_PATH/case3b45ccc3b.dat +rm -f $LOCAL_PATH/casecbe8c2427.dat +rm -f $LOCAL_PATH/regtest3.dat + +# Create test cases + +base64 -d <<'EOF' | gunzip -c >$LOCAL_PATH/case3b45ccc3b.dat +H4sIAODLjlwCA/v/L5whkyGPIYUhn6GcoZhBgSGIIZUhHShWzFDCUMRQCRRxBcpmAnn5QL4CQxhQ +vggomwnk5wH5pgx6DAZAyMvABcbRDB4M3kA9kQzxDD4M/gzODI5AOp7BF0g7A+U8GfyAsjEMwUAV +wQwhQLYvkOfMUPqRUvDw4yAHnz6OgsELgGlYh8EYCHXA6RnENmLIgbJNGZLh4jEMvEWRee8eXl8u +//f8N9vK5cVVXP9v2rB+/qYw+3xko5Su8jSiLZ0zwJ4GAO4s/cYABAAA +EOF + +base64 -d <<'EOF' | gunzip -c >$LOCAL_PATH/casecbe8c2427.dat +H4sIALjPjlwCA2NwZfBliGFwZihlKALCVIY8hhIgLx9MFwHpHIZgoGgJUA2ILmIoY8hkSAayioEi +OQyJQHW5YLIcqLaIIRsoXgLklwBVgcyIYSgA8oqAOBdsCsiEYoZYBl4GLgYlsG2JDElAc1KB6kCm +ZYLtTWWoAJIgncVACDE5BajeFkjCeFYMBijQEIuZxUCcDPZZJkNJ3f7yK45/V3S8epR2I14uf+4W +ee+dz0RXshv4SHxzff2XJYbx0pWaEs+ul5XKF9hlFIu4RG73Lf3rOXHW3NxpuvVnE9Xk7zxv2p3I +tlLtWjY/i1HIGhdpLy/Gub9nH5jLd/rqdYfv2uumzgq7PIldPY3Labru/65Q/nLJh1oBk/0tT2v2 +eUdbzFg0NfPmamFH421aJxMPhnr7X+y0iRdSX+ex+IJ0Yaf0ahV5440Wj7cbK/jkbSjcNdvpR+WN +/5Knnn8PjvvD9O/Ws4pXUqG3lbdFrf1846zzcTOFW8yhB3QNZRP6TjOsu1rDvIaHZVfMyYd1Mhev +ik/a5m36Y85+y63pPmtXb8nOU5Zd0qK0yVJK8a27WqKHSOKaS7wpwULu1TsM94bVGD3xviR0u1Il +rFHoxeUrm2+6Ke4x2SGitD912ZGfLcmG0xiyIn+bmx0+s+dbXuT8xfl+CgL168yNzYxCgsviz/46 +b7746Wnh8zXZHDof6/yDyxdf31JkzN5YVP4kf/vkvrS1ioauYemc3RIt7znZQvpOy7XO8VU5+KeP +VXKPXrzr+nMv/v5wkpA7v2TukgqHZ4e6i+Zsjfny6vHdg7+mLFjg/th4m55ppH75HYcLjEa/U4/w +SeXMTuVXablo/fmJnlPA6T12usz8nBGVKbVzTNqrTJ6d/+Y0y2bGc5MlzgnymUVq/9/PyZ2QxZvR +4WyR810zd32X5ncJRd/y7VNCd746G/jTTFLTJfHx86dVtlkL02zeCJeYsmkdrXVhtpl7Y5OOyJcD +DJXA9JPJkA5MT8YMOuA0psNgBExRMLYZgwkSOxnM1kdiG6CQkNTpD0zXGeBc4AJMx7nQFF8MTttA +8f8VDBoM5gya4NRNtgN0zczNjM1MDCwMLcwMTCwtLYxNjLE4wK5pwpebAAJ05DUABAAA +EOF + +base64 -d <<'EOF' >$LOCAL_PATH/regtest3.dat +UkVHRURJVDQKCltIS0VZX0xPQ0FMX01BQ0hJTkVdCgpbSEtFWV9MT0NBTF9NQUNISU5FXFNPRlRX +QVJFXQoKW0hLRVlfTE9DQUxfTUFDSElORVxTT0ZUV0FSRVxNaWNyb3NvZnRdCgpbSEtFWV9MT0NB +TF9NQUNISU5FXFNPRlRXQVJFXE1pY3Jvc29mdFxXaW5kb3dzIE5UXQoKW0hLRVlfTE9DQUxfTUFD +SElORVxTT0ZUV0FSRVxNaWNyb3NvZnRcV2luZG93cyBOVFxDdXJyZW50VmVyc2lvbl0KIkN1cnJl +bnRWZXJzaW9uIj0iNi4xIgoKW0hLRVlfTE9DQUxfTUFDSElORVxTWVNURU1dCgpbSEtFWV9MT0NB +TF9NQUNISU5FXFNZU1RFTVxDdXJyZW50Q29udHJvbFNldF0KCltIS0VZX0xPQ0FMX01BQ0hJTkVc +U1lTVEVNXEN1cnJlbnRDb250cm9sU2V0XENvbnRyb2xdCgpbSEtFWV9MT0NBTF9NQUNISU5FXFNZ +U1RFTVxDdXJyZW50Q29udHJvbFNldFxDb250cm9sXFByb2R1Y3RPcHRpb25zXQoiUHJvZHVjdFR5 +cGUiPSJMYW5tYW5OVCIKCltIS0VZX0xPQ0FMX01BQ0hJTkVcU1lTVEVNXEN1cnJlbnRDb250cm9s +U2V0XENvbnRyb2xcUHJpbnRdCgpbSEtFWV9MT0NBTF9NQUNISU5FXFNZU1RFTVxDdXJyZW50Q29u +dHJvbFNldFxDb250cm9sXFRlcm1pbmFsIFNlcnZlcl0KCltIS0VZX0xPQ0FMX01BQ0hJTkVcU1lT +VEVNXQoKW0hLRVlfTE9DQUxfTUFDSElORVxTWVNURU1cQ3VycmVudENvbnRyb2xTZXRdCgpbSEtF +WV9MT0NBTF9NQUNISU5FXFNZU1RFTVxDdXJyZW50Q29udHJvbFNldFxTZXJ2aWNlc10KCltIS0VZ +X0xPQ0FMX01BQ0hJTkVcU1lTVEVNXEN1cnJlbnRDb250cm9sU2V0XFNlcnZpY2VzXE5ldGxvZ29u +XQoKW0hLRVlfTE9DQUxfTUFDSElORVxTWVNURU1cQ3VycmVudENvbnRyb2xTZXRcU2VydmljZXNc +TmV0bG9nb25cUGFyYW1ldGVyc10KIlJlZnVzZVBhc3N3b3JkQ2hhbmdlIj1kd29yZDowMDAwMDAw +MAoKW0hLRVlfTE9DQUxfTUFDSElORVxTWVNURU1cQ3VycmVudENvbnRyb2xTZXRcU2VydmljZXNc +QWxlcnRlcl0KCltIS0VZX0xPQ0FMX01BQ0hJTkVcU1lTVEVNXEN1cnJlbnRDb250cm9sU2V0XA== +EOF + +testit "Test net rpc registry import" \ + test_net_registry_import || + failed=$(expr $failed + 1) + +# Clean up test cases. +rm -f $LOCAL_PATH/case3b45ccc3b.dat +rm -f $LOCAL_PATH/casecbe8c2427.dat +rm -f $LOCAL_PATH/regtest3.dat + +testok $0 $failed diff --git a/source3/script/tests/test_net_registry_roundtrip.sh b/source3/script/tests/test_net_registry_roundtrip.sh new file mode 100755 index 0000000..e1974c2 --- /dev/null +++ b/source3/script/tests/test_net_registry_roundtrip.sh @@ -0,0 +1,158 @@ +#!/bin/sh +# +# Blackbox test for net conf/registry roundtrips. +# +# Copyright (C) 2010 Gregor Beck +# Copyright (C) 2011 Michael Adam + +if [ $# -lt 3 ]; then + cat <>$LOG + "$@" 2>>$LOG + RC=$? + echo "RC: $RC" >>$LOG + test "x$RC" = "x0" || { + echo "ERROR: $* failed (RC=$RC)" | tee -a $LOG + } + return $RC + # echo -n . +} + +LOGDIR_PREFIX="conf_roundtrip" + +conf_roundtrip() +( + DIR=$(mktemp -d ${PREFIX}/${LOGDIR_PREFIX}_XXXXXX) + LOG=$DIR/log + + echo conf_roundtrip $1 >$LOG + + sed -e "$SED_INVALID_PARAMS" $1 >$DIR/conf_in + + conf_roundtrip_step $NETCMD conf drop + test "x$?" = "x0" || { + return 1 + } + + test -z "$($NETCMD conf list)" 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: conf drop failed" | tee -a $LOG + return 1 + fi + + conf_roundtrip_step $NETCMD conf import $DIR/conf_in + test "x$?" = "x0" || { + return 1 + } + + conf_roundtrip_step $NETCMD conf list >$DIR/conf_exp + test "x$?" = "x0" || { + return 1 + } + + grep "\[global\]" $DIR/conf_exp >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: conf import => conf export failed" | tee -a $LOG + return 1 + fi + + conf_roundtrip_step $NETCMD -d10 registry export $REGPATH $DIR/conf_exp.reg + test "x$?" = "x0" || { + return 1 + } + + conf_roundtrip_step $NETCMD conf drop + test "x$?" = "x0" || { + return 1 + } + + test -z "$($NETCMD conf list)" 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: conf drop failed" | tee -a $LOG + return 1 + fi + + conf_roundtrip_step $NETCMD registry import $DIR/conf_exp.reg + test "x$?" = "x0" || { + return 1 + } + + conf_roundtrip_step $NETCMD conf list >$DIR/conf_out + test "x$?" = "x0" || { + return 1 + } + + diff -q $DIR/conf_out $DIR/conf_exp >>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: registry import => conf export failed" | tee -a $LOG + return 1 + fi + + conf_roundtrip_step $NETCMD registry export $REGPATH $DIR/conf_out.reg + test "x$?" = "x0" || { + return 1 + } + + diff -q $DIR/conf_out.reg $DIR/conf_exp.reg >>$LOG + if [ "$?" = "1" ]; then + echo "Error: registry import => registry export failed" | tee -a $LOG + return 1 + fi + rm -r $DIR +) + +CONF_FILES=$SERVERCONFFILE + +# remove old logs: +for OLDDIR in $(find ${PREFIX} -type d -name "${LOGDIR_PREFIX}_*"); do + echo "removing old directory ${OLDDIR}" + rm -rf ${OLDDIR} +done + +for conf_file in $CONF_FILES; do + testit "conf_roundtrip $conf_file" \ + conf_roundtrip $conf_file || + failed=$(expr $failed + 1) +done + +testok $0 $failed diff --git a/source3/script/tests/test_net_rpc_join.sh b/source3/script/tests/test_net_rpc_join.sh new file mode 100755 index 0000000..319d044 --- /dev/null +++ b/source3/script/tests/test_net_rpc_join.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +if [ $# -lt 4 ]; then + cat <"$credsfile" +testit "net_rpc_join_creds" $VALGRIND $BINDIR/net rpc join -S $SERVER --option=netbiosname=netrpcjointest --option=domainlogons=yes --option=privatedir=$PREFIX/private -A"$credsfile" $ADDARGS || failed=$(expr $failed + 1) +testit "net_rpc_testjoin_creds" $VALGRIND $BINDIR/net rpc testjoin -S $SERVER --option=netbiosname=netrpcjointest --option=domainlogons=yes --option=privatedir=$PREFIX/private $ADDARGS || failed=$(expr $failed + 1) +testit "net_rpc_changetrustpw_creds" $VALGRIND $BINDIR/net rpc changetrustpw -S $SERVER --option=netbiosname=netrpcjointest --option=domainlogons=yes --option=privatedir=$PREFIX/private $ADDARGS || failed=$(expr $failed + 1) +testit "net_rpc_testjoin2_creds" $VALGRIND $BINDIR/net rpc testjoin -S $SERVER --option=netbiosname=netrpcjointest --option=domainlogons=yes --option=privatedir=$PREFIX/private $ADDARGS || failed=$(expr $failed + 1) +rm -f $credsfile + +testok $0 $failed diff --git a/source3/script/tests/test_net_rpc_oldjoin.sh b/source3/script/tests/test_net_rpc_oldjoin.sh new file mode 100755 index 0000000..d650ead --- /dev/null +++ b/source3/script/tests/test_net_rpc_oldjoin.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +if [ $# -lt 3 ]; then + cat < +EOF + exit 1 +fi + +SERVER="$1" +SERVER_IP="$2" +USERNAME="$3" +PASSWORD="$4" +smbclient="$5" +shift 5 +ADDARGS="$@" + +failed=0 + +samba_bindir="$BINDIR" +samba_net="$samba_bindir/net" +samba_smbcontrol="$samba_bindir/smbcontrol" + +samba_share_dir="$LOCAL_PATH" +samba_usershare_dir="$samba_share_dir/usershares" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +test_smbclient() +{ + name="$1" + share="$2" + cmd="$3" + shift 3 + echo "test: $name" + $VALGRIND $smbclient $CONFIGURATION //$SERVER/$share -c "$cmd" "$@" + status=$? + if [ x$status = x0 ]; then + echo "success: $name" + else + echo "failure: $name" + fi + return $status +} + +test_net_usershare() +{ + name="$1" + cmd="$2" + shift + shift + echo "test: $name" + $VALGRIND $samba_net usershare "$cmd" "$@" + status=$? + if [ x$status = x0 ]; then + echo "success: $name" + else + echo "failure: $name" + fi + return $status +} + +########################################################### +# Check if we can add and delete a usershare +########################################################### + +samba_usershare_name="test_usershare_1" +samba_usershare_path="$samba_usershare_dir/$samba_usershare_name" + +testit "create usershare dir for $samba_usershare_name" mkdir --mode=0755 --verbose $samba_usershare_path || failed=$(expr $failed + 1) + +test_net_usershare "net usershare add $samba_usershare_name" "add" "$samba_usershare_name" "$samba_usershare_path" "$samba_usershare_name" + +test_net_usershare "net usershare info $samba_usershare_name" "info" "$samba_usershare_name" + +test_smbclient "smbclient to $samba_usershare_name" "$samba_usershare_name" 'ls' -U$USERNAME%$PASSWORD || failed=$(expr $failed + 1) + +# CLEANUP +test_net_usershare "net usershare delete $samba_usershare_name" "delete" "$samba_usershare_name" +testit "remove usershare dir for $samba_usershare_name" rm -rf $samba_usershare_path || failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/test_netfileenum.sh b/source3/script/tests/test_netfileenum.sh new file mode 100755 index 0000000..d343555 --- /dev/null +++ b/source3/script/tests/test_netfileenum.sh @@ -0,0 +1,84 @@ +#!/usr/bin/env bash +# +# Test rpcclient netfileenum +# +# Copyright (C) 2020 Volker Lendecke + +if [ $# -lt 5 ]; then + echo Usage: $0 \ + SMBCLIENT RPCCLIENT NET SERVER SHARE + exit 1 +fi + +SMBCLIENT="$1" +shift 1 +RPCCLIENT="$1" +shift 1 +NET="$1" +shift 1 +SERVER="$1" +shift 1 +SHARE="$1" +shift 1 + +# Do not let deprecated option warnings muck this up +SAMBA_DEPRECATED_SUPPRESS=1 +export SAMBA_DEPRECATED_SUPPRESS + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +cd $SELFTEST_TMPDIR || exit 1 + +rm -f smbclient-stdin smbclient-stdout smbclient-stderr +mkfifo smbclient-stdin smbclient-stdout smbclient-stderr + +CLI_FORCE_INTERACTIVE=1 +export CLI_FORCE_INTERACTIVE + +${SMBCLIENT} //${SERVER}/${SHARE} ${CONF} -U${USER}%${PASSWORD} \ + smbclient-stdout 2>smbclient-stderr & +CLIENT_PID=$! + +sleep 1 + +exec 100>smbclient-stdin 101&100 + +sleep 1 + +testit "Create builtin\\administrators group" \ + "${NET}" groupmap add \ + sid=S-1-5-32-544 unixgroup="${USER}"-group type=builtin || + failed=$((failed + 1)) +testit "Add ${USER} to builtin\\administrators" \ + "${NET}" groupmap addmem S-1-5-32-544 \ + $("${NET}" lookup name "${USER}" | cut -d' ' -f1) || + failed=$((failed + 1)) + +"${RPCCLIENT}" "${SERVER}" -U"${USER}"%"${PASSWORD}" -c netfileenum | + grep "$FILE"\$ +RC=$? +testit "netfileenum" test $RC = 0 || failed=$((failed + 1)) + +kill ${CLIENT_PID} +rm -f smbclient-stdin smbclient-stdout smbclient-stderr + +testit "Remove ${USER} from builtin\\administrators" \ + "${NET}" groupmap delmem S-1-5-32-544 \ + $("${NET}" lookup name "${USER}" | cut -d' ' -f1) || + failed=$((failed + 1)) +testit "Remove builtin\\administrators group" \ + "${NET}" groupmap delete \ + sid=S-1-5-32-544 || + failed=$((failed + 1)) + +testok $0 $failed diff --git a/source3/script/tests/test_nt4_trust.sh b/source3/script/tests/test_nt4_trust.sh new file mode 100755 index 0000000..b3d6ca6 --- /dev/null +++ b/source3/script/tests/test_nt4_trust.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +. $incdir/common_test_fns.inc + +failed=0 + +wbinfo="$BINDIR/wbinfo" +smbclient="$BINDIR/smbclient" + +test_trust_wbinfo_m() { + i=0 + # Give the server some time to list trusted domains + while [ $i -lt 10 ] ; do + $wbinfo -m | grep SAMBA-TEST && return 0 + sleep 2 + i=$((i + 1)) + done + return 1 +} + +test_trust_smbclient() { + $smbclient //$NT4_TRUST_SERVER_IP/tmp -U "$DOMAIN/$DOMAIN_USER%$DOMAIN_USER_PASSWORD" -c quit || return 1 + return 0 +} + +testit "nt4trust_wbinfo_m" test_trust_wbinfo_m || failed=$(expr $failed + 1) +testit "nt4trust_smbclient" test_trust_smbclient || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_offline.sh b/source3/script/tests/test_offline.sh new file mode 100755 index 0000000..5e06b1f --- /dev/null +++ b/source3/script/tests/test_offline.sh @@ -0,0 +1,33 @@ +#!/bin/sh +# +# Blackbox test for the offline VFS module. +# +if [ $# -lt 7 ]; then + cat <${error_inject_conf} + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +cd $SELFTEST_TMPDIR || exit 1 + +rm -f smbclient-stdin smbclient-stdout smbclient-stderr +mkfifo smbclient-stdin smbclient-stdout smbclient-stderr + +CLI_FORCE_INTERACTIVE=1 +export CLI_FORCE_INTERACTIVE + +${SMBCLIENT} //${SERVER}/${SHARE} ${CONF} -U${USER}%${PASSWORD} \ + smbclient-stdout 2>smbclient-stderr & +CLIENT_PID=$! + +sleep 1 + +exec 100>smbclient-stdin 101${error_inject_conf} +${SMBCONTROL} ${CONF} 0 reload-config + +sleep 1 +>${error_inject_conf} + +echo 'get badnames/blank.txt -' >&100 + +sleep 1 + +>${error_inject_conf} +${SMBCONTROL} ${CONF} 0 reload-config + +head -n 1 <&102 | grep 'getting file' >/dev/null +GREP_RET=$? + +kill ${CLIENT_PID} +rm -f smbclient-stdin smbclient-stdout smbclient-stderr + +testit "Verify that we could get the file" \ + test $GREP_RET -eq 0 || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_preserve_case.sh b/source3/script/tests/test_preserve_case.sh new file mode 100755 index 0000000..c9ca79a --- /dev/null +++ b/source3/script/tests/test_preserve_case.sh @@ -0,0 +1,86 @@ +#!/bin/sh +# +# Blackbox test for share with preserve case options +# +# https://bugzilla.samba.org/show_bug.cgi?id=10650 + +if [ $# -lt 6 ]; then + cat <&1) + status=$? + if [ x$status = x0 ]; then + subunit_pass_test "$name" + else + echo "$output" | subunit_fail_test "$name" + fi + return $status +} + +SHARE="lowercase" + +for PROTOCOL in $PROTOCOL_LIST; do + test_smbclient "Test lowercase ls 1 ($PROTOCOL)" $SHARE "ls 1" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + test_smbclient "Test lowercase get 1 ($PROTOCOL)" $SHARE "get 1 LOCAL_1" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + rm -f LOCAL_1 + + test_smbclient "Test lowercase ls A ($PROTOCOL)" $SHARE "ls A" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + test_smbclient "Test lowercase get A ($PROTOCOL)" $SHARE "get A LOCAL_A" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + rm -f LOCAL_A + + test_smbclient "Test lowercase ls z ($PROTOCOL)" $SHARE "ls z" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + test_smbclient "Test lowercase get z ($PROTOCOL)" $SHARE "get z LOCAL_Z" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + rm -f LOCAL_Z +done + +SHARE="lowercase-30000" + +for PROTOCOL in $PROTOCOL_LIST; do + test_smbclient "Test lowercase ls 25839 ($PROTOCOL)" $SHARE "ls 25839" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + + test_smbclient "Test lowercase ls 1 ($PROTOCOL)" $SHARE "ls 1" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + test_smbclient "Test lowercase get 1 ($PROTOCOL)" $SHARE "get 1 LOCAL_1" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + rm -f LOCAL_1 + + test_smbclient "Test lowercase ls A ($PROTOCOL)" $SHARE "ls A" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + test_smbclient "Test lowercase get A ($PROTOCOL)" $SHARE "get A LOCAL_A" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + rm -f LOCAL_A + + test_smbclient "Test lowercase ls z ($PROTOCOL)" $SHARE "ls z" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + test_smbclient "Test lowercase get z ($PROTOCOL)" $SHARE "get z LOCAL_Z" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + rm -f LOCAL_Z +done + +exit $failed diff --git a/source3/script/tests/test_printing_var_exp.sh b/source3/script/tests/test_printing_var_exp.sh new file mode 100755 index 0000000..5729344 --- /dev/null +++ b/source3/script/tests/test_printing_var_exp.sh @@ -0,0 +1,93 @@ +#!/bin/sh + +if [ $# -lt 4 ]; then + cat <$BINDIR/pthreadpooltest < $tmpfile + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/recycle -I$SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval "$cmd") + ret=$? + rm -f "$tmpfile" + + if [ $ret != 0 ]; then + printf "%s\n" "$out" + printf "failed recycle smbclient run with error %s\n" "$ret" + return 1 + fi + + test -e "$share_test_dir/.trash/testfile1" || { + printf ".trash/testfile1 expected to exist but does NOT exist\n" + return 1 + } + test -e "$share_test_dir/.trash/testfile2.tmp" && { + printf ".trash/testfile2.tmp not expected to exist but DOES exist\n" + return 1 + } + perm_want=755 + perm_is=`stat -c '%a' "$share_test_dir/.trash/"` + test "$perm_is" = "$perm_want" || { + printf ".trash/ permission should be $perm_want but is $perm_is\n" + return 1 + } + return 0 +} + + +testit "recycle" \ + test_recycle || + failed=$((failed + 1)) + +# +# Cleanup. +do_cleanup + +testok "$0" "$failed" diff --git a/source3/script/tests/test_registry_share.sh b/source3/script/tests/test_registry_share.sh new file mode 100755 index 0000000..22e9f73 --- /dev/null +++ b/source3/script/tests/test_registry_share.sh @@ -0,0 +1,39 @@ +#!/bin/sh +# Blackbox tests for registry shares +# + +if [ $# -lt 3 ]; then + cat < + +if [ $# -lt 2 ]; then + echo "Usage: test_registry_upgrade.sh NET DBWRAP_TOOL" + exit 1 +fi + +SCRIPT_DIR=$(dirname $0) +BASE_DIR="${SCRIPT_DIR}/../../.." + +NET="$1" +DBWRAP_TOOL="$2 --persistent" +DATADIR="${BASE_DIR}/testdata/samba3" +WORKSPACE="${SELFTEST_TMPDIR}/registry_upgrade" +CONFIG_FILE="${WORKSPACE}/smb.conf" +CONFIGURATION="--configfile=${CONFIG_FILE}" + +NETCMD="$NET $CONFIGURATION" + +incdir="${BASE_DIR}/testprogs/blackbox" +. $incdir/subunit.sh + +failed=0 + +cd $SELFTEST_TMPDIR || exit 1 + +REGPATH="HKLM\Software\Samba" + +LOGDIR_PREFIX="registry_upgrade" + +registry_check() +( + CHECKNO="$1" + CHECKDIFF="$2" + REGVER="" + ALLOWEDERR="INFO: version =|Check database:|overwrite registry format version 0 with 1|no INFO/version found" + + test "x$CHECKNO" = "x0" && { + REGVER="--reg-version=1" + } + + echo "Registry check $CHECKNO" | tee -a $LOG + CHECK="$($NETCMD registry check $REGVER 2>&1)" + RC=$? + + ERRORSTR="$(echo "$CHECK" | grep -vE $ALLOWEDERR)" + test "x$RC" = "x0" || { + echo "upgrade check $CHECKNO failed:" | tee -a $LOG + return 1 + } + + test "x$ERRORSTR" = "x" || { + echo "upgrade check $CHECKNO failed:" | tee -a $LOG + echo "reason: $CHECK" | tee -a $LOG + return 1 + } + + test "x$CHECKDIFF" = "xcheckdiff" && { + $NETCMD registry export 'HKLM' $WORKSPACE/export_${CHECKNO}.reg >>$LOG + test "x$?" = "x0" || { + echo "Error: 'net registry export HKLM' failed" | tee -a $LOG + } + + diff -q $WORKSPACE/export_0.reg $WORKSPACE/export_${CHECKNO}.reg >>$LOG + test "x$?" = "x0" || { + echo "Error: $WORKSPACE/export_0.reg differs from $WORKSPACE/export_${CHECKNO}.reg" | tee -a $LOG + return 1 + } + } + + return 0 +) + +registry_upgrade() +{ + echo registry_upgrade $1 | tee -a $LOG + + (cat $DATADIR/registry.tdb >$WORKSPACE/registry.tdb) >>$LOG 2>&1 + + REGISTRY="${WORKSPACE}/registry.tdb" + + test -e $REGISTRY || { + echo "Error: Database file not available" | tee -a $LOG + return 1 + } + + # create config file + echo '[global]' >${CONFIG_FILE} + echo " state directory = ${WORKSPACE}" >>${CONFIG_FILE} + echo " private directory = ${WORKSPACE}" >>${CONFIG_FILE} + echo " lock directory = ${WORKSPACE}" >>${CONFIG_FILE} + + # set database INFO/version to 1 + #$DBWRAP_TOOL $REGISTRY store 'INFO/version' uint32 1 + #test "x$?" = "x0" || { + # echo "Error: Can not set INFO/version" >> $LOG + # return 1 + #} + + # check original registry.tdb + echo "$REGISTRY" | tee -a $LOG + registry_check 0 + test "x$?" = "x0" || { + echo "Error: initial 'registry_check 0' failed" | tee -a $LOG + return 1 + } + + # trigger upgrade + echo "$NETCMD registry enumerate $REGPATH" >>$LOG + $NETCMD registry enumerate $REGPATH >>$LOG + test "x$?" = "x0" || { + echo "Error: 'net registry enumerate $REGPATH' failed" | tee -a $LOG + return 1 + } + + # check upgraded database + registry_check 1 + test "x$?" = "x0" || { + echo "Error: 'registry_check 1' after upgrade failed" | tee -a $LOG + return 1 + } + + # export database for diffs + $NETCMD registry export 'HKLM' $WORKSPACE/export_0.reg | tee -a $LOG + test "x$?" = "x0" || { + echo "Error 'net registry export' failed" | tee -a $LOG + return 1 + } + + # remove version string + $DBWRAP_TOOL $REGISTRY delete INFO/version | tee -a $LOG + test "x$?" = "x0" || { + echo "Error: Can not remove INFO/version key from registry" | tee -a $LOG + return 1 + } + + # trigger upgrade on upgraded database + echo "$NETCMD registry enumerate $REGPATH" >>$LOG + $NETCMD registry enumerate $REGPATH >>$LOG 2>&1 + test "x$?" = "x0" || { + echo "Error: 'net registry enumerate $REGPATH' failed" | tee -a $LOG + return 1 + } + + # check upgraded database again + registry_check 2 checkdiff + test "x$?" = "x0" || { + echo "Error: 'registry_check 2' after upgrade failed" | tee -a $LOG + return 1 + } + + # set database INFO/version to version 2 + $DBWRAP_TOOL $REGISTRY store 'INFO/version' uint32 2 + test "x$?" = "x0" || { + echo "Error: Can not set INFO/version" | tee -a $LOG + return 1 + } + + # trigger upgrade + $NETCMD registry enumerate $REGPATH >>$LOG + test "x$?" = "x0" || { + echo "Error: 'net registry enumerate $REGPATH' failed" | tee -a $LOG + return 1 + } + + # check upgraded database again + registry_check 3 checkdiff + test "x$?" = "x0" || { + echo "Error: 'registry_check 3' after upgrade failed" | tee -a $LOG + return 1 + } +} + +# remove old workspace +rm -rf $WORKSPACE + +mkdir $WORKSPACE + +DIR=$(mktemp -d ${WORKSPACE}/${LOGDIR_PREFIX}_XXXXXX) +LOG=$DIR/log + +testit "registry_upgrade" registry_upgrade || failed=$(expr $failed + 1) + +if [ $failed -eq 0 ]; then + rm -rf $WORKSPACE +fi + +testok $0 $failed diff --git a/source3/script/tests/test_resolvconf.sh b/source3/script/tests/test_resolvconf.sh new file mode 100755 index 0000000..6cf189c --- /dev/null +++ b/source3/script/tests/test_resolvconf.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +if [ ! -x $BINDIR/resolvconftest ]; then + # Some machines don't have /bin/true, simulate it + cat >$BINDIR/resolvconftest <${error_inject_conf} + +failed=0 + +out=$(${SMBCLIENT} //${SERVER}/${SHARE} ${CONF} -U${USER}%${PASSWORD} \ + -c "put VERSION") +testit_grep "Expect MEDIA_WRITE_PROTECTED" NT_STATUS_MEDIA_WRITE_PROTECTED \ + echo "$out" || failed=$(expr $failed + 1) + +>${error_inject_conf} + +testok $0 $failed diff --git a/source3/script/tests/test_rpcclient.sh b/source3/script/tests/test_rpcclient.sh new file mode 100755 index 0000000..4260963 --- /dev/null +++ b/source3/script/tests/test_rpcclient.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +if [ $# -lt 1 ]; then + cat < +EOF + exit 1 +fi + +KRB5CCNAME=$1 +shift 1 +export KRB5CCNAME +ADDARGS="$*" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +testit "rpcclient" $VALGRIND $BINDIR/rpcclient $ADDARGS || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_rpcclient_dfs.sh b/source3/script/tests/test_rpcclient_dfs.sh new file mode 100755 index 0000000..0ae9e50 --- /dev/null +++ b/source3/script/tests/test_rpcclient_dfs.sh @@ -0,0 +1,45 @@ +#!/bin/sh +# +# Copyright (c) 2022 Pavel Filipenský +# +# Blackbox tests for the rpcclient DFS commands + +if [ $# -lt 4 ]; then + cat < +EOF + exit 1 +fi + +USERNAME="$1" +PASSWORD="$2" +shift 2 +ADDARGS="$@" + +rpcclient_samlogon_schannel_seal() +{ + $VALGRIND $BINDIR/rpcclient -U% -c "schannel;samlogon '$USERNAME' '$PASSWORD';samlogon '$USERNAME' '$PASSWORD'" "$@" +} + +rpcclient_samlogon_schannel_sign() +{ + $VALGRIND $BINDIR/rpcclient -U% -c "schannelsign;samlogon '$USERNAME' '$PASSWORD';samlogon '$USERNAME' '$PASSWORD'" "$@" +} + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +testit "rpcclient dsenumdomtrusts" $VALGRIND $BINDIR/rpcclient $ADDARGS -U% -c "dsenumdomtrusts" || failed=$(expr $failed + 1) +testit "rpcclient getdcsitecoverage" $VALGRIND $BINDIR/rpcclient $ADDARGS -U% -c "getdcsitecoverage" || failed=$(expr $failed + 1) +testit "rpcclient samlogon schannel seal" rpcclient_samlogon_schannel_seal $ADDARGS || failed=$(expr $failed +1) +testit "rpcclient samlogon schannel sign" rpcclient_samlogon_schannel_sign $ADDARGS || failed=$(expr $failed +1) + +testok $0 $failed diff --git a/source3/script/tests/test_rpcclientsrvsvc.sh b/source3/script/tests/test_rpcclientsrvsvc.sh new file mode 100755 index 0000000..fdade1a --- /dev/null +++ b/source3/script/tests/test_rpcclientsrvsvc.sh @@ -0,0 +1,90 @@ +#!/bin/sh +# +# Blackbox tests for the rpcclient srvsvc commands +# +# Copyright (C) 2015 Christof Schmitt + +if [ $# -lt 5 ]; then + cat < $destdir/foo + mkdir -p $destdir/bar + echo "$content" > $destdir/bar/baz + echo "$content" > $destdir/bar/lfoo + echo "$content" > $destdir/bar/letcpasswd + echo "$content" > $destdir/bar/loutside + elif [ "$version" = "fullsnap" ] ; then + #snapshot files + echo "$content" > $destdir/foo + mkdir -p $destdir/bar + echo "$content" > $destdir/bar/baz + ln -fs ../foo $destdir/bar/lfoo + ln -fs /etc/passwd $destdir/bar/letcpasswd + ln -fs ../../outside $destdir/bar/loutside + echo "$content" > `dirname $destdir`/outside + else #subshare snapshot - at bar + echo "$content" > $destdir/baz + ln -fs ../foo $destdir/lfoo + ln -fs /etc/passwd $destdir/letcpasswd + ln -fs ../../outside $destdir/loutside + echo "$content" > `dirname $destdir`/../outside + fi + +} + +# build a snapshots directory +build_snapshots() +{ + local where #where to build snapshots + local prefix #prefix from snapshot dir to share root + local start #timestamp index of first snapshot + local end #timestamp index of last snapshot + local sub #creat a snapshot of subtree of share + local snapdir + local snapname + local i + local version + + where=$1 + prefix=$2 + start=$3 + end=$4 + sub=$5 + + snapdir=$where/.snapshots + mkdir -p $snapdir + + version="fullsnap" + if [ "$sub" = "1" ] ; then + version="subsnap" + prefix="" + + # a valid link target for an inner symlink - + # the link is not broken yet should be blocked + # by wide link checks + touch $snapdir/foo + fi + + for i in `seq $start $end` ; do + snapname=${SNAPSHOTS[$i]} + mkdir $snapdir/$snapname + build_files $snapdir/$snapname "$prefix" $version "$snapname" + done +} + +# Test listing previous versions of a file +test_count_versions() +{ + local share + local path + local expected_count + local skip_content + local versions + local tstamps + local tstamp + local content + local is_dir + + share=$1 + path=$2 + expected_count=$3 + skip_content=$4 + versions=`$SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "allinfo $path" | grep "^create_time:" | wc -l` + if [ "$versions" != "$expected_count" ] ; then + echo "expected $expected_count versions of $path, got $versions" + return 1 + fi + + is_dir=0 + $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "allinfo $path" | grep "^attributes:.*D" && is_dir=1 + if [ $is_dir = 1 ] ; then + skip_content=1 + fi + + #readable snapshots + tstamps=`$SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "allinfo $path" | awk '/^@GMT-/ {snapshot=$1} /^create_time:/ {printf "%s\n", snapshot}'` + for tstamp in $tstamps ; do + if [ $is_dir = 0 ] ; + then + if ! $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "get $tstamp\\$path $WORKDIR/foo" ; then + echo "Failed getting \\\\$SERVER\\$share\\$tstamp\\$path" + return 1 + fi + else + if ! $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "ls $tstamp\\$path\\*" ; then + echo "Failed listing \\\\$SERVER\\$share\\$tstamp\\$path" + return 1 + fi + fi + + #also check the content, but not for wide links + if [ "x$skip_content" != "x1" ] ; then + content=`cat $WORKDIR/foo` + if [ "$content" != "$tstamp" ] ; then + echo "incorrect content of \\\\$SERVER\\$share\\$tstamp\\$path expected [$tstamp] got [$content]" + return 1 + fi + fi + done + + #non-readable snapshots + tstamps=`$SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "allinfo $path" | \ + awk '/^@GMT-/ {if (snapshot!=""){printf "%s\n", snapshot} ; snapshot=$1} /^create_time:/ {snapshot=""} END {if (snapshot!=""){printf "%s\n", snapshot}}'` + for tstamp in $tstamps ; do + if [ $is_dir = 0 ] ; + then + if $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "get $tstamp\\$path $WORKDIR/foo" ; then + echo "Unexpected success getting \\\\$SERVER\\$share\\$tstamp\\$path" + return 1 + fi + else + if $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "ls $tstamp\\$path\\*" ; then + echo "Unexpected success listing \\\\$SERVER\\$share\\$tstamp\\$path" + return 1 + fi + fi + done +} + +# Test fetching a previous version of a file +test_fetch_snap_file() +{ + local share + local path + local snapidx + + share=$1 + path=$2 + snapidx=$3 + $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP \ + -c "get ${SNAPSHOTS[$snapidx]}/$path $WORKDIR/foo" +} + +# Test fetching a previous version of a file +test_fetch_snap_dir() +{ + local share + local path + local snapidx + + share=$1 + path=$2 + snapidx=$3 + + # This first command is not strictly needed, but it causes the snapshots to + # appear in a network trace which helps debugging... + $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP \ + -c "allinfo $path" + + $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP \ + -c "ls ${SNAPSHOTS[$snapidx]}/$path/*" +} + +test_shadow_copy_fixed() +{ + local share #share to contact + local where #where to place snapshots + local prefix #prefix to files inside snapshot + local msg + local allow_wl + local ncopies_allowd + local ncopies_blocked + + share=$1 + where=$2 + prefix=$3 + msg=$4 + allow_wl=$5 + + ncopies_allowed=4 + ncopies_blocked=1 + if [ -n "$allow_wl" ] ; then + ncopies_blocked=4 + fi + + #delete snapshots from previous tests + find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1 + build_snapshots $WORKDIR/$where "$prefix" 0 2 + + testit "$msg - regular file" \ + test_count_versions $share foo $ncopies_allowed || \ + failed=`expr $failed + 1` + + testit "$msg - regular file in subdir" \ + test_count_versions $share bar/baz $ncopies_allowed || \ + failed=`expr $failed + 1` + + testit "$msg - regular file in case insensitive subdir" \ + test_count_versions $share bar/bAz $ncopies_allowed || \ + failed=`expr $failed + 1` + + testit "$msg - local symlink" \ + test_count_versions $share bar/lfoo $ncopies_allowed || \ + failed=`expr $failed + 1` + + testit "$msg - abs symlink outside" \ + test_count_versions $share bar/letcpasswd $ncopies_blocked 1 || \ + failed=`expr $failed + 1` + + testit "$msg - rel symlink outside" \ + test_count_versions $share bar/loutside $ncopies_blocked 1 || \ + failed=`expr $failed + 1` + + testit "$msg - list directory" \ + test_count_versions $share bar $ncopies_allowed || \ + failed=`expr $failed + 1` +} + +test_shadow_copy_everywhere() +{ + local share #share to contact + + share=$1 + + #delete snapshots from previous tests + find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1 + build_snapshots "$WORKDIR/mount" "base/share" 0 0 + build_snapshots "$WORKDIR/mount/base" "share" 1 2 + build_snapshots "$WORKDIR/mount/base/share" "" 3 5 + build_snapshots "$WORKDIR/mount/base/share/bar" "" 6 9 1 + + testit "snapshots in each dir - regular file" \ + test_count_versions $share foo 4 || \ + failed=`expr $failed + 1` + + testit "snapshots in each dir - regular file in subdir" \ + test_count_versions $share bar/baz 5 || \ + failed=`expr $failed + 1` + + testit "snapshots in each dir - local symlink (but outside snapshot)" \ + test_count_versions $share bar/lfoo 1 || \ + failed=`expr $failed + 1` + + testit "snapshots in each dir - abs symlink outside" \ + test_count_versions $share bar/letcpasswd 1 || \ + failed=`expr $failed + 1` + + testit "snapshots in each dir - rel symlink outside" \ + test_count_versions $share bar/loutside 1 || \ + failed=`expr $failed + 1` + + #the previous versions of the file bar/lfoo points to are outside its + #snapshot, and are not reachable. However, but previous versions + #taken at different, non-overlapping times higher up the + #hierarchy are still reachable. + testit "fetch a previous version of a regular file" \ + test_fetch_snap_file $share "bar/baz" 6 || \ + failed=`expr $failed + 1` + + testit "fetch a previous version of a regular file via non-canonical parent path" \ + test_fetch_snap_file $share "BAR/baz" 6 || \ + failed=`expr $failed + 1` + + testit "fetch a previous version of a regular file via non-canonical basepath" \ + test_fetch_snap_file $share "bar/BAZ" 6 || \ + failed=`expr $failed + 1` + + testit "fetch a previous version of a regular file via non-canonical path" \ + test_fetch_snap_file $share "BAR/BAZ" 6 || \ + failed=`expr $failed + 1` + + testit_expect_failure "fetch a (non-existent) previous version of a symlink" \ + test_fetch_snap_file $share "bar/lfoo" 6 || \ + failed=`expr $failed + 1` + + testit "fetch a previous version of a symlink via browsing (1)" \ + test_fetch_snap_file $share "bar/lfoo" 0 || \ + failed=`expr $failed + 1` + + testit "fetch a previous version of a symlink via browsing (2)" \ + test_fetch_snap_file $share "bar/lfoo" 1 || \ + failed=`expr $failed + 1` + + testit "fetch a previous version of a symlink via browsing (3)" \ + test_fetch_snap_file $share "bar/lfoo" 3 || \ + failed=`expr $failed + 1` + + testit "list a previous version directory" \ + test_fetch_snap_dir $share "bar" 6 || \ + failed=`expr $failed + 1` +} + +test_shadow_copy_format() +{ + local share #share to contact + local where #where to place snapshots + local prefix #prefix to files inside snapshot + local ncopies_allowd + local msg + + share=$1 + where=$2 + prefix=$3 + ncopies_allowed=$4 + msg=$5 + + #delete snapshots from previous tests + find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1 + build_snapshots $WORKDIR/$where "$prefix" 10 19 + + testit "$msg - regular file" \ + test_count_versions $share foo $ncopies_allowed 1 || \ + failed=`expr $failed + 1` +} + +# Test fetching a file where there's no current version of it +test_missing_basedir() +{ + local share + local where + local prefix + local snapidx + + share=$1 + where=$2 + prefix=$3 + snapidx=$4 + + #delete snapshots from previous tests + find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1 + build_snapshots $WORKDIR/$where "$prefix" "$snapidx" "$snapidx" + + (cd "$WORKDIR/$where"/share; mv bar _bar) + + testit "fetch a file without a latest version" \ + test_fetch_snap_file "$share" "bar/baz" "$snapidx" || \ + failed=`expr $failed + 1` + + (cd "$WORKDIR/$where"/share; mv _bar bar) +} + +#build "latest" files +build_files $WORKDIR/mount base/share "latest" "latest" + +failed=0 + +# a test with wide links allowed - also to verify that what's later +# being blocked is a result of server security measures and not +# a testing artifact. +test_shadow_copy_fixed shadow_wl mount base/share "shadow copies with wide links allowed" 1 + +# tests for a fixed snapshot location +test_shadow_copy_fixed shadow1 mount base/share "full volume snapshots mounted under volume" +test_shadow_copy_fixed shadow2 . base/share "full volume snapshots mounted outside volume" +test_shadow_copy_fixed shadow3 mount/base share "sub volume snapshots mounted under snapshot point" +test_shadow_copy_fixed shadow4 . share "sub volume snapshots mounted outside" +test_shadow_copy_fixed shadow5 mount/base/share "" "full volume snapshots and share mounted under volume" +test_shadow_copy_fixed shadow6 . "" "full volume snapshots and share mounted outside" +test_shadow_copy_fixed shadow8 . share "logical snapshot layout" + +# tests for snapshot everywhere - one snapshot location +test_shadow_copy_fixed shadow7 mount base/share "'everywhere' full volume snapshots" +test_shadow_copy_fixed shadow7 mount/base share "'everywhere' sub volume snapshots" +test_shadow_copy_fixed shadow7 mount/base/share "" "'everywhere' share snapshots" + +# a test for snapshots everywhere - multiple snapshot locations +test_shadow_copy_everywhere shadow7 + +# tests for testing snapshot selection via shadow:format +test_shadow_copy_format shadow_fmt0 mount/base share 3 "basic shadow:format test" +test_shadow_copy_format shadow_fmt1 mount/base share 2 "shadow:format with only date" +test_shadow_copy_format shadow_fmt2 mount/base share 2 "shadow:format with some prefix" +test_shadow_copy_format shadow_fmt3 mount/base share 2 "shadow:format with modified format" +test_shadow_copy_format shadow_fmt4 mount/base share 3 "shadow:format with snapprefix" +test_shadow_copy_format shadow_fmt5 mount/base share 6 "shadow:format with delimiter" +test_missing_basedir shadow3 "mount/base" "share" 6 + +exit $failed diff --git a/source3/script/tests/test_shadow_copy_torture.sh b/source3/script/tests/test_shadow_copy_torture.sh new file mode 100755 index 0000000..3a6ba91 --- /dev/null +++ b/source3/script/tests/test_shadow_copy_torture.sh @@ -0,0 +1,227 @@ +#!/usr/bin/env bash +# +# Blackbox test for shadow_copy2 VFS. +# + +if [ $# -lt 7 ]; then + cat <$destdir/foo + + mkdir -p $WORKDIR/subdir/ + touch $WORKDIR/subdir/hardlink +} + +# build a snapshots directory +build_snapshots() +{ + local snapdir + + snapdir=$WORKDIR/.snapshots + + mkdir -p $snapdir/$SNAPSHOT + + build_files $snapdir/$SNAPSHOT + + mkdir -p $snapdir/$SNAPSHOT/subdir + ln "$WORKDIR"/subdir/hardlink "$snapdir"/$SNAPSHOT/subdir/hardlink +} + +build_stream_on_snapshot() +{ + file=$WORKDIR/.snapshots/$SNAPSHOT/foo + + setfattr -n 'user.DosStream.bar:$DATA' -v baz $file || return 1 +} + +test_shadow_copy_write() +{ + local msg + + msg=$1 + + #delete snapshots from previous tests + find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1 + build_snapshots + + testit "writing to shadow copy of a file" \ + $SMBTORTURE \ + -U$USERNAME%$PASSWORD \ + "//$SERVER/shadow_write" \ + --option="torture:twrp_file=foo" \ + --option="torture:twrp_snapshot=$SNAPSHOT" \ + smb2.twrp.write || + failed=$(expr $failed + 1) +} + +test_shadow_copy_stream() +{ + local msg + + msg=$1 + + #delete snapshots from previous tests + find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1 + build_snapshots + build_stream_on_snapshot || { + subunit_start_test msg + subunit_skip_test msg </dev/null 2>&1 + build_snapshots + + testit "opening shadow copy root of share" \ + $SMBTORTURE \ + -U$USERNAME%$PASSWORD \ + "//$SERVER/shadow_write" \ + --option="torture:twrp_snapshot=$SNAPSHOT" \ + smb2.twrp.openroot || + failed=$(expr $failed + 1) +} + +test_shadow_copy_fix_inodes() +{ + local msg + + msg=$1 + + #delete snapshots from previous tests + find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1 + build_snapshots + + out=$($SMBCLIENT \ + -U $USERNAME%$PASSWORD \ + "//$SERVER/shadow_write" \ + -c "open $SNAPSHOT/subdir/hardlink") || failed=$(expr $failed + 1) + echo $out + echo $out | grep "hardlink: for read/write fnum 1" || return 1 +} + +build_hiddenfile() +{ + local snapdir + + snapdir=$WORKDIR/.snapshots + + #delete snapshots from previous tests + find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1 + build_snapshots + + touch $WORKDIR/hiddenfile + + # Create a file with hidden attribute + $SMBCLIENT -U $USERNAME%$PASSWORD \ + "//$SERVER/shadow_write" \ + -c "put $WORKDIR/hiddenfile hiddenfile; setmode hiddenfile +h" + # ...and move it to the snapshot directory + mv $WORKDIR/hiddenfile $snapdir/$SNAPSHOT/ +} + +test_hiddenfile() +{ + build_hiddenfile + + out=$($SMBCLIENT \ + -U $USERNAME%$PASSWORD \ + "//$SERVER/shadow_write" \ + -c "allinfo $SNAPSHOT/hiddenfile") || return 1 + echo $out + echo $out | grep "attributes: HA (22)" || return 1 + + out=$($SMBCLIENT \ + -U $USERNAME%$PASSWORD \ + "//$SERVER/shadow_write" \ + -c "ls $SNAPSHOT/hiddenfile") || return 1 + echo $out + echo $out | grep "hiddenfile[[:blank:]]*AH" || return 1 + + return 0 +} + +test_shadow_copy_listdir_fix_inodes() +{ + local msg + + msg=$1 + + #delete snapshots from previous tests + find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1 + build_snapshots + + testit "$msg" \ + $SMBTORTURE \ + -U$USERNAME%$PASSWORD \ + "//$SERVER/shadow_write" \ + --option="torture:twrp_snapshot=$SNAPSHOT" \ + smb2.twrp.listdir || + failed=$(expr $failed + 1) +} + +build_files $WORKDIR + +# test open for writing and write behaviour of snapshoted files +test_shadow_copy_write "write behaviour of snapshoted files" + +test_shadow_copy_stream "reading stream of snapshotted file" + +test_shadow_copy_openroot "opening root of shadow copy share" + +testit "fix inodes with hardlink" test_shadow_copy_fix_inodes || failed=$(expr $failed + 1) + +testit "Test reading DOS attribute" test_hiddenfile || failed=$(expr $failed + 1) + +test_shadow_copy_listdir_fix_inodes "fix inodes when listing directory" + +exit $failed diff --git a/source3/script/tests/test_shareenum.sh b/source3/script/tests/test_shareenum.sh new file mode 100755 index 0000000..0334243 --- /dev/null +++ b/source3/script/tests/test_shareenum.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +# this tests share enumeration with "access based share enum" + +if [ $# -lt 4 ]; then + cat </dev/null 2>&1 +} + +testit "$USERNAME sees tmp" user_see_share $USERNAME tmp +testit "$USERNAME sees valid-users-tmp" user_see_share $USERNAME valid-users-tmp +testit "force_user sees tmp" user_see_share force_user tmp +testit_expect_failure "force_user does not see valid-users-tmp" user_see_share force_user valid-users-tmp diff --git a/source3/script/tests/test_sharesec.sh b/source3/script/tests/test_sharesec.sh new file mode 100755 index 0000000..a083a56 --- /dev/null +++ b/source3/script/tests/test_sharesec.sh @@ -0,0 +1,140 @@ +#!/bin/sh +# +# Test sharesec command. +# +# Verify that changing and querying the security descriptor works. Also +# ensure that the output format for ACL entries does not change. +# +# The test uses well-known SIDs to not require looking up names and SIDs +# +# Copyright (C) 2015, 2019 Christof Schmitt + +if [ $# -lt 4 ]; then + echo Usage: test_sharesec.sh SERVERCONFFILE SHARESEC NET SHARE + exit 1 +fi + +CONF=$1 +SHARESEC=$2 +NET=$3 +SHARE=$4 + +CMD="$SHARESEC $CONF $SHARE" +NET_CMD="$NET $CONF" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +testit "Set new ACL" $CMD --replace S-1-1-0:ALLOWED/0x0/READ || + failed=$(expr $failed + 1) +testit "Query new ACL" $CMD --view || failed=$(expr $failed + 1) +COUNT=$($CMD --view | grep ACL: | sed -e 's/^ACL://' | wc -l) +testit "Verify new ACL count" test $COUNT -eq 1 || failed=$(expr $failed + 1) +ACL=$($CMD --view | grep ACL: | sed -e 's/^ACL://') +testit "Verify new ACL" test $ACL = S-1-1-0:ALLOWED/0x0/READ + +OWNER=$($CMD --view | grep OWNER:) +testit "Verify empty OWNER" test "$OWNER" = "OWNER:" || + failed=$(expr $failed + 1) +GROUP=$($CMD --view | grep GROUP:) +testit "Verify empty GROUP" test "$GROUP" = "GROUP:" || + failed=$(expr $failed + 1) +CONTROL=$($CMD --view | grep CONTROL: | sed -e 's/^CONTROL://') +testit "Verify control flags" test "$CONTROL" = "SR|DP" || + failed=$(expr $failed + 1) + +testit "Add second ACL entry" $CMD --add S-1-5-32-544:ALLOWED/0x0/FULL || + failed=$(expr $failed + 1) +testit "Query ACL with two entries" $CMD --view || + failed=$(expr $failed + 1) +COUNT=$($CMD --view | grep ACL: | sed -e 's/^ACL://' | wc -l) +testit "Verify ACL count with two entries" test $COUNT -eq 2 || + failed=$(expr $failed + 1) +ACL=$($CMD --view | grep S-1-5-32-544 | sed -e 's/^ACL://') +testit "Verify second ACL entry" test $ACL = S-1-5-32-544:ALLOWED/0x0/FULL || + failed=$(expr $failed + 1) + +testit "Modify ACL entry" $CMD --modify S-1-5-32-544:ALLOWED/0x0/CHANGE || + failed=$(expr $failed + 1) +testit "Verify ACL with two entries after modify" $CMD --view || + failed=$(expr $failed + 1) +COUNT=$($CMD --view | grep ACL: | sed -e 's/^ACL://' | wc -l) +testit "Verify ACL count with two entries after modify" test $COUNT -eq 2 || + failed=$(expr $failed + 1) +ACL=$($CMD --view | grep S-1-5-32-544 | sed -e 's/^ACL://') +testit "Verify modified entry" test $ACL = S-1-5-32-544:ALLOWED/0x0/CHANGE || + failed=$(expr $failed + 1) + +testit "Add deny ACL entry" $CMD --add S-1-5-32-545:DENIED/0x0/CHANGE || + failed=$(expr $failed + 1) +testit "Query ACL with three entries" $CMD --view || + failed=$(expr $failed + 1) +COUNT=$($CMD --view | grep ACL: | sed -e 's/^ACL://' | wc -l) +testit "Verify ACL count with three entries" test $COUNT -eq 3 || + failed=$(expr $failed + 1) +ACL=$($CMD --view | grep S-1-5-32-545 | sed -e 's/^ACL://') +testit "Verify DENIED ACL entry" test $ACL = S-1-5-32-545:DENIED/0x0/CHANGE || + failed=$(expr $failed + 1) + +testit "Add special ACL entry" $CMD --add S-1-5-32-546:ALLOWED/0x0/RWXDP || + failed=$(expr $failed + 1) +testit "Query ACL with four entries" $CMD --view || + failed=$(expr $failed + 1) +COUNT=$($CMD --view | grep ACL: | sed -e 's/^ACL://' | wc -l) +testit "Verify ACL count with four entries" test $COUNT -eq 4 || + failed=$(expr $failed + 1) +ACL=$($CMD --view | grep S-1-5-32-546 | sed -e 's/^ACL://') +testit "Verify special entry" test $ACL = S-1-5-32-546:ALLOWED/0x0/RWXDP || + failed=$(expr $failed + 1) + +testit "Remove ACL entry" $CMD --remove S-1-5-32-546:ALLOWED/0x0/RWXDP || + failed=$(expr $failed + 1) +testit "Query ACL with three entries after removal" $CMD --view || + failed=$(expr $failed + 1) +COUNT=$($CMD --view | grep ACL: | sed -e 's/^ACL://' | wc -l) +testit "Verify ACL count after removal" test $COUNT -eq 3 || + failed=$(expr $failed + 1) +ACL="$($CMD --view | grep S-1-5-32-546)" +testit "Verify removal" test -e "$ACL" || failed=$(expr $failed + 1) + +testit "Set ACL as hex value" $CMD --add S-1-5-32-547:0x1/0x0/0x001F01FF || + failed=$(expr $failed + 1) +ACL="$($CMD --view | grep S-1-5-32-547 | sed -e 's/^ACL://')" +testit "Verify numerically set entry" \ + test "$ACL" = S-1-5-32-547:DENIED/0x0/FULL || + failed=$(expr $failed + 1) + +testit "Set ACL as dec value" $CMD --add S-1-5-32-548:1/0/0x001F01FF || + failed=$(expr $failed + 1) +ACL="$($CMD --view | grep S-1-5-32-548 | sed -e 's/^ACL://')" +testit "Verify numerically set entry" \ + test "$ACL" = S-1-5-32-548:DENIED/0x0/FULL || + failed=$(expr $failed + 1) + +testit "Set back to default ACL " $CMD --replace S-1-1-0:ALLOWED/0x0/FULL || + failed=$(expr $failed + 1) +testit "Query standard ACL" $CMD --view || + failed=$(expr $failed + 1) +COUNT=$($CMD --view | grep ACL: | sed -e 's/^ACL://' | wc -l) +testit "Verify standard ACL count" test $COUNT -eq 1 || + failed=$(expr $failed + 1) +ACL=$($CMD --view | grep ACL: | sed -e 's/^ACL://') +testit "Verify standard ACL" test $ACL = S-1-1-0:ALLOWED/0x0/FULL || + failed=$(expr $failed + 1) + +testit "Create new share" $NET_CMD conf addshare tmp_share /tmp || + failed=$(expr $failed + 1) +testit "Change ACL" $SHARESEC $CONF --replace S-1-1-0:DENIED/0x0/FULL tmp_share || + failed=$(expr $failed + 1) +testit "Delete share" $NET_CMD conf delshare tmp_share || + failed=$(expr $failed + 1) +testit "Create share again" $NET_CMD conf addshare tmp_share /tmp || + failed=$(expr $failed + 1) +ACL=$($SHARESEC $CONF --view tmp_share | grep 'ACL:') +testit "Check for default ACL" \ + test "$ACL" = "ACL:S-1-1-0:ALLOWED/0x0/FULL" || + failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_smb1_shadow_copy_torture.sh b/source3/script/tests/test_smb1_shadow_copy_torture.sh new file mode 100755 index 0000000..3ea3030 --- /dev/null +++ b/source3/script/tests/test_smb1_shadow_copy_torture.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# +# Blackbox test for shadow_copy2 VFS - SMB1 only. +# + +if [ $# -lt 7 ]; then + cat <$destdir/foo +} + +# build a snapshots directory +build_snapshots() +{ + local snapdir + + snapdir=$WORKDIR/.snapshots + + mkdir -p $snapdir + mkdir $snapdir/$SNAPSHOT + + build_files $snapdir/$SNAPSHOT +} + +test_shadow_copy_openroot() +{ + local msg + + msg=$1 + + #delete snapshots from previous tests + find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1 + build_snapshots + + testit "opening shadow copy root of share over SMB1" \ + $SMBTORTURE \ + -U$USERNAME%$PASSWORD \ + "//$SERVER/shadow_write" \ + --option="torture:twrp_snapshot=$SNAPSHOT" \ + base.smb1-twrp-openroot || + failed=$(expr $failed + 1) +} + +build_files $WORKDIR + +# test open for writing and write behaviour of snapshoted files +test_shadow_copy_openroot "opening root of shadow copy share" + +exit $failed diff --git a/source3/script/tests/test_smb1_system_security.sh b/source3/script/tests/test_smb1_system_security.sh new file mode 100755 index 0000000..dac8897 --- /dev/null +++ b/source3/script/tests/test_smb1_system_security.sh @@ -0,0 +1,44 @@ +#!/bin/sh +# +# Runs the smbtorture3 SMB1-SYSTEM-SECURITY test +# that requires SeSecurityPrivilege against Samba. +# + +if [ $# -lt 7 ]; then + echo "Usage: $0 SERVER SERVER_IP USERNAME PASSWORD SMBTORTURE3 NET SHARE" + exit 1 +fi + +SERVER="$1" +SERVER_IP="$2" +USERNAME="$3" +PASSWORD="$4" +SMBTORTURE3="$5" +NET="$6" +SHARE="$7" + +failed=0 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +smb1_system_security() +{ + out=$($SMBTORTURE3 //$SERVER_IP/$SHARE -U $USERNAME%$PASSWORD -mNT1 SMB1-SYSTEM-SECURITY) + if [ $? -ne 0 ]; then + echo "SMB1-SYSTEM-SECURITY failed" + echo "$out" + return 1 + fi +} + +# Grant SeSecurityPrivilege to the user +testit "grant SeSecurityPrivilege" $NET rpc rights grant $USERNAME SeSecurityPrivilege -U $USERNAME%$PASSWORD -I $SERVER_IP || failed=$(expr $failed + 1) + +# Run the test. +testit "smb1-system-security" smb1_system_security || failed=$(expr $failed + 1) + +# Revoke SeSecurityPrivilege +testit "revoke SeSecurityPrivilege" $NET rpc rights revoke $USERNAME SeSecurityPrivilege -U $USERNAME%$PASSWORD -I $SERVER_IP || failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/test_smb2_not_casesensitive.sh b/source3/script/tests/test_smb2_not_casesensitive.sh new file mode 100755 index 0000000..7e85834 --- /dev/null +++ b/source3/script/tests/test_smb2_not_casesensitive.sh @@ -0,0 +1,81 @@ +#!/bin/sh +# +# Blackbox test for SMB2 case insensitivity +# + +if [ $# -lt 6 ]; then + cat <$tmpfile + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -mSMB3 -U$USERNAME%$PASSWORD "$SERVER" -I $SERVER_IP -c "ls TeStFiLe.TxT" 2>&1' + out=$(eval $cmd) + ret=$? + + rm -f $tmpfile + + if [ $ret = 0 ]; then + return 0 + else + echo "$out" + echo "failed to get file with different case" + return 1 + fi +} + +# Test that a rename causes a conflict works when target name exists in +# different case +test_rename() +{ + set -x + tmpfile=$LOCAL_PATH/torename.txt + echo "foobar" >$tmpfile + targetfile=$LOCAL_PATH/target.txt + touch $targetfile + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -mSMB3 -U$USERNAME%$PASSWORD "$SERVER" -I $SERVER_IP -c "rename ToReNaMe.TxT TaRgEt.txt" 2>&1' + out=$(eval $cmd) + ret=$? + + rm -f $tmpfile + rm -f $targetfile + rm -f $LOCAL_PATH/TaRgEt.txt + + if [ $ret = 1 -a -z "${out##*COLLISION*}" ]; then + return 0 + else + echo "$out" + echo "failed to get file with different case" + return 1 + fi +} + +testit "accessing a file with different case succeeds" \ + test_access_with_different_case || + failed=$(expr $failed + 1) + +testit "renaming a file with different case succeeds" \ + test_rename || + failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/test_smbXsrv_client_cross_node.sh b/source3/script/tests/test_smbXsrv_client_cross_node.sh new file mode 100755 index 0000000..5b412b2 --- /dev/null +++ b/source3/script/tests/test_smbXsrv_client_cross_node.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash +# +# Test smbd let cluster node 0 destroy the connection, +# if the client with a specific client-guid connections to node 1 +# + +if [ $# -lt 4 ]; then + echo Usage: test_smbXsrv_client_cross_node.sh SERVERCONFFILE NODE0 NODE1 SHARENAME + exit 1 +fi + +CONF=$1 +NODE0=$2 +NODE1=$3 +SHARE=$4 + +SMBCLIENT="$BINDIR/smbclient" +SMBSTATUS="$BINDIR/smbstatus" + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. "$incdir"/subunit.sh + +failed=0 + +test_smbclient() +{ + name="$1" + server="$2" + share="$3" + cmd="$4" + shift + shift + subunit_start_test "$name" + output=$($VALGRIND $SMBCLIENT //$server/$share -c "$cmd" "$@" 2>&1) + status=$? + if [ x$status = x0 ]; then + subunit_pass_test "$name" + else + echo "$output" | subunit_fail_test "$name" + fi + return $status +} + +cd "$SELFTEST_TMPDIR" || exit 1 + +# Create the smbclient communication pipes. +rm -f smbclient-stdin smbclient-stdout smbclient-stderr +mkfifo smbclient-stdin smbclient-stdout smbclient-stderr + +smbstatus_num_sessions() +{ + UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 "$SMBSTATUS" "$CONF" --json | jq -M '.sessions | length' +} + +testit_grep "step1: smbstatus 0 sessions" '^0$' smbstatus_num_sessions || failed=$(expr $failed + 1) + +test_smbclient "smbclient against node0[${NODE0}]" "${NODE0}" "${SHARE}" "ls" -U"${DC_USERNAME}"%"${DC_PASSWORD}" \ + --option="libsmb:client_guid=6112f7d3-9528-4a2a-8861-0ca129aae6c4" \ + || failed=$(expr $failed + 1) + +testit_grep "step2: smbstatus 0 sessions" '^0$' smbstatus_num_sessions || failed=$(expr $failed + 1) + +CLI_FORCE_INTERACTIVE=1 +export CLI_FORCE_INTERACTIVE + +testit "start backgroup smbclient against node0[${NODE0}]" true || failed=$(expr $failed + 1) + +# Connect a first time +${SMBCLIENT} //"${NODE0}"/"${SHARE}" -U"${DC_USERNAME}"%"${DC_PASSWORD}" \ + --option="libsmb:client_guid=6112f7d3-9528-4a2a-8861-0ca129aae6c4" \ + smbclient-stdout 2>smbclient-stderr & +CLIENT_PID=$! + +exec 100>smbclient-stdin 101&1) + status=$? + if [ x$status = x0 ]; then + subunit_pass_test "$name" + else + echo "$output" | subunit_fail_test "$name" + fi + return $status +} + +cd "$SELFTEST_TMPDIR" || exit 1 + +# Create the smbclient communication pipes. +rm -f smbclient1-stdin smbclient1-stdout smbclient1-stderr +mkfifo smbclient1-stdin smbclient1-stdout smbclient1-stderr +rm -f smbclient2-stdin smbclient2-stdout smbclient2-stderr +mkfifo smbclient2-stdin smbclient2-stdout smbclient2-stderr + +smbstatus_num_sessions() +{ + # We don't check for died processes + UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 "$SMBSTATUS" "$CONF" --fast --json | jq -M '.sessions | length' +} + +ctdb_add_public_ip() +{ + UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 "$CTDB" addip ${CTDB_IFACE_IP}/24 lo + UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 "$CTDB" ipreallocate +} + +ctdb_ip() +{ + UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 "$CTDB" ip +} + +ctdb_gettickles() +{ + UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 "$CTDB" gettickles ${CTDB_IFACE_IP} +} + +ctdb_reload_public_ips() +{ + UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 "$CTDB" reloadips 0 + UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 "$CTDB" ipreallocate +} + +testit_grep_count "step1: smbstatus 0 sessions" '^0$' 1 smbstatus_num_sessions || failed=$(expr $failed + 1) + +test_smbclient "step2: smbclient against node0[${CTDB_IFACE_IP}]" "${CTDB_IFACE_IP}" "${SHARE}" "ls" -U"${DC_USERNAME}"%"${DC_PASSWORD}" \ + --option="libsmb:client_guid=6112f7d3-9528-4a2a-8861-0ca129aae6c4" \ + || failed=$(expr $failed + 1) + +testit_grep_count "step2: smbstatus 0 sessions" '^0$' 1 smbstatus_num_sessions || failed=$(expr $failed + 1) + +CLI_FORCE_INTERACTIVE=1 +export CLI_FORCE_INTERACTIVE + +testit "step3: start backgroup smbclient against node0[${CTDB_IFACE_IP}]" true || failed=$(expr $failed + 1) + +# Connect a first time +${SMBCLIENT} //"${CTDB_IFACE_IP}"/"${SHARE}" -U"${DC_USERNAME}"%"${DC_PASSWORD}" \ + --option="libsmb:client_guid=6112f7d3-9528-4a2a-8861-0ca129aae6c4" \ + smbclient1-stdout 2>smbclient1-stderr & +CLIENT1_PID=$! + +exec 100>smbclient1-stdin 101smbclient2-stdout 2>smbclient2-stderr & +CLIENT2_PID=$! + +exec 200>smbclient2-stdin 201smbclient-stdout 2>smbclient-stderr & +CLIENT_PID=$! + +exec 100>smbclient-stdin 101 +EOF + exit 1 +fi + +SERVER="$1" +SERVER_IP="$2" +USERNAME="$3" +PASSWORD="$4" +SMBCLIENT="$5" +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +shift 5 +ADDARGS="$*" + +failed=0 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +echo "${SERVER_IP}" | grep -q ':.*:' && { + # If we have an ipv6 address e.g. + # fd00:0000:0000:0000:0000:0000:5357:5f03 + # we also try + # fd00-0000-0000-0000-0000-0000-5357-5f03.ipv6-literal.net + IPV6LITERAL=$(echo "${SERVER_IP}.ipv6-literal.net" | sed -e 's!:!-!g' -e 's!%!s!') + testit "smbclient //${IPV6LITERAL}/tmpguest as user" $SMBCLIENT //${IPV6LITERAL}/tmpguest $CONFIGURATION -U$USERNAME%$PASSWORD -c quit $ADDARGS || failed=$(expr $failed + 1) + testit "smbclient //${IPV6LITERAL}./tmpguest as user" $SMBCLIENT //${IPV6LITERAL}./tmpguest $CONFIGURATION -U$USERNAME%$PASSWORD -c quit $ADDARGS || failed=$(expr $failed + 1) +} +testit "smbclient //${SERVER_IP}/tmpguest as user" $SMBCLIENT //${SERVER_IP}/tmpguest $CONFIGURATION -U$USERNAME%$PASSWORD -p 139 -c quit $ADDARGS || failed=$(expr $failed + 1) + +testit "smbclient //$SERVER/guestonly as user" $SMBCLIENT //$SERVER/guestonly $CONFIGURATION -U$USERNAME%$PASSWORD -I $SERVER_IP -p 139 -c quit $ADDARGS || failed=$(expr $failed + 1) +testit "smbclient //$SERVER/guestonly as anon" $SMBCLIENT //$SERVER/guestonly $CONFIGURATION -U% -I $SERVER_IP -p 139 -c quit $ADDARGS || failed=$(expr $failed + 1) +testit "smbclient //$SERVER/tmpguest as user" $SMBCLIENT //$SERVER/tmpguest $CONFIGURATION -U$USERNAME%$PASSWORD -I $SERVER_IP -p 139 -c quit $ADDARGS || failed=$(expr $failed + 1) +testit "smbclient //$SERVER/tmpguest as anon" $SMBCLIENT //$SERVER/tmpguest $CONFIGURATION -U% -I $SERVER_IP -p 139 -c quit $ADDARGS || failed=$(expr $failed + 1) +testit "smbclient //$SERVER/forceuser as user" $SMBCLIENT //$SERVER/forceuser $CONFIGURATION -U$USERNAME%$PASSWORD -I $SERVER_IP -p 139 -c quit $ADDARGS || failed=$(expr $failed + 1) +testit "smbclient //$SERVER/forceuser as anon" $SMBCLIENT //$SERVER/forceuser $CONFIGURATION -U% -I $SERVER_IP -p 139 -c quit $ADDARGS || failed=$(expr $failed + 1) +testit "smbclient //$SERVER/forceuser_unixonly as user" $SMBCLIENT //$SERVER/forceuser_unixonly $CONFIGURATION -U$USERNAME%$PASSWORD -I $SERVER_IP -p 139 -c quit $ADDARGS || failed=$(expr $failed + 1) +testit "smbclient //$SERVER/forceuser_wkngroup as user" $SMBCLIENT //$SERVER/forceuser_wkngroup $CONFIGURATION -U$USERNAME%$PASSWORD -I $SERVER_IP -p 139 -c quit $ADDARGS || failed=$(expr $failed + 1) +testit "smbclient //$SERVER/forcegroup as user" $SMBCLIENT //$SERVER/forcegroup $CONFIGURATION -U$USERNAME%$PASSWORD -I $SERVER_IP -p 139 -c quit $ADDARGS || failed=$(expr $failed + 1) +testit "smbclient //$SERVER/forcegroup as anon" $SMBCLIENT //$SERVER/forcegroup $CONFIGURATION -U% -I $SERVER_IP -p 139 -c quit $ADDARGS || failed=$(expr $failed + 1) +exit $failed diff --git a/source3/script/tests/test_smbclient_basic.sh b/source3/script/tests/test_smbclient_basic.sh new file mode 100755 index 0000000..6e2a17c --- /dev/null +++ b/source3/script/tests/test_smbclient_basic.sh @@ -0,0 +1,47 @@ +#!/bin/sh + +# this runs the file serving tests that are expected to pass with samba3 against shares with various options + +if [ $# -lt 5 ]; then + cat < +EOF + exit 1 +fi + +SERVER="$1" +SERVER_IP="$2" +USERNAME="$3" +PASSWORD="$4" +smbclient="$5" +CONFIGURATION="$6" +shift 6 +ADDARGS="$@" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +. $incdir/common_test_fns.inc + +# TEST using \ as the separator (default) +test_smbclient "smbclient as $DOMAIN\\$USERNAME" 'ls' "//$SERVER/tmp" -U$DOMAIN\\$USERNAME%$PASSWORD $ADDARGS || failed=$(expr $failed + 1) +# TEST using / as the separator (default) +test_smbclient "smbclient as $DOMAIN/$USERNAME" 'ls' "//$SERVER/tmp" -U$DOMAIN/$USERNAME%$PASSWORD $ADDARGS || failed=$(expr $failed + 1) + +# TEST using 'winbind separator = +' +test_smbclient "smbclient as $DOMAIN+$USERNAME" 'ls' "//$SERVER/tmp" -U$DOMAIN+$USERNAME%$PASSWORD $ADDARGS --option=winbindseparator=+ || failed=$(expr $failed + 1) + +# TEST using 'winbind separator = +' set in a config file +smbclient_config="$PREFIX/tmpsmbconf" +cat >$smbclient_config <$smbclient_config < +EOF + exit 1 +fi + +KRB5CCNAME=$1 +export KRB5CCNAME +SMBCLIENT3=$2 +SERVER=$3 +shift 3 +ADDARGS="$*" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +testit "smbclient" $VALGRIND $SMBCLIENT3 //$SERVER/tmp -c 'ls' --use-krb5-ccache=$KRB5CCNAME $ADDARGS || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_smbclient_large_file.sh b/source3/script/tests/test_smbclient_large_file.sh new file mode 100755 index 0000000..80816be --- /dev/null +++ b/source3/script/tests/test_smbclient_large_file.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +if [ $# -lt 1 ]; then + cat < +EOF + exit 1 +fi + +KRB5CCNAME=$1 +export KRB5CCNAME +SMBCLIENT3=$2 +SERVER=$3 +PREFIX=$4 +shift 4 +ADDARGS="$*" + +# Test that a noninteractive smbclient does not prompt +test_large_write_read() +{ + + cat >$PREFIX/largefile-script </dev/null 2>&1 + + if [ $? = 0 ]; then + true + else + echo did not get success message + false + fi +} + +rm -f $PREFIX/largefile +dd if=/dev/zero of=$PREFIX/largefile seek=$((20 * 1024 * 1024)) count=1 bs=1 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +testit "smbclient large posix write read" test_large_write_read || failed=$(expr $failed + 1) + +testit "cmp of read and written files" cmp $PREFIX/largefile $PREFIX/largefile2 || failed=$(expr $failed + 1) +rm -f $PREFIX/largefile2 + +testok $0 $failed diff --git a/source3/script/tests/test_smbclient_list_servers.sh b/source3/script/tests/test_smbclient_list_servers.sh new file mode 100755 index 0000000..237e82f --- /dev/null +++ b/source3/script/tests/test_smbclient_list_servers.sh @@ -0,0 +1,45 @@ +#!/bin/sh +# +# Ensure we don't get an error smb1cli_req_writev_submit: called for dialect[SMB3_11] +# when listing servers via -L. +# BUG: https://bugzilla.samba.org/show_bug.cgi?id=14939 + +if [ $# -lt 5 ]; then + cat < +EOF + exit 1 +fi + +SERVER="$1" +SMBCLIENT="$2" +PREFIX="$3" +shift 3 +ADDARGS="$*" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +LOG_DIR=$PREFIX/st_log_basename_dir + +test_smbclient_log_basename() +{ + rm -rf $LOG_DIR + mkdir $LOG_DIR + cmd='$VALGRIND $SMBCLIENT -l $LOG_DIR -d3 //$SERVER/IPC\$ $CONFIGURATION -U%badpassword -c quit $ADDARGS' + out=$(eval $cmd 2>&1) + grep 'Client started' $LOG_DIR/log.smbclient +} + +testit "smbclient log-basename" test_smbclient_log_basename || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_smbclient_machine_auth.sh b/source3/script/tests/test_smbclient_machine_auth.sh new file mode 100755 index 0000000..c89f848 --- /dev/null +++ b/source3/script/tests/test_smbclient_machine_auth.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +# this runs the file serving tests that are expected to pass with samba3 against shares with various options + +if [ $# -lt 2 ]; then + cat < +EOF + exit 1 +fi + +SERVER="$1" +SMBCLIENT="$2" +# This is used by test_smbclient() +# shellcheck disable=2034 +CONFIGURATION="${3}" +shift 3 +ADDARGS="$*" + +# This is used by test_smbclient() +# shellcheck disable=2034 +smbclient="${VALGRIND} ${SMBCLIENT}" + +incdir="$(dirname "${0}")/../../../testprogs/blackbox" +. "${incdir}/subunit.sh" +. "${incdir}/common_test_fns.inc" + +failed=0 + +test_smbclient "smbclient //${SERVER}/tmp" \ + "quit" "//${SERVER}/tmp" --machine-pass -p 139 "${ADDARGS}" || \ + failed=$((failed + 1)) + +# Testing these here helps because we know the machine account isn't already +# this user/group. +test_smbclient "smbclient //${SERVER}/forceuser" \ + "quit" "//${SERVER}/forceuser" --machine-pass -p 139 "${ADDARGS}" || \ + failed=$((failed + 1)) + +test_smbclient "smbclient //${SERVER}/forcegroup" \ + "quit" "//${SERVER}/forcegroup" --machine-pass -p 139 "${ADDARGS}" || \ + failed=$((failed + 1)) + +exit ${failed} diff --git a/source3/script/tests/test_smbclient_mget.sh b/source3/script/tests/test_smbclient_mget.sh new file mode 100755 index 0000000..5275d50 --- /dev/null +++ b/source3/script/tests/test_smbclient_mget.sh @@ -0,0 +1,47 @@ +#!/bin/sh + +if [ $# -lt 6 ]; then + cat < +EOF + exit 1 +fi + +SERVER="$1" +USERNAME="$2" +PASSWORD="$3" +MAPTOGUEST="$4" +SMBCLIENT="$5" +PROTOCOL="$6" +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +CONFIGURATION=${7} +shift 7 +ADDARGS="$*" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +if [ $PROTOCOL != "SMB3" -a $PROTOCOL != "NT1" ]; then + cat </dev/null 2>&1 + + if [ $? = 0 ]; then + # got a prompt .. fail + echo matched interactive prompt in non-interactive mode + return 1 + fi + + return 0 +} + +# Test that an interactive smbclient prompts to stdout +test_interactive_prompt_stdout() +{ + prompt="smb" + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + + cat >$tmpfile </dev/null 2>&1 + + if [ $? != 0 ]; then + echo failed to match interactive prompt on stdout + return 1 + fi + + return 0 +} + +# Test creating a bad symlink and deleting it. +test_bad_symlink() +{ + prompt="posix_unlink deleted file /newname" + tmpfile=$PREFIX/smbclient_bad_symlinks_commands + + cat >$tmpfile </dev/null 2>&1 + + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed create then delete bad symlink - grep failed with $ret" + return 1 + fi + + return 0 +} + +# Test creating a good symlink and deleting it by path. +test_good_symlink() +{ + tmpfile=$PREFIX/smbclient.in.$$ + slink_name="$LOCAL_PATH/slink" + slink_target="$LOCAL_PATH/slink_target" + + touch $slink_target + ln -s $slink_target $slink_name + cat >$tmpfile <$tmpfile </dev/null 2>&1 + + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed writing into read-only directory - grep failed with $ret" + return 1 + fi + + return 0 +} + +# Test sending a message +test_message() +{ + tmpfile=$PREFIX/message_in.$$ + + cat >$tmpfile <$tmpfile </dev/null 2>&1 + + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed reading owner-only file - grep failed with $ret" + return 1 + fi + + return 0 +} + +# Test accessing an msdfs path. +test_msdfs_link() +{ + tmpfile=$PREFIX/smbclient.in.$$ + prompt=" msdfs-target " + + cmd='$SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/msdfs-share -I $SERVER_IP $ADDARGS -m $PROTOCOL -c dir 2>&1' + out=$(eval $cmd) + ret=$? + + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing msfds-share\ with error $ret" + return 1 + fi + + cat >$tmpfile </dev/null 2>&1 + + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\msdfs-src1 - grep failed with $ret" + return 1 + fi + + cat >$tmpfile </dev/null 2>&1 + + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\deeppath\\msdfs-src2 - grep failed with $ret" + return 1 + fi + + return 0 +} + +# Test recursive listing across msdfs links +test_msdfs_recursive_dir() +{ + tmpfile=$PREFIX/smbclient.in.$$ + + cat >$tmpfile < /dev/null 2>&1 + + ret="$?" + if [ "$ret" -ne 0 ]; then + echo "$out" + echo "Listing \\msdfs-share recursively did not properly end in symlink recursion" + fi + + return 0 +} + +# Test doing a normal file rename on an msdfs path. +test_msdfs_rename() +{ + tmpfile="$PREFIX/smbclient.in.$$" + filename_src="src.$$" + filename_dst="dest.$$" + filename_src_path="$PREFIX/$filename_src" + rm -f "$filename_src_path" + touch "$filename_src_path" + + # + # Use both non-force and force rename to + # ensure we test both codepaths inside libsmb. + # + cat >$tmpfile </dev/null 2>&1 + + ret="$?" + if [ "$ret" -eq 0 ]; then + echo "$out" + echo "renaming $filename_src $filename_dst got NT_STATUS_ error" + return 1 + fi + return 0 +} + +# Test doing a normal file hardlink on an msdfs path. +test_msdfs_hardlink() +{ + tmpfile="$PREFIX/smbclient.in.$$" + filename_src="src.$$" + filename_dst="dest.$$" + filename_src_path="$PREFIX/$filename_src" + rm -f "$filename_src_path" + touch "$filename_src_path" + + cat >$tmpfile </dev/null 2>&1 + + ret="$?" + if [ "$ret" -eq 0 ]; then + echo "$out" + echo "hardlink $filename_src $filename_dst got NT_STATUS_ error" + return 1 + fi + return 0 +} + +test_msdfs_del() +{ + tmpfile="$PREFIX/smbclient.in.$$" + filename_src="src.$$" + filename_src_path="$PREFIX/$filename_src" + rm -f "$filename_src_path" + touch "$filename_src_path" + + cat > $tmpfile </dev/null 2>&1 + + ret="$?" + if [ "$ret" -eq 0 ] ; then + echo "$out" + echo "del $filename_src NT_STATUS_ error" + return 1 + fi + return 0 +} + +test_msdfs_deltree() +{ + tmpfile="$PREFIX/smbclient.in.$$" + dirname_src="foodir.$$" + filename_src="src.$$" + filename_src_path="$PREFIX/$filename_src" + dirname_src_path="$PREFIX/$dirname" + rm -f "$filename_src_path" + touch "$filename_src_path" + + cat > $tmpfile </dev/null 2>&1 + + ret="$?" + if [ "$ret" -eq 0 ] ; then + echo "$out" + echo "deltree $dirname_src NT_STATUS_ error" + return 1 + fi + return 0 +} + +# Archive bits are correctly set on file/dir creation and rename. +test_rename_archive_bit() +{ + prompt_file="attributes: A (20)" + prompt_dir="attributes: D (10)" + tmpfile="$PREFIX/smbclient.in.$$" + filename="foo.$$" + filename_ren="bar.$$" + dirname="foodir.$$" + dirname_ren="bardir.$$" + filename_path="$PREFIX/$filename" + local_name1="$LOCAL_PATH/$filename" + local_name2="$LOCAL_PATH/$filename_ren" + local_dir_name1="$LOCAL_PATH/$dirname" + local_dir_name2="$LOCAL_PATH/$dirname_ren" + + rm -f $filename_path + rm -f $local_name1 + rm -f $local_name2 + + # Create a new file, ensure it has 'A' attributes. + touch $filename_path + + cat >$tmpfile </dev/null 2>&1 + + ret=$? + + rm -f $filename_path + rm -f $local_name1 + rm -f $local_name2 + + if [ $ret != 0 ]; then + echo "$out" + echo "Attributes incorrect on new file $ret" + return 1 + fi + + # Now check if we remove 'A' and rename, the A comes back. + touch $filename_path + + cat >$tmpfile </dev/null 2>&1 + + ret=$? + + rm -f $filename_path + rm -f $local_name1 + rm -f $local_name2 + + if [ $ret != 0 ]; then + echo "$out" + echo "Attributes incorrect on renamed file $ret" + return 1 + fi + + rm -rf $local_dir_name1 + rm -rf $local_dir_name2 + + # Create a new directory, ensure it has 'D' but not 'A' attributes. + + cat >$tmpfile </dev/null 2>&1 + + ret=$? + + rm -rf $local_dir_name1 + rm -rf $local_dir_name2 + + if [ $ret != 0 ]; then + echo "$out" + echo "Attributes incorrect on new directory $ret" + return 1 + fi + + # Now check if we rename, we still only have 'D' attributes + + cat >$tmpfile </dev/null 2>&1 + + ret=$? + + rm -f $local_name1 + rm -f $local_name2 + + if [ $ret != 0 ]; then + echo "$out" + echo "Attributes incorrect on renamed directory $ret" + return 1 + fi + + return 0 +} + +# Test authenticating using the winbind ccache +test_ccache_access() +{ + $WBINFO --ccache-save="${USERNAME}%${PASSWORD}" + ret=$? + + if [ $ret != 0 ]; then + echo "wbinfo failed to store creds in cache (user='${USERNAME}', pass='${PASSWORD}')" + return 1 + fi + + $SMBCLIENT //$SERVER_IP/tmp --use-winbind-ccache -U "${USERNAME}" $ADDARGS -c quit 2>&1 + ret=$? + + if [ $ret != 0 ]; then + echo "smbclient failed to use cached credentials" + return 1 + fi + + $WBINFO --ccache-save="${USERNAME}%GarBage" + ret=$? + + if [ $ret != 0 ]; then + echo "wbinfo failed to store creds in cache (user='${USERNAME}', pass='GarBage')" + return 1 + fi + + $SMBCLIENT //$SERVER_IP/tmp --use-winbind-ccache -U "${USERNAME}" $ADDARGS -c quit 2>&1 + ret=$? + + if [ $ret -eq 0 ]; then + echo "smbclient succeeded with wrong cached credentials" + return 1 + fi + + $WBINFO --logoff +} + +# Test authenticating using the winbind ccache +test_auth_file() +{ + tmpfile=$PREFIX/smbclient.in.$$ + cat >$tmpfile <&1 + ret=$? + rm $tmpfile + + if [ $ret != 0 ]; then + echo "smbclient failed to use auth file" + return 1 + fi + + cat >$tmpfile <&1 + ret=$? + rm $tmpfile + + if [ $ret -eq 0 ]; then + echo "smbclient succeeded with wrong auth file credentials" + return 1 + fi +} + +# Test doing a directory listing with backup privilege. +test_backup_privilege_list() +{ + tmpfile=$PREFIX/smbclient_backup_privilege_list + + # selftest uses the forward slash as a separator, but "net sam rights + # grant" requires the backslash separator + USER_TMP=$(printf '%s' "$USERNAME" | tr '/' '\\') + + # If we don't have a DOMAIN component to the username, add it. + printf '%s' "$USER_TMP" | grep '\\' 2>&1 + ret=$? + if [ $ret != 0 ]; then + priv_username="$DOMAIN\\$USER_TMP" + else + priv_username="$USER_TMP" + fi + + $NET sam rights grant $priv_username SeBackupPrivilege 2>&1 + ret=$? + if [ $ret != 0 ]; then + echo "Failed to add SeBackupPrivilege to user $priv_username - $ret" + return 1 + fi + + cat >$tmpfile <&1 + ret=$? + if [ $ret != 0 ]; then + echo "failed to remove SeBackupPrivilege from user $priv_username - $ret" + return 1 + fi +} + +# Test accessing an share with bad names (won't convert). +test_bad_names() +{ + # First with SMB1 + + if [ $PROTOCOL = "NT1" ]; then + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/badname-tmp -I $SERVER_IP $ADDARGS -m$PROTOCOL -c ls 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + + if [ $ret != 0 ]; then + echo "$out" + echo "failed accessing badname-tmp (SMB1) with error $ret" + return 1 + fi + + echo "$out" | wc -l 2>&1 | grep 5 + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\badname-tmp - grep of number of lines (1) failed with $ret" + return 1 + fi + + echo "$out" | grep '^ \. *D' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\badname-tmp - grep (1) failed with $ret" + return 1 + fi + + echo "$out" | grep '^ \.\. *D' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\badname-tmp - grep (2) failed with $ret" + return 1 + fi + + echo "$out" | grep '^ blank.txt *N' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\badname-tmp - grep (3) failed with $ret" + return 1 + fi + + echo "$out" | grep '^ *$' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\badname-tmp - grep (4) failed with $ret" + return 1 + fi + + echo "$out" | grep 'blocks of size.*blocks available' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\badname-tmp - grep (5) failed with $ret" + return 1 + fi + fi + + if [ $PROTOCOL = "SMB3" ]; then + + # Now check again with -mSMB3 + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/badname-tmp -I $SERVER_IP $ADDARGS -m$PROTOCOL -c ls 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + + if [ $ret != 0 ]; then + echo "$out" + echo "failed accessing badname-tmp (SMB3) with error $ret" + return 1 + fi + + echo "$out" | wc -l 2>&1 | grep 5 + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\badname-tmp - SMB3 grep of number of lines (1) failed with $ret" + return 1 + fi + + echo "$out" | grep '^ \. *D' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\badname-tmp - SMB3 grep (1) failed with $ret" + return 1 + fi + + echo "$out" | grep '^ \.\. *D' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\badname-tmp - SMB3 grep (2) failed with $ret" + return 1 + fi + + echo "$out" | grep '^ blank.txt *N' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\badname-tmp - SMB3 grep (3) failed with $ret" + return 1 + fi + + echo "$out" | grep '^ *$' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\badname-tmp - SMB3 grep (4) failed with $ret" + return 1 + fi + + echo "$out" | grep 'blocks of size.*blocks available' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\badname-tmp - SMB3 grep (5) failed with $ret" + return 1 + fi + fi +} + +# Test accessing an share with a name that must be mangled - with acl_xattrs. +# We know foo:bar gets mangled to FF4GBY~Q with the default name-mangling algorithm (hash2). +test_mangled_names() +{ + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + cat >$tmpfile <$tmpfile <$tmpfile <$tmpfile <$tmpfile <$tmpfile <$tmpfile <$PREFIX/$local_nosymlink_target_file + + local_foobar_target_file="testfile" + echo "$share_target_file" >$PREFIX/$local_foobar_target_file + + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + cat >$tmpfile <$tmpfile <$tmpfile <$tmpfile <$tmpfile <$tmpfile <$tmpfile <$tmpfile <$tmpfile <$tmpfile <$tmpfile <$tmpfile <$tmpfile <$tmpfile <$tmpfile <$tmpfile <$tmpfile <$tmpfile <$tmpfile </dev/null 2>&1 + if [ $? != 0 ]; then + # didn't get output to stdout + echo "expected output was NOT output to stdout" + return 1 + fi + + # this time execute ls but redirect stdout alone to /dev/null + cmd='$SMBCLIENT -E "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -c "ls" 2>&1 > /dev/null' + eval echo "$cmd" + out=$(eval $cmd) + if [ $? != 0 ]; then + echo "$out" + echo "command failed" + return 1 + fi + + # test smbclient 'ls' command output went to stderr + echo "$out" | grep "blocks available" >/dev/null 2>&1 + if [ $? != 0 ]; then + # didn't get output to stderr + echo "expected output was NOT output to stderr" + return 1 + fi + + return 0 + +} + +# +# +LOGDIR_PREFIX=test_smbclient_s3 + +# possibly remove old logdirs: + +for OLDDIR in $(find ${PREFIX} -type d -name "${LOGDIR_PREFIX}_*"); do + echo "removing old directory ${OLDDIR}" + rm -rf ${OLDDIR} +done + +LOGDIR=$(mktemp -d ${PREFIX}/${LOGDIR_PREFIX}_XXXXXX) + +testit "smbclient -L $SERVER_IP" $SMBCLIENT -L $SERVER_IP -N -p 139 ${RAWARGS} || failed=$(expr $failed + 1) +testit "smbclient -L $SERVER -I $SERVER_IP" $SMBCLIENT -L $SERVER -I $SERVER_IP -N -p 139 ${RAWARGS} -c quit || failed=$(expr $failed + 1) + +testit "noninteractive smbclient does not prompt" \ + test_noninteractive_no_prompt || + failed=$(expr $failed + 1) + +testit "noninteractive smbclient -l does not prompt" \ + test_noninteractive_no_prompt -l $LOGDIR || + failed=$(expr $failed + 1) + +testit "smbclient output goes to stderr when -E is passed" \ + test_smbclient_minus_e_stderr || + failed=$(expr $failed + 1) + +testit "interactive smbclient prompts on stdout" \ + test_interactive_prompt_stdout || + failed=$(expr $failed + 1) + +testit "interactive smbclient -l prompts on stdout" \ + test_interactive_prompt_stdout -l $LOGDIR || + failed=$(expr $failed + 1) + +testit "creating a bad symlink and deleting it" \ + test_bad_symlink || + failed=$(expr $failed + 1) + +testit "creating a good symlink and deleting it by path" \ + test_good_symlink || + failed=$(expr $failed + 1) + +testit "writing into a read-only directory fails" \ + test_read_only_dir ro-tmp || + failed=$(expr $failed + 1) + +testit "writing into a read-only share fails" \ + test_read_only_dir valid-users-tmp || + failed=$(expr $failed + 1) + +testit "Reading a owner-only file fails" \ + test_owner_only_file || + failed=$(expr $failed + 1) + +testit "Accessing an MS-DFS link" \ + test_msdfs_link || + failed=$(expr $failed + 1) + +testit "Recursive ls across MS-DFS links" \ + test_msdfs_recursive_dir || + failed=$(expr $failed + 1) + +testit "Rename on MS-DFS share" \ + test_msdfs_rename || + failed=$(expr $failed + 1) + +testit "Hardlink on MS-DFS share" \ + test_msdfs_hardlink || + failed=$(expr $failed + 1) + +testit "del on MS-DFS share" \ + test_msdfs_del || \ + failed=`expr $failed + 1` + +testit "deltree on MS-DFS share" \ + test_msdfs_deltree || \ + failed=`expr $failed + 1` + +testit "Ensure archive bit is set correctly on file/dir rename" \ + test_rename_archive_bit || + failed=$(expr $failed + 1) + +testit "ccache access works for smbclient" \ + test_ccache_access || + failed=$(expr $failed + 1) + +testit "sending a message to the remote server" \ + test_message || + failed=$(expr $failed + 1) + +testit "using an authentication file" \ + test_auth_file || + failed=$(expr $failed + 1) + +testit "list with backup privilege" \ + test_backup_privilege_list || + failed=$(expr $failed + 1) + +testit "list a share with bad names (won't convert)" \ + test_bad_names || + failed=$(expr $failed + 1) + +testit "list a share with a mangled name + acl_xattr object" \ + test_mangled_names || + failed=$(expr $failed + 1) + +testit "server-side file copy" \ + test_scopy || + failed=$(expr $failed + 1) + +testit "creating a :stream at root of share" \ + test_toplevel_stream || + failed=$(expr $failed + 1) + +testit "Ensure widelinks are restricted" \ + test_widelinks || + failed=$(expr $failed + 1) + +testit "streams_depot can delete correctly" \ + test_streams_depot_delete || + failed=$(expr $failed + 1) + +testit "stream_xattr attributes" \ + test_stream_directory_xattr || + failed=$(expr $failed + 1) + +testit "follow symlinks = no" \ + test_nosymlinks || + failed=$(expr $failed + 1) + +testit "follow local symlinks" \ + test_local_symlinks || + failed=$(expr $failed + 1) + +testit "noperm share regression" \ + test_noperm_share_regression || + failed=$(expr $failed + 1) + +testit "smbclient deltree command" \ + test_deltree || + failed=$(expr $failed + 1) + +testit "server os message" \ + test_server_os_message || + failed=$(expr $failed + 1) + +testit "test server quiet message" \ + test_server_quiet_message || + failed=$(expr $failed + 1) + +testit "setmode test" \ + test_setmode || + failed=$(expr $failed + 1) + +testit "utimes" \ + test_utimes || + failed=$(expr $failed + 1) + +testit "rename_dotdot" \ + test_rename_dotdot || + failed=$(expr $failed + 1) + +testit "volume" \ + test_volume || + failed=$(expr $failed + 1) + +testit "rm -rf $LOGDIR" \ + rm -rf $LOGDIR || + failed=$(expr $failed + 1) + +testit "delete a non empty directory" \ + test_del_nedir || + failed=$(expr $failed + 1) + +testit "valid users" \ + test_valid_users || + failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_smbclient_tarmode.pl b/source3/script/tests/test_smbclient_tarmode.pl new file mode 100755 index 0000000..fa69d28 --- /dev/null +++ b/source3/script/tests/test_smbclient_tarmode.pl @@ -0,0 +1,1723 @@ +#!/usr/bin/perl +# Unix SMB/CIFS implementation. +# Test suite for the tar backup mode of smbclient. +# Copyright (C) Aurélien Aptel 2013 + +# 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 . + +=head1 NAME + +C - Test for smbclient tar backup feature + +=cut + +use v5.10; +use strict; +use warnings; + +use Archive::Tar; +use Data::Dumper; +use Digest::MD5 qw/md5_hex/; +use File::Path qw/make_path remove_tree/; +use File::Spec; +use File::Temp; +use Getopt::Long; +use Pod::Usage; +use Term::ANSIColor; + +sub d {print Dumper @_;} + +# DEFAULTS +# 'our' to make them available in the File package +our $USER = ''; +our $PW = ''; +our $HOST = ''; +our $IP = ''; +our $SHARE = ''; +our $DIR = 'tar_test_dir'; +our $LOCALPATH = ''; +our $TMP = File::Temp->newdir(); +our $BIN = 'smbclient'; +our $SUBUNIT = 0; + +my $SELECTED_TEST = ''; +my $LIST_TEST = 0; + +my @SMBARGS = (); + +our $DEBUG = 0; +our $VERBOSE = 0; +my $MAN = 0; +my $HELP = 0; +my $CLEAN = 0; + +# all tests +my @TESTS = ( +# ['test helper', \&test_helper], + ['create, normal files (no attributes)', \&test_creation_normal, 'normal'], + ['create, normal nested files (no attributes)', \&test_creation_normal, 'nested'], + ['create, normal files (interactive)', \&test_creation_normal, 'inter'], + ['create, large file', \&test_creation_large_file], + ['create, long path', \&test_creation_long_path], + ['create, incremental with -g', \&test_creation_incremental, '-g'], + ['create, incremental with tarmode', \&test_creation_incremental, 'tarmode inc'], + ['create, reset archived files with -a', \&test_creation_reset, '-a'], + ['create, reset archived files with tarmode', \&test_creation_reset, 'tarmode reset'], + ['create, files newer than a file', \&test_creation_newer], + ['create, combination of tarmode filter', \&test_creation_attr], + ['create, explicit include', \&test_creation_include], + ['create, explicit exclude', \&test_creation_exclude], + ['create, include w/ filelist (F)', \&test_creation_list], + ['create, wildcard simple', \&test_creation_wildcard_simple], + ['create, regex', \&test_creation_regex], + ['create, multiple backup in session', \&test_creation_multiple], + ['extract, normal files', \&test_extraction_normal], + ['extract, explicit include', \&test_extraction_include], + ['extract, explicit exclude', \&test_extraction_exclude], + ['extract, include w/ filelist (F)', \&test_extraction_list], + ['extract, regex', \&test_extraction_regex], +); + +=head1 SYNOPSIS + + test_smbclient_tarmode.pl [options] -- [smbclient options] + + Options: + -h, --help brief help message + --man full documentation + + Environment: + -u, --user USER + -p, --password PW + -n, --name HOST (required) + -i, --ip IP + -s, --share SHARE (required) + -d, --dir PATH + sub-path to use on the share + + -l, --local-path PATH (required) + path to the root of the samba share on the machine. + + -b, --bin BIN + path to the smbclient binary to use + + Test: + --list + list tests + + --test N + --test A-B + --test A,B,D-F + only run certain tests (accept list and intervals of numbers) + + -v, --verbose + be more verbose + + --debug + print command and their output (also set -v) + + --subunit + print output in subunit format + +=cut + +GetOptions('u|user=s' => \$USER, + 'p|password=s' => \$PW, + 'n|name=s' => \$HOST, + 'i|ip=s' => \$IP, + 's|share=s' => \$SHARE, + 'd|dir=s' => \$DIR, + 'l|local-path=s' => \$LOCALPATH, + 'b|bin=s' => \$BIN, + + 'test=s' => \$SELECTED_TEST, + 'list' => \$LIST_TEST, + + 'clean' => \$CLEAN, + 'subunit' => \$SUBUNIT, + 'debug' => \$DEBUG, + 'v|verbose' => \$VERBOSE, + 'h|help' => \$HELP, + 'man' => \$MAN) or pod2usage(2); + +pod2usage(0) if $HELP; +pod2usage(-exitval => 0, -verbose => 2) if $MAN; +list_test(), exit 0 if $LIST_TEST; +pod2usage(1) unless $HOST; +pod2usage(1) unless $SHARE; +pod2usage(1) unless $LOCALPATH; + +if ($USER xor $PW) { + die "Need both user and password when one is provided\n"; +} +elsif ($USER and $PW) { + push @SMBARGS, '-U'.$USER.'%'.$PW; +} +else { + push @SMBARGS, '-N'; +} + +if ($IP) { + push @SMBARGS, '-I', $IP; +} + +# remaining arguments are passed to smbclient +push @SMBARGS, @ARGV; + +# path to store the downloaded tarball +my $TAR = "$TMP/tarmode.tar"; + +##### + +# SANITIZATION + +# remove all final slashes from input paths +$LOCALPATH =~ s{[/\\]+$}{}g; +$SHARE =~ s{[/\\]+$}{}g; +$HOST =~ s{[/\\]+$}{}g; +$DIR =~ s{^\.[/\\]+$}{}g; +$DIR =~ s{[/\\]+$}{}g; + +if (!-d $LOCALPATH) { + die "Local path '$LOCALPATH' is not a directory.\n"; +} + +if ($CLEAN) { + # clean the whole root first + remove_tree($LOCALPATH, { keep_root => 1 }); +} + +if ($DEBUG) { + $VERBOSE = 1; +} + +##### + +# RUN TESTS + +my @selection = parse_test_string($SELECTED_TEST); + +if ($SELECTED_TEST eq '') { + run_test(@TESTS); +} elsif (@selection > 0) { + run_test(@selection); +} else { + die "Test selection '$SELECTED_TEST' is invalid\n"; +} + +################################# + +=head1 DOCUMENTATION + +=head2 Defining a test + +=over + +=item * Create a function C + +=item * Use the File module, documented below + +=item * Use C, C, C or C + +=item * Return number of error + +=item * Add function to C<@TESTS> + +=back + +The function must be placed in the C<@TESTS> list along with a short +description and optional arguments. + +=cut + +sub test_creation_newer { + my @files; + my $dt = 3000; + + # create oldest file at - DT + my $oldest = File->new_remote('oldest'); + $oldest->set_time(time - $dt); + + # create limit file + my $limit = File->new_local("$TMP/limit"); + + # create newA file at + DT + my $newA = File->new_remote('newA'); + $newA->set_time(time + $dt); + + # create newB file at + DT + my $newB = File->new_remote('newB'); + $newB->set_time(time + $dt); + + # get files newer than limit_file + push @files, $newA, $newB; + + smb_tar('', '-TcN', $limit->localpath, $TAR, $DIR); + return check_tar($TAR, \@files); +} + +sub test_creation_attr { + my @attr = qw/r h s a/; + my @all; + my @inc; + my $err = 0; + + # one normal file + my $f = File->new_remote("file-n.txt"); + push @all, $f; + + # combinations of attributes + for my $n (1..@attr) { + for (combine(\@attr, $n)) { + my @t = @$_; + my $fn = "file-" . join('+', @t) . ".txt"; + my $f = File->new_remote($fn); + $f->set_attr(@t); + push @all, $f; + } + } + + @inc = grep { !$_->attr('s') } @all; + smb_tar('tarmode nosystem', '-Tc', $TAR, $DIR); + $err += check_tar($TAR, \@inc); + + @inc = grep { !$_->attr('h') } @all; + smb_tar('tarmode nohidden', '-Tc', $TAR, $DIR); + $err += check_tar($TAR, \@inc); + + @inc = grep { !$_->attr_any('h', 's') } @all; + smb_tar('tarmode nohidden nosystem', '-Tc', $TAR, $DIR); + $err += check_tar($TAR, \@inc); + + @inc = grep { $_->attr('a') && !$_->attr_any('h', 's') } @all; + smb_tar('tarmode inc nohidden nosystem', '-Tc', $TAR, $DIR); + $err += check_tar($TAR, \@inc); + # adjust attr so remote files can be deleted with deltree + File::walk(sub { $_->set_attr(qw/n r s h/) }, File::tree($DIR)); + + $err; +} + +sub test_creation_reset { + my ($mode) = @_; + + my @files; + my $n = 3; + for (1..$n) { + my $f = File->new_remote("file-$_"); + $f->set_attr('a'); + push @files, $f; + } + + if ($mode =~ /reset/) { + smb_tar('tarmode full reset', '-Tc', $TAR, $DIR); + } else { + smb_tar('', '-Tca', $TAR, $DIR); + } + + my $err = check_tar($TAR, \@files); + return $err if ($err > 0); + + for my $f (File::list($DIR)) { + if ($f->{attr}{a}) { + printf " ! %s %s\n", $f->attr_str, $f->remotepath; + $err++; + } + } + return $err; +} + +sub test_creation_large_file { + my $size = int(15e6); # 15MB + my $f = File->new_remote("fat.jpg", 0, $size); + + smb_tar('', '-Tc', $TAR, $DIR); + return check_tar($TAR, [$f]); +} + +sub test_creation_long_path { + my $d = "a"x130; + my @all; + + for (qw( foo/a bar/b )) { + push @all, File->new_remote("$d/$_"); + } + + smb_tar('', '-Tc', $TAR, $DIR); + return check_tar($TAR, \@all); +} + +sub test_creation_normal { + my ($mode) = @_; + + my $prefix = ($mode =~ /nest/) ? "/foo/bar/bar/" : ''; + my @files; + my $n = 5; + for (1..$n) { + my $f = File->new_remote($prefix."file-$_"); + push @files, $f; + } + + if ($mode =~ /inter/) { + smb_tar("tar c $TAR $DIR", ''); + } else { + smb_tar('tarmode full', '-Tc', $TAR, $DIR); + } + return check_tar($TAR, \@files); +} + +sub test_creation_incremental { + my ($mode) = @_; + + my @files; + my $n = 10; + for (1..$n) { + my $f = File->new_remote("file-$_"); + + # set archive bit on ~half of them + if ($_ < $n/2) { + $f->set_attr('a'); + push @files, $f; + } + else { + $f->set_attr((qw/n r s h/)[$_ % 4]); + } + } + + if ($mode =~ /inc/) { + smb_tar('tarmode inc', '-Tc', $TAR, $DIR); + } else { + smb_tar('', '-Tcg', $TAR, $DIR); + } + my $res = check_tar($TAR, \@files); + # adjust attr so remote files can be deleted with deltree + File::walk(sub { $_->set_attr(qw/n r s h/) }, File::tree($DIR)); + return $res +} + + +sub test_extraction_normal { + my @files; + my $n = 5; + for (1..$n) { + my $f = File->new_remote("file-$_"); + push @files, $f; + } + + # store + smb_tar('', '-Tc', $TAR, $DIR); + my $err = check_tar($TAR, \@files); + return $err if $err > 0; + + reset_remote(); + + smb_tar('', '-Tx', $TAR); + check_remote($DIR, \@files); +} + +sub test_extraction_include { + my @all_files; + my @inc_files; + + for (qw(file_inc inc/b inc/c inc/dir/foo dir_ex/d zob)) { + my $f = File->new_remote($_); + push @all_files, $f; + push @inc_files, $f if /inc/; + } + + # store + smb_tar('', '-Tc', $TAR, $DIR); + my $err = check_tar($TAR, \@all_files); + return $err if $err > 0; + + reset_remote(); + + smb_tar('', '-TxI', $TAR, "$DIR/file_inc", "$DIR/inc"); + check_remote($DIR, \@inc_files); +} + +sub test_extraction_exclude { + my @all_files; + my @inc_files; + + for (qw(file_exc exc/b exc/c exc/dir/foo dir_ex/d zob)) { + my $f = File->new_remote($_); + push @all_files, $f; + push @inc_files, $f if !/exc/; + } + + # store + smb_tar('', '-Tc', $TAR, $DIR); + my $err = check_tar($TAR, \@all_files); + return $err if $err > 0; + + reset_remote(); + + smb_tar('', '-TxX', $TAR, "$DIR/file_exc", "$DIR/exc"); + check_remote($DIR, \@inc_files); +} + + +sub test_creation_include { + my @files; + + for (qw(file_inc inc/b inc/c inc/dir/foo dir_ex/d zob)) { + my $f = File->new_remote($_); + push @files, $f if /inc/; + } + + smb_tar('', '-TcI', $TAR, "$DIR/file_inc", "$DIR/inc"); + return check_tar($TAR, \@files); +} + +sub test_creation_exclude { + my @files; + + for (qw(file_ex ex/b ex/c ex/dir/foo foo/bar zob)) { + my $f = File->new_remote($_); + push @files, $f if !/ex/; + } + + smb_tar('', '-TcX', $TAR, "$DIR/file_ex", "$DIR/ex"); + return check_tar($TAR, \@files); +} + +sub test_creation_list { + my @inc_files; + + for (qw(file_inc inc/b inc/c inc/dir/foo foo/bar zob)) { + my $f = File->new_remote($_); + push @inc_files, $f if /inc/; + } + + my $flist = File->new_local("$TMP/list", file_list(@inc_files)); + smb_tar('', '-TcF', $TAR, $flist->localpath); + return check_tar($TAR, \@inc_files); +} + +sub test_creation_regex { + my @exts = qw(jpg exe); + my @dirs = ('', "$DIR/"); + my @all = make_env(\@exts, \@dirs); + my $nb; + my @inc; + my $err = 0; + + # EXCLUSION + + # skip *.exe + @inc = grep { $_->remotepath !~ m{exe$} } @all; + smb_tar('', '-TcrX', $TAR, '*.exe'); + $err += check_tar($TAR, \@inc); + + # if the pattern is a path, it doesn't skip anything + smb_tar('', '-TcrX', $TAR, "$DIR/*.exe"); + $err += check_tar($TAR, \@all); + smb_tar('', '-TcrX', $TAR, "$DIR/*"); + $err += check_tar($TAR, \@all); + smb_tar('', '-TcrX', $TAR, "$DIR"); + $err += check_tar($TAR, \@all); + + # no paths => include everything + smb_tar('', '-TcrX', $TAR); + $err += check_tar($TAR, \@all); + + + # skip everything + smb_tar('', '-TcrX', $TAR, "*.*"); + $err += check_tar($TAR, []); + smb_tar('', '-TcrX', $TAR, "*"); + $err += check_tar($TAR, []); + + # INCLUSION + + # no paths => include everything + smb_tar('', '-Tcr', $TAR); + $err += check_tar($TAR, \@all); + + # include everything + smb_tar('', '-Tcr', $TAR, '*'); + $err += check_tar($TAR, \@all); + + # include only .exe at root + @inc = grep { $_->remotepath =~ m{^[^/]+exe$}} @all; + smb_tar('', '-Tcr', $TAR, '*.exe'); + $err += check_tar($TAR, \@inc); + + # smb_tar('', '-Tcr', $TAR, "$DIR/*"); + ## in old version (bug?) + # $err += check_tar($TAR, []); + ## in rewrite + # @inc = grep { $_->remotepath =~ /^$DIR/ } @all; + # $err += check_tar($TAR, \@inc); + + $err; +} + +sub test_creation_wildcard_simple { + my @exts = qw(jpg exe); + my @dirs = ('', "$DIR/"); + my @all = make_env(\@exts, \@dirs); + my $nb; + my @inc; + my $err = 0; + + @inc = grep { $_->remotepath =~ m{^[^/]+exe$} } @all; + smb_tar('', '-Tc', $TAR, "*.exe"); + $err += check_tar($TAR, \@inc); + + @inc = grep { $_->remotepath =~ m{$DIR/.+exe$} } @all; + smb_tar('', '-Tc', $TAR, "$DIR/*.exe"); + $err += check_tar($TAR, \@inc); + + $err; +} + +# NOT USED +# helper to test tests +sub test_helper { + my @exts = qw(txt jpg exe); + my @dirs = ('', "$DIR/", "$DIR/dir/"); + my @all = make_env(\@exts, \@dirs); + my $nb; + my $err = 0; + my @inc; + + smb_tar('', '-Tc', $TAR); + return 1 if check_tar($TAR, \@all); + reset_remote(); + + my @exc = grep { $_->remotepath =~ m!/dir/.+exe!} @all; + @inc = grep { $_->remotepath !~ m!/dir/.+exe!} @all; + smb_tar('', '-TxXr', $TAR, "/$DIR/dir/*.exe"); + $err += check_remote('/', \@all); # BUG: should be \@inc + reset_remote(); + + return 0; +} + +sub test_creation_multiple { + my @exts = qw(jpg exe); + my @dirs = ('', "$DIR/"); + my @all = make_env(\@exts, \@dirs); + my $nb; + my @inc; + my $err = 0; + + my ($tarA, $tarB) = ("$TMP/a.tar", "$TMP/b.tar"); + my @incA = grep { $_->remotepath =~ m{^[^/]+exe$} } @all; + my @incB = grep { $_->remotepath =~ m{^[^/]+jpg$} } @all; + + my $flistA = File->new_local("$TMP/listA", file_list(@incA))->localpath; + my $flistB = File->new_local("$TMP/listB", file_list(@incB))->localpath; + + smb_tar("tar cF $tarA $flistA ; tar cF $tarB $flistB ; quit"); + $err += check_tar($tarA, \@incA); + $err += check_tar($tarB, \@incB); + + $err; +} + +sub test_extraction_regex { + my @exts = qw(txt jpg exe); + my @dirs = ('', "$DIR/", "$DIR/dir/"); + my @all = make_env(\@exts, \@dirs); + my $nb; + my $err = 0; + my (@inc, @exc); + + smb_tar('', '-Tc', $TAR); + return 1 if check_tar($TAR, \@all); + reset_remote(); + + # INCLUDE + + # only include file at root + @inc = grep { $_->remotepath =~ m!exe!} @all; + smb_tar('', '-Txr', $TAR, "*.exe"); + $err += check_remote('/', \@inc); + reset_remote(); + + @inc = grep { $_->remotepath =~ m!/dir/.+exe!} @all; + smb_tar('', '-Txr', $TAR, "/$DIR/dir/*.exe"); + $err += check_remote('/', []); # BUG: should be \@inc + reset_remote(); + + # EXCLUDE + + # exclude file not directly at root + @inc = grep { $_->remotepath =~ m!^[^/]+$!} @all; + @exc = grep { $_->remotepath !~ m!^[^/]+$!} @all; + smb_tar('', '-TxrX', $TAR, map {$_->remotepath} @exc); + $err += check_remote('/', \@all); # BUG: should be @inc... + reset_remote(); + + # exclude only $DIR/dir/*exe + @exc = grep { $_->remotepath =~ m!/dir/.+exe!} @all; + @inc = grep { $_->remotepath !~ m!/dir/.+exe!} @all; + smb_tar('', '-TxXr', $TAR, "/$DIR/dir/*.exe"); + $err += check_remote('/', \@all); # BUG: should be \@inc + reset_remote(); + + $err; +} + +sub test_extraction_wildcard { + my @exts = qw(txt jpg exe); + my @dirs = ('', "$DIR/", "$DIR/dir/"); + my $nb; + my $err = 0; + + for my $dir (@dirs) { + + my @all; + + $nb = 0; + for my $dir (@dirs) { + for (@exts) { + my $fn = $dir . "file$nb." . $_; + my $f = File->new_remote($fn, 'ABSPATH'); + $f->delete_on_destruction(1); + push @all, $f; + $nb++; + } + } + + + my @inc; + my $ext = 'exe'; + my $fn = $dir."file$nb.".$ext; + my $pattern = $dir.'*.'.$ext; + my $flist; + + # with F + + $flist = File->new_local("$TMP/list", "$pattern\n"); + + # store + my $re = '^'.$dir.'.*file'; + @inc = grep { $dir eq '' or $_->remotepath =~ m{$re} } @all; + smb_tar('', '-Tc', $TAR, $dir); + $err += check_tar($TAR, \@inc); + + reset_remote(); + my $re2 = '^'.$dir.'file.+exe'; + @inc = grep { $_->remotepath =~ /$re2/ } @all; + smb_tar('', '-TxrF', $TAR, $flist->localpath); + $err += check_remote($dir, \@inc); + + reset_remote(); + } + + $err; +} + +sub test_extraction_list { + my @inc_files; + my @all_files; + + for (qw(file_inc inc/b inc/c inc/dir/foo foo/bar zob)) { + my $f = File->new_remote($_); + push @all_files, $f; + push @inc_files, $f if /inc/; + } + + # store + smb_tar('', '-Tc', $TAR, $DIR); + my $err = check_tar($TAR, \@all_files); + return $err if $err > 0; + + reset_remote(); + + my $flist = File->new_local("$TMP/list", file_list(@inc_files)); + smb_tar('', '-TxF', $TAR, $flist->localpath); + return check_remote($DIR, \@inc_files); +} + +################################# + +# IMPLEMENTATION + +=head2 Useful functions + +Here are a list of useful functions and helpers to define tests. + +=cut + +# list test number and description +sub list_test { + my $i = 0; + for (@TESTS) { + my ($desc, $f, @args) = @$_; + printf "%2d.\t%s\n", $i++, $desc; + } +} + +sub run_test { + if ($SUBUNIT) { + run_test_subunit(@_); + } else { + run_test_normal(@_); + } +} + +sub run_test_normal { + for (@_) { + my ($desc, $f, @args) = @$_; + my $err; + + reset_env(); + say "TEST: $desc"; + if ($VERBOSE) { + $err = $f->(@args); + } else { + # turn off STDOUT + open my $saveout, ">&STDOUT"; + open STDOUT, '>', File::Spec->devnull(); + $err = $f->(@args); + open STDOUT, ">&", $saveout; + } + print_res($err); + print "\n"; + } + reset_env(); +} + +sub run_test_subunit { + for (@_) { + my ($desc, $f, @args) = @$_; + my $err; + my $str = ''; + + reset_env(); + say "test: $desc"; + + # capture output in $buf + my $buf = ''; + open my $handle, '>', \$buf; + select $handle; + + # check for die() calls + eval { + $err = $f->(@args); + }; + if ($@) { + $str = $@; + $err = 1; + } + close $handle; + + # restore output + select STDOUT; + + # result string is output + eventual exception message + $str = $buf.$str; + + printf "%s: %s [\n%s]\n", ($err > 0 ? "failure" : "success"), $desc, $str; + } + reset_env(); +} + +sub parse_test_string { + my $s = shift; + my @tests = (); + + if (!length($s)) { + return (); + } + + for (split /,/, $s) { + if (/^\d+$/) { + if ($_ >= @TESTS) { + return (); + } + push @tests, $TESTS[$_]; + } + elsif (/^(\d+)-(\d+)$/) { + my ($min, $max) = sort ($1, $2); + if ($max >= @TESTS) { + return (); + } + + for ($min..$max) { + push @tests, $TESTS[$_]; + } + } + else { + return (); + } + } + + return @tests; +} + +sub print_res { + my $err = shift; + if ($err) { + printf " RES: %s%d ERR%s\n", color('bold red'), $err, color 'reset'; + } else { + printf " RES: %sOK%s\n", color('bold green'), color 'reset'; + } +} + +sub make_env { + my ($exts, $dirs) = @_; + my @all; + my $nb = 0; + for my $dir (@$dirs) { + for (@$exts) { + my $fn = $dir . "file$nb." . $_; + my $f = File->new_remote($fn, 'ABSPATH'); + $f->delete_on_destruction(1); + push @all, $f; + $nb++; + } + } + + @all; +} + +=head3 C + +=head3 C + +Return a list of all possible I-uplet (or combination of C<$n> element) of C<@set>. + +=cut +sub combine { + my ($list, $n) = @_; + die "Insufficient list members" if $n > @$list; + + return map [$_], @$list if $n <= 1; + + my @comb; + + for (my $i = 0; $i+$n <= @$list; $i++) { + my $val = $list->[$i]; + my @rest = @$list[$i+1..$#$list]; + push @comb, [$val, @$_] for combine(\@rest, $n-1); + } + + return @comb; +} + + +=head3 C + +Remove all files in the server C<$DIR> (not root) + +=cut +sub reset_remote { + # remove_tree($LOCALPATH . '/'. $DIR); + # make_path($LOCALPATH . '/'. $DIR); + my $DIR; + my @names; + my $name; + + smb_client_cmd(0, '-c', "deltree ./*"); + + # Ensure all files are gone. + + opendir(DIR,$LOCALPATH) or die "Can't open $LOCALPATH\n"; + @names = readdir(DIR) or die "Unable to read $LOCALPATH\n"; + closedir(DIR); + foreach $name (@names) { + next if ($name eq "."); # skip the current directory entry + next if ($name eq ".."); # skip the parent directory entry + die "$LOCALPATH not empty\n"; + } +} + +=head3 C + +Remove all files in the temp directory C<$TMP> + +=cut +sub reset_tmp { + remove_tree($TMP, { keep_root => 1 }); +} + + +=head3 C + +Remove both temp and remote (C<$DIR>) files + +=cut +sub reset_env { + reset_tmp(); + reset_remote(); +} + +=head3 C + +Make a multiline string of all the files remote path, one path per line. + +C<@files> must be a list of C instance. + +=cut +sub file_list { + my @files = @_; + my $s = ''; + for (@files) { + $s .= $_->remotepath."\n"; + } + return $s; +} + +# remove leading "./" +sub remove_dot { + my $s = shift; + $s =~ s{^\./}{}; + $s; +} + +=head3 C + +Check if C<$remotepath> has B all the C<@files>. + +Print a summary on STDOUT. + +C<@files> must be a list of C instance. + +=cut +sub check_remote { + my ($subpath, $files) = @_; + my (%done, %expected); + my (@less, @more, @diff); + + for (@$files) { + my $fn = remove_dot($_->remotepath); + $expected{$fn} = $_; + $done{$fn} = 0; + } + + my %remote; + File::walk(sub { $remote{remove_dot($_->remotepath)} = $_ }, File::tree($subpath)); + + for my $rfile (sort keys %remote) { + + # files that shouldn't be there + if (!exists $expected{$rfile}) { + say " + $rfile"; + push @more, $rfile; + next; + } + + # same file multiple times + if ($done{$rfile} > 0) { + $done{$rfile}++; + push @more, $rfile; + printf " +%3d %s\n", $done{$rfile}, $rfile; + next; + } + + $done{$rfile}++; + + # different file + my $rmd5 = $remote{$rfile}->md5; + if ($expected{$rfile}->md5 ne $rmd5) { + say " ! $rfile ($rmd5)"; + push @diff, $rfile; + next; + } + + say " $rfile"; + } + + # file that should have been in tar + @less = grep { $done{$_} == 0 } sort keys %done; + for (@less) { + say " - $_"; + } + + # summary + printf("\t%d files, +%d, -%d, !%d\n", + scalar keys %done, + scalar @more, + scalar @less, + scalar @diff); + return (@more + @less + @diff); # nb of errors +} + +=head3 C + +Check if the archive C<$path_to_tar> has B all the C<@files>. + +Print a summary on C; + +C<@files> must be a list of C instance. + +=cut +sub check_tar { + my ($tar, $files) = @_; + my %done; + my (@less, @more, @diff); + + my %h; + + + if (!-f $tar) { + say "no tar file $tar"; + return 1; + } + + for (@$files) { + $h{$_->tarpath} = $_; + $done{$_->tarpath} = 0; + } + + my $total = 0; + my $i = Archive::Tar->iter($tar, 1, {md5 => 1}); + while (my $f = $i->()) { + if ($f->has_content) { + my $p = $f->full_path; + + # we skip pseudo files of Pax format archives + next if ($p =~ m/\/PaxHeader/); + + $total++; + $p =~ s{^\./+}{}; + + # file that shouldn't be there + if (!exists $done{$p}) { + push @more, $p; + say " + $p"; + next; + } + + # same file multiple times + if ($done{$p} > 0) { + $done{$p}++; + push @more, $p; + printf " +%3d %s\n", $done{$p}, $p; + next; + } + + $done{$p}++; + + # different file + + my $md5 = $f->data; + if ($^V lt v5.16) { + $md5 = md5_hex($md5); + } + + if ($md5 ne $h{$p}->md5) { + say " ! $p ($md5)"; + push @diff, $p; + next; + } + + say " $p"; + } + } + + # file that should have been in tar + @less = grep { $done{$_} == 0 } keys %done; + for (sort @less) { + say " - $_"; + } + + # summary + printf("\t%d files, +%d, -%d, !%d\n", + $total, + scalar @more, + scalar @less, + scalar @diff); + return (@more + @less + @diff); # nb of errors +} + +=head3 C + +=head3 C + +Run smbclient with C<@args> passed as argument and return output. + +Each element of C<@args> becomes one escaped argument of smbclient. + +Host, share, user, password and the additional arguments provided on +the command-line are already inserted. + +The output contains both the C and C. + +if C<$will_die> then Die if smbclient crashes or exits with an error code. +otherwise return output + +=cut +sub smb_client_cmd { + my ($will_die, @args) = @_; + + my $fullpath = "//$HOST/$SHARE"; + my $cmd = sprintf("%s %s %s", + quotemeta($BIN), + quotemeta($fullpath), + join(' ', map {quotemeta} (@SMBARGS, @args))); + + if ($DEBUG) { + my $tmp = $cmd; + $tmp =~ s{\\([./+-])}{$1}g; + say color('bold yellow'), $tmp, color('reset'); + } + + my $out = `$cmd 2>&1`; + my $err = $?; + my $errstr = ''; + # handle abnormal exit + if ($err == -1) { + $errstr = "failed to execute $cmd: $!\n"; + } + elsif ($err & 127) { + $errstr = sprintf "child died with signal %d (%s)\n", ($err & 127), $cmd; + } + elsif ($err >> 8) { + $errstr = sprintf "child exited with value %d (%s)\n", ($err >> 8), $cmd; + } + + if ($DEBUG) { + say $out; + } + + if ($err) { + if ($will_die) { + die "ERROR: $errstr"; + } else { + say "ERROR: $errstr"; + } + } + return $out; +} + +=head3 C + +Run smbclient with C<@args> passed as argument and return output. + +Each element of C<@args> becomes one escaped argument of smbclient. + +Host, share, user, password and the additional arguments provided on +the command-line are already inserted. + +The output contains both the C and C. + +Die if smbclient crashes or exits with an error code. + +=cut +sub smb_client { + my (@args) = @_; + return smb_client_cmd(1, @args) +} + +sub smb_cmd { + return smb_client('-c', join(' ', @_)); +} + +=head3 C + +=head3 C + +Run C<$cmd> command and use C<@args> as argument and return output. + +Wrapper around C for tar calls. + +=cut +sub smb_tar { + my ($cmd, @rest) = @_; + printf " CMD: %s\n ARG: %s\n", $cmd, join(' ', @rest); + smb_client((length($cmd) ? ('-c', $cmd) : ()), @rest); +} + +=head3 C + +Return integer in C<[ $min ; $max ]> + +=cut +sub random { + my ($min, $max) = @_; + ($min, $max) = ($max, $min) if ($min > $max); + $min + int(rand($max - $min)); +} + +################################# + +package File; + +=head2 The File module + +All the test should use the C class. It has nice functions and +methods to deal with paths, to create random files, to list the +content of the server, to change attributes, etc. + +There are 2 kinds of C: remote and local. + +=over + +=item * Remote files are accessible on the server. + +=item * Local files are not. + +=back + +Thus, some methods only works on remote files. If they do not make +sense for local ones, they always return undef. + +=cut +use File::Basename; +use File::Path qw/make_path remove_tree/; +use Digest::MD5 qw/md5_hex/; +use Scalar::Util 'blessed'; + +=head3 Constructors + +=head4 C<< File->new_remote($path [, $abs, $size]) >> + +Creates a file accessible on the server at C<$DIR/$path> ie. not at the +root of the share and write C<$size> random bytes. + +If no size is provided, a random size is chosen. + +If you want to remove the automatic prefix C<$DIR>, set C<$abs> to 1. + +The file is created without any DOS attributes. + +If C<$path> contains non-existent directories, they are automatically +created. + +=cut +sub new_remote { + my ($class, $path, $abs, $size) = @_; + my ($file, $dir) = fileparse($path); + + $dir = '' if $dir eq './'; + my $loc; + + if ($abs) { + $loc = cleanpath($main::LOCALPATH.'/'.$dir); + } else { + $dir = cleanpath($main::DIR.'/'.$dir); + $loc = cleanpath($main::LOCALPATH.'/'.$dir); + } + + make_path($loc); + + my $self = bless { + 'attr' => {qw/r 0 s 0 h 0 a 0 d 0 n 0/}, + 'dir' => $dir, + 'name' => $file, + 'md5' => create_file($loc.'/'.$file, $size), + 'remote' => 1, + }, $class; + + $self->set_attr(); + + $self; +} + +=head4 C<< File->new_local($abs_path [, $data]) >> + +Creates a file at C<$abs_path> with $data in it on the system. +If $data is not provided, fill it with random bytes. + +=cut +sub new_local { + my ($class, $path, $data) = @_; + my ($file, $dir) = fileparse($path); + + make_path($dir); + + my $md5; + + if (defined $data) { + open my $f, '>', $path or die "can't write in $path: $!"; + print $f $data; + close $f; + $md5 = md5_hex($data); + } else { + $md5 = create_file($path); + } + + my $self = { + 'attr' => {qw/r 0 s 0 h 0 a 0 d 0 n 0/}, + 'dir' => $dir, + 'name' => $file, + 'md5' => $md5, + 'remote' => 0, + }; + + bless $self, $class; +} + +=head3 Methods + +=head4 C<< $f->localpath >> + +Return path on the system eg. F + +=cut +sub localpath { + my $s = shift; + if ($s->{remote}) { + return cleanpath($main::LOCALPATH.'/'.$s->remotepath); + } + else { + return cleanpath($s->{dir}.'/'.$s->{name}); + } +} + +=head4 C<< $f->remotepath >> + +Return path on the server share. + +Return C if the file is local. + +=cut +sub remotepath { + my ($s) = @_; + return undef if !$s->{remote}; + my $r = $s->{dir}.'/'.$s->{name}; + $r =~ s{^/}{}; + return cleanpath($r); +} + + +=head4 C<< $f->remotedir >> + +Return the directory path of the file on the server. + +Like C<< $f->remotepath >> but without the final file name. + +=cut +sub remotedir { + my $s = shift; + return undef if !$s->{remote}; + cleanpath($s->{dir}); +} + +=head4 C<< $f->tarpath >> + +Return path as it would appear in a tar archive. + +Like C<< $f->remotepath >> but prefixed with F<./> + +=cut +sub tarpath { + my $s = shift; + return undef if !$s->{remote}; + my $r = $s->remotepath; + $r =~ s{^\./+}{}; + return $r; +} + +=head4 C<< $f->delete_on_destruction( 0 ) >> + +=head4 C<< $f->delete_on_destruction( 1 ) >> + +By default, a C is not deleted on the filesystem when it is not +referenced anymore in Perl memory. + +When set to 1, the destructor unlink the file if it is not already removed. +If the C created directories when constructed, it does not remove them. + +=cut +sub delete_on_destruction { + my ($s, $delete) = @_; + $s->{delete_on_destruction} = $delete; +} + +=head4 C<< $f->set_attr( ) >> + +=head4 C<< $f->set_attr( 'a' ) >> + +=head4 C<< $f->set_attr( 'a', 'r', 's', 'h' ) >> + +Remove all DOS attributes and only set the one provided. + +=cut +sub set_attr { + my ($s, @flags) = @_; + return undef if !$s->{remote}; + + $s->{attr} = {qw/r 0 s 0 h 0 a 0 d 0 n 0/}; + + for (@flags) { + $s->{attr}{lc($_)} = 1; + } + + my $file = $s->{name}; + my @args; + if ($s->remotedir) { + push @args, '-D', $s->remotedir; + } + main::smb_client(@args, '-c', qq{setmode "$file" -rsha}); + if (@flags && $flags[0] !~ /n/i) { + main::smb_client(@args, '-c', qq{setmode "$file" +}.join('', @flags)); + } +} + +=head4 C<< $f->attr_any( 'a' ) >> + +=head4 C<< $f->attr_any( 'a', 's', ... ) >> + +Return 1 if the file has any of the DOS attributes provided. + +=cut +sub attr_any { + my ($s, @flags) = @_; + for (@flags) { + return 1 if $s->{attr}{$_}; + } + 0; +} + + +=head4 C<< $f->attr( 'a' ) >> + +=head4 C<< $f->attr( 'a', 's', ... ) >> + +Return 1 if the file has all the DOS attributes provided. + +=cut +sub attr { + my ($s, @flags) = @_; + for (@flags) { + return 0 if !$s->{attr}{$_}; + } + 1; +} + +=head4 C<< $f->attr_str >> + +Return DOS attributes as a compact string. + + Read-only, hidden, system, archive => "rhsa" + +=cut +sub attr_str { + my $s = shift; + return undef if !$s->{remote}; + join('', map {$_ if $s->{attr}{$_}} qw/r h s a d n/); +} + +=head4 C<< $f->set_time($t) >> + +Set modification and access time of the file to C<$t>. + +C<$t> must be in Epoch time (number of seconds since 1970/1/1). + +=cut +sub set_time { + my ($s, $t) = @_; + utime $t, $t, $s->localpath; +} + +=head4 C<< $f->md5 >> + +Return md5 sum of the file. + +The result is cached. + +=cut +sub md5 { + my $s = shift; + + if (!$s->{md5}) { + open my $h, '<', $s->localpath() or die "can't read ".$s->localpath.": $!"; + binmode $h; + $s->{md5} = Digest::MD5->new->addfile($h)->hexdigest; + close $h; + } + + return $s->{md5}; +} + +sub DESTROY { + my $s = shift; + if ($s->{delete_on_destruction} && -f $s->localpath) { + if ($main::DEBUG) { + say "DESTROY ".$s->localpath; + } + unlink $s->localpath; + } +} + +=head3 Functions + +=head4 C<< File::walk( \&function, @files) >> + +=head4 C<< File::walk( sub { ... }, @files) >> + +Iterate on file hierarchy in C<@files> and return accumulated results. + +Use C<$_> in the sub to access the current C. + +The C<@files> must come from a call to the C function. + +=cut +sub walk { + my $fun = \&{shift @_}; + + my @res; + + for (@_) { + if ($_->{attr}{d}) { + push @res, walk($fun, @{$_->{content}}); + } else { + push @res, $fun->($_); + } + } + + return @res; +} + +=head4 C<< File::list( $remotepath ) >> + +Return list of file (C instance) in C<$remotepath>. + +C<$remotepath> must be a directory. + +=cut +sub list { + my ($path) = @_; + $path ||= '/'; + my @files; + my $out = main::smb_client('-D', $path, '-c', 'ls'); + $path =~ s{^/}{}; + + for (split /\n/, $out) { + next if !/^ (.+?)\s+([AHSRDN]*)\s+(\d+)\s+(.+)/o; + my ($fn, $attr, $size, $date) = ($1, $2, $3, $4); + next if $fn =~ /^\.{1,2}$/; + + push @files, bless { + 'remote' => 1, + 'dir' => $path, + 'name' => $fn, + 'size' => int($size), + 'date' => $date, + 'attr' => { + # list context returns something different than the + # boolean matching result => force scalar context + 'a' => scalar ($attr =~ /A/), + 'h' => scalar ($attr =~ /H/), + 's' => scalar ($attr =~ /S/), + 'r' => scalar ($attr =~ /R/), + 'd' => scalar ($attr =~ /D/), + 'n' => scalar ($attr =~ /N/), + }, + }, 'File'; + } + return @files; +} + +=head4 C<< File::tree( $remotepath ) >> + +Return recursive list of file in C<$remotepath>. + +C<$remotepath> must be a directory. + +Use C to iterate over all the files. + +=cut +sub tree { + my ($d) = @_; + my @files; + + if (!defined $d) { + @files = list(); + } elsif (blessed $d) { + @files = list($d->remotepath); + } else { + @files = list($d); + } + + for my $f (@files) { + if ($f->{attr}{d}) { + $f->{content} = [tree($f)]; + } + } + + return @files; +} + +# remove trailing or duplicated slash +sub cleanpath { + my $p = shift; + $p =~ s{/+}{/}g; + $p =~ s{/$}{}; + $p; +} + +# create random file at path local path $fn +sub create_file { + my ($fn, $size) = @_; + my $buf = ''; + unlink $fn if -e $fn; + $size ||= main::random(512, 1024); + $size = int($size); + my $md5; + + # try /dev/urandom, faster + if (-e '/dev/urandom') { + my $cmd = sprintf('head -c %d /dev/urandom | tee %s | md5sum', + $size, quotemeta($fn)); + $md5 = (split / /, `$cmd`)[0]; + } else { + open my $out, '>', $fn or die "can't open $fn: $!\n"; + binmode $out; + for (1..$size) { + $buf .= pack('C', main::random(0, 256)); + } + print $out $buf; + close $out; + $md5 = md5_hex($buf); + } + return $md5; +} + + +=head3 Examples + + # create remote file in $DIR/foo/bar + my $f = File->new_remote("foo/bar/myfile"); + say $f->localpath; # /opt/share/$DIR/foo/bar/myfile + say $f->remotepath; # $DIR/foo/bar/myfile + say $f->remotedir; # $DIR/foo/bar + + + # same but in root dir + my $f = File->new_remote("myfile", 1); + say $f->localpath; # /opt/share/myfile + say $f->remotepath; # myfile + say $f->remotedir; # + + + # create local random temp file in $TMP + my $f = File->new_local("$TMP/temp"); + say $f->remotepath; # undef because it's not on the server + + + # same but file contains "hello" + my $f = File->new_local("$TMP/temp", "hello"); + + + # list of files in $DIR (1 level) + for (File::list($DIR)) { + say $_->remotepath; + } + + + # list of all files in dir and subdir of $DIR + File::walk(sub { say $_->remotepath }, File::tree($DIR)); + +=cut + +1; diff --git a/source3/script/tests/test_smbclient_tarmode.sh b/source3/script/tests/test_smbclient_tarmode.sh new file mode 100755 index 0000000..d48e412 --- /dev/null +++ b/source3/script/tests/test_smbclient_tarmode.sh @@ -0,0 +1,197 @@ +#!/bin/sh + +# this runs a simple tarmode test + +if [ $# -lt 7 ]; then + cat < +EOF + exit 1 +fi + +SERVER="$1" +SERVER_IP="$2" +USERNAME="$3" +PASSWORD="$4" +LOCAL_PATH="$5" +PREFIX="$6" +SMBCLIENT="$7" +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +shift 7 +ADDARGS="$*" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +FAILCOUNT=0 + +# Check command is available +have_command() +{ + type "$1" >/dev/null 2>&1 + return $? +} + +# Create a test corpus +create_test_data() +{ + + local DIR="$1" + local BS=1024 + local NUM_FILES=10 + local NORND_COUNT=25 + + # Bomb if dir exists + if [ -e "$DIR" ]; then + echo "Test data directory '$DIR' already exists!" + false + return + fi + + if ! mkdir -p "$DIR" >/dev/null 2>&1; then + echo "Couldn't create test data directory '$DIR'" + false + return + fi + + local I=1 + if have_command "od"; then # Use random file sizes + local RND_COUNT + for RND_COUNT in $(od -An -N$NUM_FILES -tu1 /dev/null 2>&1; then + echo "Couldn't create test file '$DIR/file.$I' (random size)" + false + return + fi + I=$(expr $I + 1) + done + else # Fallback to same file sizes + while [ $I -le $NUM_FILES ]; do + if ! dd if=/dev/urandom of="$DIR/file.$I" bs=$BS count=$NORND_COUNT >/dev/null 2>&1; then + echo "Couldn't create test file '$DIR/file.$I' (static size)" + false + return + fi + I=$(expr $I + 1) + done + fi + + true + return + +} + +# Check that two directories are equivalent (In Data content) +validate_data() +{ + local DIR1="$1" + local DIR2="$2" + + diff -r "$DIR1" "$DIR2" + return $? +} + +# Test tarmode -Tc +test_tarmode_creation() +{ + + # Clear temp data + rm -rf -- "$PREFIX"/tarmode >/dev/null 2>&1 + rm -f "$PREFIX"/tarmode.tar >/dev/null 2>&1 + $SMBCLIENT //$SERVER/tarmode $CONFIGURATION -U$USERNAME%$PASSWORD -c "deltree smbclient_tar" + + # Build the test data + if ! create_test_data "$LOCAL_PATH"; then + echo "Test data creation failed" + false + return + fi + + # Create tarfile with smbclient + if ! $SMBCLIENT //$SERVER/tarmode $CONFIGURATION -U$USERNAME%$PASSWORD -I $SERVER_IP -p 139 \ + $ADDARGS -c "tarmode full" -Tc "$PREFIX/tarmode.tar" "/smbclient_tar"; then + echo "Couldn't create tar file with tarmode -Tc" + false + return + fi + + # Extract data to verify - this puts it into $PREFIX/smbclient_tar/ + # but we must leave it there as it's used to verify in test_tarmode_extraction() + if ! tar -xf "$PREFIX/tarmode.tar" -C "$PREFIX"; then + echo "Couldn't extract data from created tarfile" + false + return + fi + + # Verify data + if ! validate_data "$PREFIX/smbclient_tar" "$LOCAL_PATH"; then + echo "Data not equivalent" + false + return + fi + + # Clear temp data + rm -rf -- "$PREFIX"/tarmode >/dev/null 2>&1 + rm -f "$PREFIX"/tarmode.tar >/dev/null 2>&1 + $SMBCLIENT //$SERVER/tarmode $CONFIGURATION -U$USERNAME%$PASSWORD -c "deltree smbclient_tar" + true + return + +} + +# Test tarmode -Tx +test_tarmode_extraction() +{ + + # Clear temp data + rm -rf -- "$PREFIX"/tarmode >/dev/null 2>&1 + rm -f "$PREFIX"/tarmode.tar >/dev/null 2>&1 + $SMBCLIENT //$SERVER/tarmode $CONFIGURATION -U$USERNAME%$PASSWORD -c "deltree smbclient_tar" + + # Build the test data + if ! create_test_data "$PREFIX/tarmode"; then + echo "Test data creation failed" + false + return + fi + + # Create tarfile to extract on client + if ! tar -cf "$PREFIX/tarmode.tar" -C "$PREFIX" smbclient_tar; then + echo "Couldn't create tar archive" + false + return + fi + + # Extract tarfile with smbclient + if ! $SMBCLIENT //$SERVER/tarmode $CONFIGURATION -U$USERNAME%$PASSWORD -I $SERVER_IP -p 139 \ + $ADDARGS -c "tarmode full" -Tx "$PREFIX/tarmode.tar"; then + echo "Couldn't extract tar file with tarmode -Tx" + false + return + fi + + # Verify data + if ! validate_data "$PREFIX/smbclient_tar" "$LOCAL_PATH"; then + echo "Data not equivalent" + false + return + fi + + # Clear temp data + rm -rf -- "$PREFIX"/tarmode >/dev/null 2>&1 + rm -f "$PREFIX"/tarmode.tar >/dev/null 2>&1 + $SMBCLIENT //$SERVER/tarmode $CONFIGURATION -U$USERNAME%$PASSWORD -c "deltree smbclient_tar" + # Cleanup the verification data created by test_tarmode_creation(). + rm -rf "$PREFIX"/smbclient_tar >/dev/null 2>&1 + true + return + +} + +testit "test_tarmode_creation" \ + test_tarmode_creation || FAILCOUNT=$(expr $FAILCOUNT + 1) + +testit "test_tarmode_extraction" \ + test_tarmode_extraction || FAILCOUNT=$(expr $FAILCOUNT + 1) + +testok $0 $FAILCOUNT diff --git a/source3/script/tests/test_smbcquota.py b/source3/script/tests/test_smbcquota.py new file mode 100755 index 0000000..02229d7 --- /dev/null +++ b/source3/script/tests/test_smbcquota.py @@ -0,0 +1,244 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# Tests for smbcquotas +# Copyright (C) Noel Power 2017 + +# 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 . + +import os, subprocess, sys +import traceback +import logging +import shutil + +USER_QUOTAS = 1 +USER_DEFAULT_QUOTAS = 2 +GROUP_QUOTAS = 3 +GROUP_DEFAULT_QUOTAS = 4 +BLOCK_SIZE = 1024 +DEFAULT_SOFTLIM = 2 +DEFAULT_HARDLIM = 4 + +class test_env: + def __init__(self): + self.server = None + self.domain = None + self.username = None + self.password = None + self.envdir = None + self.quota_db = None + self.smbcquotas = None + self.users = [] + +class user_info: + def __init__(self): + self.uid = 0 + self.username = "" + self.softlim = 0 + self.hardlim = 0 + +class Quota: + def __init__(self): + self.flags = 0 + self.quotatype = USER_DEFAULT_QUOTAS + self.uid = 0 + self.usedblocks = 0 + self.softlimit = 0 + self.hardlimit = 0 + self.hardlimit = 0 + self.usedinodes = 0 + self.slimitinodes = 0 + self.hlimitinodes = 0 + +def init_quota_db(users, output_file): + filecontents = open(output_file,"w+") + lines = "" + default_values = "0 " + str(DEFAULT_SOFTLIM) + " " + str(DEFAULT_HARDLIM) + " 0 0 0" + for user in users: + lines = lines + user.uid + " " + default_values + "\n" + filecontents.write(lines) + filecontents.close() + +def load_quotas(input_file): + fileContents = open(input_file,"r") + lineno = 0 + quotas = [] + for line in fileContents: + if line.strip().startswith("#"): + continue + content = line.strip().split() + quota = Quota() + if len(content) < 7: + logging.debug("ignoring line %d, doesn't have enough fields\n"%lineno) + else: + quota.flags = 2 + quota.uid = content[0] + quota.usedblocks = content[1] + quota.softlimit = content[2] + quota.hardlimit = content[3] + quota.usedinodes = content[4] + quota.slimitinodes = content[5] + quota.hlimitinodes = content[6] + quotas.append(quota) + + fileContents.close() + return quotas + +def get_quotas(uid, quota_list): + for quota in quota_list: + if quota.uid == uid: + return quota + return None + +def get_users(): + output = subprocess.Popen(['getent', 'passwd'], + stdout=subprocess.PIPE).communicate()[0].decode("utf-8").split('\n') + users = [] + for line in output: + info = line.split(':') + if len(info) > 3 and info[0]: + user = user_info() + user.username = info[0] + user.uid = info[2] + logging.debug("Adding user ->%s<-\n"%user.username) + users.append(user) + return users + + + +def smbcquota_output_to_userinfo(output): + infos = [] + for line in output: + if len(line) > 1: + username = line.strip(':').split()[0] + quota_info = line.split(':')[1].split('/') + if len(quota_info) > 2: + info = user_info() + info.username = username.strip() + info.softlim = int(quota_info[1].strip()) / BLOCK_SIZE + info.hardlim = int(quota_info[2].strip()) / BLOCK_SIZE + infos.append(info) + return infos + +def check_quota_limits(infos, softlim, hardlim): + if len(infos) < 1: + logging.debug("no users info to check :-(\n") + return False + for info in infos: + if int(info.softlim) != softlim: + logging.debug("expected softlimit %s got ->%s<-\n"%(softlim, info.softlim)) + return False + if int(info.hardlim) != hardlim: + logging.debug("expected hardlimit limit %s got %s\n"%(hardlim,info.hardlim)) + return False + return True + +class test_base: + def __init__(self, env): + self.env = env + def run(self, protocol): + pass + +class listtest(test_base): + def run(self, protocol): + init_quota_db(self.env.users, self.env.quota_db) + quotas = load_quotas(self.env.quota_db) + args = [self.env.smbcquotas] + remaining_args = ['-U' + self.env.username + "%" + self.env.password, '-L', '//' + self.env.server + '/quotadir'] + if protocol == 'smb2': + args.append('-m smb2') + args.extend(remaining_args) + output = subprocess.Popen([self.env.smbcquotas, '-U' + self.env.username + "%" + self.env.password, '-L', '//' + self.env.server + '/quotadir'], stdout=subprocess.PIPE).communicate()[0].decode("utf-8").split('\n') + infos = smbcquota_output_to_userinfo(output) + return check_quota_limits(infos, DEFAULT_SOFTLIM, DEFAULT_HARDLIM) +def get_uid(name, users): + for user in users: + if user.username == name: + return user.uid + return None + +class gettest(test_base): + def run(self, protocol): + init_quota_db(self.env.users, self.env.quota_db) + quotas = load_quotas(self.env.quota_db) + uid = get_uid(self.env.username, self.env.users) + output = subprocess.Popen([self.env.smbcquotas, '-U' + self.env.username + "%" + self.env.password, '-u' + self.env.username, '//' + self.env.server + '/quotadir'], stdout=subprocess.PIPE).communicate()[0].decode("utf-8").split('\n') + user_infos = smbcquota_output_to_userinfo(output) + db_user_info = get_quotas(uid, quotas) + # double check, we compare the results from the db file + # the quota script the server uses compared to what + # smbcquota is telling us + return check_quota_limits(user_infos, int(db_user_info.softlimit), int(db_user_info.hardlimit)) + +class settest(test_base): + def run(self, protocol): + init_quota_db(self.env.users, self.env.quota_db) + quotas = load_quotas(self.env.quota_db) + uid = get_uid(self.env.username, self.env.users) + old_db_user_info = get_quotas(uid, quotas) + + #increase limits by 2 blocks + new_soft_limit = (int(old_db_user_info.softlimit) + 2) * BLOCK_SIZE + new_hard_limit = (int(old_db_user_info.hardlimit) + 2) * BLOCK_SIZE + + new_limits = "UQLIM:%s:%d/%d"%(self.env.username, new_soft_limit, new_hard_limit) + logging.debug("setting new limits %s"%new_limits) + + output = subprocess.Popen([self.env.smbcquotas, '-U' + self.env.username + "%" + self.env.password, '//' + self.env.server + '/quotadir', '-S', new_limits], stdout=subprocess.PIPE).communicate()[0].decode("utf-8").split('\n') + logging.debug("output from smbcquota is %s"%output) + user_infos = smbcquota_output_to_userinfo(output) + return check_quota_limits(user_infos, new_soft_limit / BLOCK_SIZE, new_hard_limit / BLOCK_SIZE) + +# map of tests +subtest_descriptions = { + "list test" : listtest, + "get test" : gettest, + "set test" : settest +} + +def main(): + logging.basicConfig(format='%(asctime)s %(message)s', level=logging.DEBUG) + + logging.debug("got args %s\n"%str(sys.argv)) + + if len(sys.argv) < 7: + logging.debug ("Usage: test_smbcquota.py server domain username password envdir smbcquotas\n") + sys.exit(1) + env = test_env() + env.server = sys.argv[1] + env.domain = sys.argv[2] + env.username = sys.argv[3] + env.password = sys.argv[4] + env.envdir = sys.argv[5] + env.smbcquotas = sys.argv[6] + quota_script = os.path.join(os.path.dirname(sys.argv[0]), + "getset_quota.py") + #copy the quota script to the environment + shutil.copy2(quota_script, env.envdir) + + env.quota_db = os.path.join(env.envdir, "quotas.db") + env.users = get_users() + for protocol in ['smb1', 'smb2']: + for key in subtest_descriptions.keys(): + test = subtest_descriptions[key](env) + logging.debug("running subtest '%s' using protocol '%s'\n"%(key,protocol)) + result = test.run(protocol) + if result == False: + logging.debug("subtest '%s' for '%s' failed\n"%(key,protocol)) + sys.exit(1) + else: + logging.debug("subtest '%s' for '%s' passed\n"%(key,protocol)) + sys.exit(0) + +if __name__ == '__main__': + main() diff --git a/source3/script/tests/test_smbcquota.sh b/source3/script/tests/test_smbcquota.sh new file mode 100755 index 0000000..c001192 --- /dev/null +++ b/source3/script/tests/test_smbcquota.sh @@ -0,0 +1,45 @@ +#!/bin/sh +# Unix SMB/CIFS implementation. +# Tests for smbcquotas +# Copyright (C) Noel Power 2017 + +# 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 . +# + +# +# Blackbox test wrapper for smbcquota +# +if [ $# -lt 6 ]; then + cat <$error_inject_conf +echo '[global]' >>$error_inject_conf +echo 'panic action = ""' >>$error_inject_conf + +testit_expect_failure "smbclient" $VALGRIND \ + $BINDIR/smbclient //$SERVER_IP/error_inject \ + -U$USERNAME%$PASSWORD -c dir || + failed=$(expr $failed + 1) + +rm $error_inject_conf + +panic_count_1=$(grep -c PANIC $SMBD_TEST_LOG) + +testit "check_panic_1" test $(expr $panic_count_0 + 1) -eq $panic_count_1 || + failed=$(expr $failed + 1) + +# +# Verify that a failing chdir vfs call does not result in a smbd panic +# + +echo 'error_inject:chdir = ESTALE' >$error_inject_conf + +testit_expect_failure "smbclient" $VALGRIND \ + $BINDIR/smbclient //$SERVER_IP/error_inject \ + -U$USERNAME%$PASSWORD -c dir || + failed=$(expr $failed + 1) + +panic_count_2=$(grep -c PANIC $SMBD_TEST_LOG) + +testit "check_panic_2" test $panic_count_1 -eq $panic_count_2 || + failed=$(expr $failed + 1) + +rm $error_inject_conf + +testok $0 $failed diff --git a/source3/script/tests/test_smbd_no_krb5.sh b/source3/script/tests/test_smbd_no_krb5.sh new file mode 100755 index 0000000..faa46c9 --- /dev/null +++ b/source3/script/tests/test_smbd_no_krb5.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +if [ $# -lt 1 ]; then + cat <$global_inject_conf + +# verify that kerberos fails +test_smbclient_expect_failure "smbd_no_krb5" "ls" "//$SERVER/tmp" --use-kerberos=required $opt || failed=$(expr $failed + 1) + +# verify downgrade to ntlmssp +test_smbclient "test_spnego_downgrade" "ls" "//$SERVER/tmp" $opt --use-kerberos=disabled || failed=$(expr $failed + 1) + +echo '' >$global_inject_conf + +testok $0 $failed diff --git a/source3/script/tests/test_smbget.sh b/source3/script/tests/test_smbget.sh new file mode 100755 index 0000000..acc492d --- /dev/null +++ b/source3/script/tests/test_smbget.sh @@ -0,0 +1,619 @@ +#!/usr/bin/env bash +# +# Blackbox test for smbget. +# + +if [ $# -lt 8 ]; then + cat <"${tmpfile}" <"${TMPDIR}/authfile" << EOF +username = ${SERVER}/${USERNAME} +password = $PASSWORD +EOF + $SMBGET --verbose --authentication-file="${TMPDIR}/authfile" smb://$SERVER_IP/smbget/testfile + rc=$? + rm -f $TMPDIR/authfile + if [ $rc -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + cmp --silent $WORKDIR/testfile ./testfile + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + return 0 +} + +test_recursive_U() +{ + clear_download_area + $SMBGET --verbose --recursive -U${SERVER}/${USERNAME}%$PASSWORD smb://$SERVER_IP/smbget/ + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + + cmp --silent $WORKDIR/testfile ./testfile && + cmp --silent $WORKDIR/dir1/testfile1 ./dir1/testfile1 && + cmp --silent $WORKDIR/dir2/testfile2 ./dir2/testfile2 + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + + return 0 +} + +test_recursive_existing_dir() +{ + clear_download_area + mkdir dir1 + $SMBGET --verbose --recursive -U${SERVER}/${USERNAME}%$PASSWORD smb://$SERVER_IP/smbget/ + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + + cmp --silent $WORKDIR/testfile ./testfile && + cmp --silent $WORKDIR/dir1/testfile1 ./dir1/testfile1 && + cmp --silent $WORKDIR/dir2/testfile2 ./dir2/testfile2 + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + + return 0 +} + +test_recursive_with_empty() +{ # see Bug 13199 + clear_download_area + # create some additional empty directories + mkdir -p $WORKDIR/dir001/dir002/dir003 + mkdir -p $WORKDIR/dir004/dir005/dir006 + $SMBGET --verbose --recursive -U${SERVER}/${USERNAME}%$PASSWORD smb://$SERVER_IP/smbget/ + rc=$? + rm -rf $WORKDIR/dir001 + rm -rf $WORKDIR/dir004 + if [ $rc -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + + cmp --silent $WORKDIR/testfile ./testfile && + cmp --silent $WORKDIR/dir1/testfile1 ./dir1/testfile1 && + cmp --silent $WORKDIR/dir2/testfile2 ./dir2/testfile2 + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + + if [ ! -d dir001/dir002/dir003 ] || [ ! -d dir004/dir005/dir006 ]; then + echo 'ERROR: empty directories are not present' + return 1 + fi + + return 0 +} + +test_resume() +{ + clear_download_area + cp $WORKDIR/testfile . + truncate -s 1024 testfile + $SMBGET --verbose --resume -U${SERVER}/${USERNAME}%$PASSWORD smb://$SERVER_IP/smbget/testfile + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + + cmp --silent $WORKDIR/testfile ./testfile + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + + return 0 +} + +test_resume_modified() +{ + clear_download_area + dd if=/dev/urandom bs=1024 count=2 of=testfile + $SMBGET --verbose --resume -U${SERVER}/${USERNAME}%$PASSWORD smb://$SERVER_IP/smbget/testfile + if [ $? -ne 1 ]; then + echo 'ERROR: RC does not match, expected: 1' + return 1 + fi + + return 0 +} + +test_update() +{ + clear_download_area + $SMBGET --verbose -U${SERVER}/${USERNAME}%$PASSWORD smb://$SERVER_IP/smbget/testfile + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + + # secondary download should pass + $SMBGET --verbose --update -U${SERVER}/${USERNAME}%$PASSWORD smb://$SERVER_IP/smbget/testfile + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + + echo "modified" >>testfile + # touch source to trigger new download + sleep 1 + touch -m $WORKDIR/testfile + $SMBGET --verbose --update -U${SERVER}/${USERNAME}%$PASSWORD smb://$SERVER_IP/smbget/testfile + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + + cmp --silent $WORKDIR/testfile ./testfile + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + + return 0 +} + +# Test accessing an msdfs path. +test_msdfs_link() +{ + clear_download_area + + ${SMBGET} --verbose "-U${SERVER}/${USERNAME}%${PASSWORD}" \ + "smb://${SERVER}/msdfs-share/deeppath/msdfs-src2/readable_file" + ret=$? + if [ ${ret} -ne 0 ]; then + echo "ERROR: smbget failed with ${ret}" + return 1 + fi + + return 0 +} + +test_msdfs_link_domain() +{ + clear_download_area + + ${SMBGET} --verbose "-U${DOMAIN}/${DOMAIN_USER}%${DOMAIN_USER_PASSWORD}" \ + "smb://${SERVER}/msdfs-share/deeppath/msdfs-src2/readable_file" + ret=$? + if [ ${ret} -ne 0 ]; then + echo "ERROR: smbget failed with ${ret}" + return 1 + fi + + return 0 +} + +test_msdfs_link_upn() +{ + clear_download_area + + ${SMBGET} --verbose "-U${DOMAIN_USER}@${REALM}%${DOMAIN_USER_PASSWORD}" \ + "smb://${SERVER}/msdfs-share/deeppath/msdfs-src2/readable_file" + ret=$? + if [ ${ret} -ne 0 ]; then + echo "ERROR: smbget failed with ${ret}" + return 1 + fi + + return 0 +} + +# Tests --limit-rate. Getting the testfile (128K in size) with --limit-rate 100 +# (that is 100KB/s) should take at least 1 sec to complete. +test_limit_rate() +{ + clear_download_area + echo "$SMBGET --verbose --guest --limit-rate 100 smb://$SERVER_IP/smbget_guest/testfile" + time_begin=$(date +%s) + $SMBGET --verbose --guest --limit-rate 100 smb://$SERVER_IP/smbget_guest/testfile + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + time_end=$(date +%s) + cmp --silent $WORKDIR/testfile ./testfile + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + if [ $((time_end - time_begin)) -lt 1 ]; then + echo 'ERROR: It should take at least 1s to transfer 128KB with rate 100KB/s' + return 1 + fi + return 0 +} + +test_encrypt() +{ + clear_download_area + $SMBGET --verbose --encrypt -U${SERVER}/${USERNAME}%$PASSWORD smb://$SERVER_IP/smbget/testfile + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + cmp --silent $WORKDIR/testfile ./testfile + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + + clear_download_area + $SMBGET --verbose --client-protection=encrypt -U${SERVER}/${USERNAME}%$PASSWORD smb://$SERVER_IP/smbget/testfile + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + cmp --silent $WORKDIR/testfile ./testfile + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + + return 0 +} + +test_kerberos() +{ + clear_download_area + + KRB5CCNAME_PATH="${TMPDIR}/smget_krb5ccache" + rm -f "${KRB5CCNAME_PATH}" + + KRB5CCNAME="FILE:${KRB5CCNAME_PATH}" + export KRB5CCNAME + kerberos_kinit "${samba_kinit}" \ + "${DOMAIN_USER}@${REALM}" "${DOMAIN_USER_PASSWORD}" + if [ $? -ne 0 ]; then + echo 'Failed to get Kerberos ticket' + return 1 + fi + + $SMBGET --verbose --use-krb5-ccache="${KRB5CCNAME}" \ + smb://$SERVER/smbget/testfile + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + + cmp --silent $WORKDIR/testfile ./testfile + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + + rm -f "${KRB5CCNAME_PATH}" + + return 0 +} + +test_kerberos_trust() +{ + clear_download_area + + $SMBGET --verbose --use-kerberos=required \ + -U"${TRUST_F_BOTH_USERNAME}@${TRUST_F_BOTH_REALM}%${TRUST_F_BOTH_PASSWORD}" \ + smb://$SERVER.${REALM}/smbget/testfile + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + + cmp --silent $WORKDIR/testfile ./testfile + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + + return 0 +} + +# TODO FIXME +# This test does not work, as we can't tell the libsmb code that the +# principal is an enterprice principal. We need support for enterprise +# principals in kerberos_kinit_password_ext() and a way to pass it via the +# credenitals structure and commandline options. +# It works if you do: kinit -E testdenied_upn@${REALM}.upn +# +# test_kerberos_upn_denied() +# { +# set -x +# clear_download_area +# +# $SMBGET --verbose --use-kerberos=required \ +# -U"testdenied_upn@${REALM}.upn%${DC_PASSWORD}" \ +# "smb://${SERVER}.${REALM}/smbget/testfile" -d10 +# if [ $? -ne 0 ]; then +# echo 'ERROR: RC does not match, expected: 0' +# return 1 +# fi +# +# cmp --silent $WORKDIR/testfile ./testfile +# if [ $? -ne 0 ]; then +# echo 'ERROR: file content does not match' +# return 1 +# fi +# +# return 0 +# } + +create_test_data + +pushd $TMPDIR + +failed=0 +testit "download single file as guest" test_singlefile_guest || + failed=$(expr $failed + 1) + +testit "download single file with -U" test_singlefile_U || + failed=$(expr $failed + 1) + +testit "download single file with --update and domain" test_singlefile_U_domain || + failed=$((failed + 1)) + +testit "download single file with --update and UPN" test_singlefile_U_UPN || + failed=$((failed + 1)) + +testit "download single file with smb URL" test_singlefile_smburl || + failed=$(expr $failed + 1) + +testit "download single file with smb URL including domain" \ + test_singlefile_smburl2 || + failed=$(expr $failed + 1) + +testit "download single file with smb URL interactive" \ + test_singlefile_smburl_interactive || + failed=$(expr $failed + 1) + +testit "download single file with authfile" test_singlefile_authfile || + failed=$(expr $failed + 1) + +testit "recursive download" test_recursive_U || + failed=$(expr $failed + 1) + +testit "recursive download (existing target dir)" test_recursive_existing_dir || + failed=$(expr $failed + 1) + +testit "recursive download with empty directories" test_recursive_with_empty || + failed=$(expr $failed + 1) + +testit "resume download" test_resume || + failed=$(expr $failed + 1) + +testit "resume download (modified file)" test_resume_modified || + failed=$(expr $failed + 1) + +testit "update" test_update || + failed=$(expr $failed + 1) + +testit "msdfs" test_msdfs_link || + failed=$((failed + 1)) + +testit "msdfs.domain" test_msdfs_link_domain || + failed=$((failed + 1)) + +testit "msdfs.upn" test_msdfs_link_upn || + failed=$((failed + 1)) + +testit "limit rate" test_limit_rate || + failed=$((failed + 1)) + +testit "encrypt" test_encrypt || + failed=$((failed + 1)) + +testit "kerberos" test_kerberos || + failed=$((failed + 1)) + +testit "kerberos_trust" test_kerberos_trust || + failed=$((failed + 1)) + +# testit "kerberos_upn_denied" test_kerberos_upn_denied || +# failed=$((failed + 1)) + +clear_download_area + +popd # TMPDIR + +remove_test_data + +exit $failed diff --git a/source3/script/tests/test_smbpasswd.sh b/source3/script/tests/test_smbpasswd.sh new file mode 100755 index 0000000..b4d4f40 --- /dev/null +++ b/source3/script/tests/test_smbpasswd.sh @@ -0,0 +1,133 @@ +#!/bin/sh +# +# Blackbox tests for smbpasswd +# +# Copyright (c) 2015-2016 Andreas Schneider +# + +if [ $# -lt 4 ]; then + cat <$tmpfile <$tmpfile </dev/null 2>&1 + ret=$? + if [ $ret -ne 0 ]; then + echo "Failed to change password for user $user" + echo "$out" + return 1 + fi +} + +testit "Create user $samba_test_user" \ + create_local_smb_user $samba_test_user $samba_test_user_pwd || + failed=$(expr $failed + 1) + +testit "Change user password" \ + test_smbpasswd $samba_test_user $samba_test_user_pwd $samba_test_user_new_pwd || + failed=$(expr $failed + 1) + +testit "Delete user $samba_test_user" \ + delete_local_smb_user $samba_test_user || + failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/test_smbspool.sh b/source3/script/tests/test_smbspool.sh new file mode 100755 index 0000000..2036d57 --- /dev/null +++ b/source3/script/tests/test_smbspool.sh @@ -0,0 +1,294 @@ +#!/bin/sh + +if [ $# -lt 4 ]; then + cat <$tmpfile <$cmdfile <$tmpfile <$cmdfile <$tmpfile <$cmdfile < $status_shares +!UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 $SMBSTATUS --processes > $status_processes +!UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 $SMBSTATUS --locks > $status_locks +close 1 +rm $file +quit +EOF + + cmd="CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS --quiet < $cmdfile 2>&1" + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + + rm -f $cmpfile + rm -f $tmpfile + + if [ $ret -ne 0 ]; then + echo "Failed to run smbclient with error $ret" + echo "$out" + return 1 + fi + + out=$(cat $PREFIX/$status_processes) + echo "$out" | grep -c 'PID *Username' + ret=$? + if [ $ret -eq 1 ]; then + echo "Failed: Could not start smbstatus" + echo "$out" + return 1 + fi + echo "$out" | grep -c "$USERNAME" + ret=$? + if [ $ret -eq 1 ]; then + echo "Failed: open connection not found" + echo "$out" + return 1 + fi + + out=$(cat $PREFIX/$status_shares) + echo "$out" | grep -c 'Service *pid' + ret=$? + if [ $ret -eq 1 ]; then + echo "Failed: Could not start smbstatus" + echo "$out" + return 1 + fi + echo "$out" | grep -c "tmp" + ret=$? + if [ $ret -eq 1 ]; then + echo "Failed: shares not found" + echo "$out" + return 1 + fi + + out=$(cat $PREFIX/$status_locks) + echo "$out" | grep -c "Locked files:" + ret=$? + if [ $ret -eq 1 ]; then + echo "Failed: locked file not found" + echo "$out" + return 1 + fi + echo "$out" | grep -c "$file" + ret=$? + if [ $ret -eq 1 ]; then + echo "Failed: wrong file locked" + echo "$out" + return 1 + fi + + rm $PREFIX/$status_shares + rm $PREFIX/$status_processes + rm $PREFIX/$status_locks + + return 0 +} + +test_smbstatus_json() +{ + local cmdfile=$PREFIX/smbclient_commands + local tmpfile=$PREFIX/smbclient_lock_file + local file=smbclient_lock_file + local status_json=smbstatus_output_json + local status_json_long=smbstatus_output_json_long + + cat > $tmpfile < $cmdfile < $status_json +!UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 $SMBSTATUS --json -vBN > $status_json_long +close 1 +rm $file +quit +EOF + + cmd="CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS --quiet < $cmdfile 2>&1" + out=$(eval $cmd) + echo $out + ret=$? + + rm -f $cmdfile + rm -f $tmpfile + + if [ $ret -ne 0 ]; then + echo "Failed to run smbclient with error $ret" + echo "$out" + return 1 + fi + + echo $out | grep -c 'JSON support not available, please install lib Jansson' + ret=$? + if [ $ret -eq 0 ]; then + subunit_start_test "test_smbstatus_json" + subunit_skip_test "test_smbstatus_json" < +EOF + exit 1 +fi + +t="$1" +unc="$2" +username="$3" +password="$4" +SMBTORTURE="$5" +shift 5 +ADDARGS="$*" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +panic_count_0=$(grep -c PANIC $SMBD_TEST_LOG) + +echo "$panic_count_0" >/tmp/look + +failed=0 +testit "smbtorture" $VALGRIND $SMBTORTURE $unc -U"$username"%"$password" $ADDARGS $t || failed=$(expr $failed + 1) + +panic_count_1=$(grep -c PANIC $SMBD_TEST_LOG) + +echo "$panic_count_1" >>/tmp/look + +testit "check_panic" test $panic_count_0 -eq $panic_count_1 || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_smbtorture_s3.sh b/source3/script/tests/test_smbtorture_s3.sh new file mode 100755 index 0000000..4376f4a --- /dev/null +++ b/source3/script/tests/test_smbtorture_s3.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +# this runs the file serving tests that are expected to pass with samba3 + +if [ $# -lt 5 ]; then + cat < +EOF + exit 1 +fi + +t="$1" +unc="$2" +username="$3" +password="$4" +SMBTORTURE="$5" +shift 5 +ADDARGS="$*" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 +testit "smbtorture" $VALGRIND $SMBTORTURE $unc -U"$username"%"$password" $ADDARGS $t || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_stream_dir_rename.sh b/source3/script/tests/test_stream_dir_rename.sh new file mode 100755 index 0000000..7ac3194 --- /dev/null +++ b/source3/script/tests/test_stream_dir_rename.sh @@ -0,0 +1,72 @@ +#!/bin/sh +# +# Test a stream can rename a directory once an invalid stream path below it was requested. +# BUG: https://bugzilla.samba.org/show_bug.cgi?id=15314 + +if [ $# -lt 5 ]; then + cat <$tmpfile < + +if [ $# -lt 4 ]; then + cat < + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +test_success() +{ + true +} + +testit "success" \ + test_success || + failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_symlink_dosmode.sh b/source3/script/tests/test_symlink_dosmode.sh new file mode 100755 index 0000000..dd6cb6b --- /dev/null +++ b/source3/script/tests/test_symlink_dosmode.sh @@ -0,0 +1,74 @@ +#!/bin/sh + +if [ $# -lt 7 ]; then + cat <"$tmpfile" <"$tmpfile" <"$tmpfile" <"$tmpfile" <"$tmpfile" <${TEMP_CONFFILE} <${TEMP_CONFFILE} <${TEMP_CONFFILE} <&1) + status=$? + if [ "$status" = "0" ]; then + echo "$output" | grep --quiet 'WARNING: The "lsa over netlogon " option is deprecated' + status=$? + if [ "$status" = "1" ]; then + subunit_pass_test "$name" + else + echo $output | subunit_fail_test "$name" + fi + else + echo $output | subunit_fail_test "$name" + fi +} + +testit "name resolve order = lmhosts wins host bcast" \ + test_one_global_option "name resolve order = lmhosts wins host bcast" || + failed=$(expr ${failed} + 1) + +testit_expect_failure "name resolve order = bad wins host bcast" \ + test_one_global_option "name resolve order = bad wins host bcast" || + failed=$(expr ${failed} + 1) + +testit_expect_failure "name resolve order = lmhosts bad host bcast" \ + test_one_global_option "name resolve order = lmhosts bad host bcast" || + failed=$(expr ${failed} + 1) + +testit_expect_failure "name resolve order = lmhosts wins bad bcast" \ + test_one_global_option "name resolve order = lmhosts wins bad bcast" || + failed=$(expr ${failed} + 1) + +testit_expect_failure "name resolve order = lmhosts wins host bad" \ + test_one_global_option "name resolve order = lmhosts wins host bad" || + failed=$(expr ${failed} + 1) + +testit "netbios name" \ + test_one_global_option "netbios name = funky" || + failed=$(expr ${failed} + 1) + +testit "netbios aliases" \ + test_one_global_option "netbios aliases = funky1 funky2 funky3" || + failed=$(expr ${failed} + 1) + +testit "netbios scope" \ + test_one_global_option "netbios scope = abc" || + failed=$(expr ${failed} + 1) + +testit "workgroup" \ + test_one_global_option "workgroup = samba" || + failed=$(expr ${failed} + 1) + +testit "display charset" \ + test_one_global_option "display charset = UTF8" || + failed=$(expr ${failed} + 1) + +testit "ldap debug level" \ + test_one_global_option "ldap debug level = 7" || + failed=$(expr ${failed} + 1) + +for LETTER in U G D I i L N M R T a d h m v w V; do + testit "include with %${LETTER} macro expansion" \ + test_include_expand_macro "${LETTER}" || + failed=$(expr ${failed} + 1) +done + +testit "copy" \ + test_copy || + failed=$(expr ${failed} + 1) + +test_testparm_deprecated "test_deprecated_warning_printed" +test_testparm_deprecated_suppress "test_deprecated_warning_suppressed" + +rm -f ${TEMP_CONFFILE} + +testok $0 ${failed} diff --git a/source3/script/tests/test_tevent_glib_glue.sh b/source3/script/tests/test_tevent_glib_glue.sh new file mode 100755 index 0000000..fa1d105 --- /dev/null +++ b/source3/script/tests/test_tevent_glib_glue.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 +TESTNAME="tevent_glib_glue_test" + +if [ ! -x $BINDIR/tevent_glib_glue_test ]; then + subunit_start_test "$TESTNAME" + subunit_skip_test "$TESTNAME" <&1) || return 1 + echo "smbclient allinfo on $file returned: \"$out\"" + + # Ignore create_time as that is synthesized + for time in access_time write_time change_time; do + echo "$out" | grep "$time" | grep "$expected" || { + echo "Expected \"$expected\", got: \"$(echo $out | grep $time)\"" + return 1 + } + done +} + +#Setup +testit "create testfiles" setup_testfiles || failed=$(expr $failed + 1) + +# Tests +testit "time=0" test_time time_0 "Thu Jan 1 12:00:00 AM 1970 GMT" || failed=$(expr $failed + 1) +testit "time=-1" test_time time_-1 "Wed Dec 31 11:59:59 PM 1969 GMT" || failed=$(expr $failed + 1) +testit "time=-2" test_time time_-2 "Wed Dec 31 11:59:58 PM 1969 GMT" || failed=$(expr $failed + 1) +testit "time=1968" test_time time_1968 "Mon Jan 1 12:00:00 AM 1968 GMT" || failed=$(expr $failed + 1) + +# Cleanup +testit "delete testfile" remove_testfiles || failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/test_user_in_sharelist.sh b/source3/script/tests/test_user_in_sharelist.sh new file mode 100755 index 0000000..0069d6d --- /dev/null +++ b/source3/script/tests/test_user_in_sharelist.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +if [ $# -lt 2 ]; then + echo Usage: $0 RPCCLIENT SERVER + exit 1 +fi + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +RPCCLIENT="$1"; shift 1 +SERVER="$1"; shift 1 + +"${RPCCLIENT}" "${SERVER}" -U"${USER}"%"${PASSWORD}" -c netshareenum | + grep "^netname: $USER\$" +RC=$? +testit "Verify username is listed in netshareenum due to [homes]" \ + test $RC = 0 || failed=$((failed+1)) + +testok $0 $failed diff --git a/source3/script/tests/test_usernamemap.sh b/source3/script/tests/test_usernamemap.sh new file mode 100755 index 0000000..334070e --- /dev/null +++ b/source3/script/tests/test_usernamemap.sh @@ -0,0 +1,28 @@ +#!/bin/sh +# +# Copyright (c) 2022 Pavel Filipenský +# +# Tests for "username map" smb.conf parameter for UNIX groups + +if [ $# -lt 2 ]; then + cat <$tmpfile </dev/null 2>&1 + + ret=$? + if [ $ret = 0 ]; then + # got the correct prompt .. succeed + true + else + echo "$out" + echo "failed listing share with valid users" + false + fi +} + +testit "accessing a valid users share succeeds" \ + test_valid_users_access valid-users-access || + failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/test_veto_files.sh b/source3/script/tests/test_veto_files.sh new file mode 100755 index 0000000..201883e --- /dev/null +++ b/source3/script/tests/test_veto_files.sh @@ -0,0 +1,279 @@ +#!/bin/sh +# +# Check smbclient cannot get a file that matches a veto files +# parameter, or inside a directory that matches a veto files +# parameter. +# +# BUG: https://bugzilla.samba.org/show_bug.cgi?id=15143 +# + +if [ $# -lt 6 ]; then + cat <"$tmpfile" <"$tmpfile" < "${SHAREPATH}/regular_file" +echo "hidden_file" > "${SHAREPATH}/.hidden_file" + +test_smbclient "download regular file" \ + "get regular_file" "//${SERVER}/veto_files_nohidden" \ + -U"${USERNAME}%${PASSWORD}" || + failed=$((failed + 1)) +rm -f regular_file +test_smbclient_expect_failure "hidden file can't be downloaded" \ + "get .hidden_file" "//${SERVER}/veto_files_nohidden" \ + -U"${USERNAME}%${PASSWORD}" || + failed=$((failed + 1)) +test_smbclient "list files" \ + "ls" "//${SERVER}/veto_files_nohidden" \ + -U"${USERNAME}%${PASSWORD}" || + failed=$((failed + 1)) + +do_cleanup + +# Using hash2, veto_name_file\"mangle == VHXE5P~M +# Using hash2, veto_name_dir\"mangle == VF5SKC~B + +# I think a depth of 3 should be enough. +# toplevel +touch "$SHAREPATH/veto_name_file" +mkdir "$SHAREPATH/veto_name_dir" +touch "$SHAREPATH/veto_name_dir/file_inside_dir" +mkdir "$SHAREPATH/veto_name_dir/testdir" +touch "$SHAREPATH/veto_name_dir/testdir/file_inside_dir" +# toplevel mangle names. +touch "$SHAREPATH/veto_name_file\"mangle" +mkdir "$SHAREPATH/veto_name_dir\"mangle" +touch "$SHAREPATH/veto_name_dir\"mangle/file_inside_dir" +mkdir "$SHAREPATH/veto_name_dir\"mangle/testdir" +touch "$SHAREPATH/veto_name_dir\"mangle/testdir/file_inside_dir" + +#depth1 +mkdir "$SHAREPATH/dir1" +touch "$SHAREPATH/dir1/veto_name_file" +mkdir "$SHAREPATH/dir1/veto_name_dir" +touch "$SHAREPATH/dir1/veto_name_dir/file_inside_dir" +mkdir "$SHAREPATH/dir1/veto_name_dir/testdir" +touch "$SHAREPATH/dir1/veto_name_dir/testdir/file_inside_dir" +# depth1 mangle names. +touch "$SHAREPATH/dir1/veto_name_file\"mangle" +mkdir "$SHAREPATH/dir1/veto_name_dir\"mangle" +touch "$SHAREPATH/dir1/veto_name_dir\"mangle/file_inside_dir" +mkdir "$SHAREPATH/dir1/veto_name_dir\"mangle/testdir" +touch "$SHAREPATH/dir1/veto_name_dir\"mangle/testdir/file_inside_dir" + +#depth2 +mkdir "$SHAREPATH/dir1/dir2" +touch "$SHAREPATH/dir1/dir2/veto_name_file" +mkdir "$SHAREPATH/dir1/dir2/veto_name_dir" +touch "$SHAREPATH/dir1/dir2/veto_name_dir/file_inside_dir" +mkdir "$SHAREPATH/dir1/dir2/veto_name_dir/testdir" +touch "$SHAREPATH/dir1/dir2/veto_name_dir/testdir/file_inside_dir" +# depth2 mangle names. +touch "$SHAREPATH/dir1/dir2/veto_name_file\"mangle" +mkdir "$SHAREPATH/dir1/dir2/veto_name_dir\"mangle" +touch "$SHAREPATH/dir1/dir2/veto_name_dir\"mangle/file_inside_dir" +mkdir "$SHAREPATH/dir1/dir2/veto_name_dir\"mangle/testdir" +touch "$SHAREPATH/dir1/dir2/veto_name_dir\"mangle/testdir/file_inside_dir" + +#depth3 +mkdir "$SHAREPATH/dir1/dir2/dir3" +touch "$SHAREPATH/dir1/dir2/dir3/veto_name_file" +mkdir "$SHAREPATH/dir1/dir2/dir3/veto_name_dir" +touch "$SHAREPATH/dir1/dir2/dir3/veto_name_dir/file_inside_dir" +mkdir "$SHAREPATH/dir1/dir2/dir3/veto_name_dir/testdir" +touch "$SHAREPATH/dir1/dir2/dir3/veto_name_dir/testdir/file_inside_dir" +# depth3 mangle names. +touch "$SHAREPATH/dir1/dir2/dir3/veto_name_file\"mangle" +mkdir "$SHAREPATH/dir1/dir2/dir3/veto_name_dir\"mangle" +touch "$SHAREPATH/dir1/dir2/dir3/veto_name_dir\"mangle/file_inside_dir" +mkdir "$SHAREPATH/dir1/dir2/dir3/veto_name_dir\"mangle/testdir" +touch "$SHAREPATH/dir1/dir2/dir3/veto_name_dir\"mangle/testdir/file_inside_dir" + +testit "create_veto_file" test_create_veto_file || failed=$((failed + 1)) +testit "get_veto_file" test_get_veto_file || failed=$(("$failed" + 1)) + +do_cleanup + +cd "${PREFIX_ABS}" && rm -rf ${TMPDIR} + +exit "$failed" diff --git a/source3/script/tests/test_veto_rmdir.sh b/source3/script/tests/test_veto_rmdir.sh new file mode 100755 index 0000000..4d7db9d --- /dev/null +++ b/source3/script/tests/test_veto_rmdir.sh @@ -0,0 +1,217 @@ +#!/bin/sh +# +# Check smbclient can (or cannot) delete a directory containing veto files. +# BUG: https://bugzilla.samba.org/show_bug.cgi?id=14878 +# + +if [ $# -lt 6 ]; then + cat <"$tmpfile" <"$tmpfile" <"$tmpfile" <"$tmpfile" <"$tmpfile" < +# shellcheck disable=1091 + +if [ $# -lt 4 ]; then + cat <fsp_flags.modified + if ! echo "Hello Virus!" >"${sharedir}/infected.txt"; then + echo "ERROR: Cannot create ${sharedir}/infected.txt" + return 1 + fi + + ${SMBCLIENT} "//${SERVER_IP}/${SHARE}" -U"${USER}"%"${PASSWORD}" -c "put ${sharedir}/infected.txt ${smbfile}" + + # check that virusfilter:rename prefix/suffix was added + if [ ! -f "${sharedir}/${smbfilerenamed}" ]; then + echo "ERROR: ${sharedir}/${smbfilerenamed} is missing." + return 1 + fi + + # check that file was not uploaded + if [ -f "${sharedir}/infected.upload.txt" ]; then + echo "ERROR: {sharedir}/${smbfile} should not exist." + return 1 + fi + + return 0 +} + +check_healthy_read() +{ + rm -rf "${sharedir:?}"/* + + if ! echo "Hello Samba!" >"${sharedir}/healthy.txt"; then + echo "ERROR: Cannot create ${sharedir}/healthy.txt" + return 1 + fi + + ${SMBCLIENT} //"${SERVER_IP}"/"${SHARE}" -U"${USER}"%"${PASSWORD}" -c "get healthy.txt ${sharedir}/healthy.download.txt" + + if ! cmp "${sharedir}/healthy.txt" "${sharedir}/healthy.download.txt"; then + echo "ERROR: cmp ${sharedir}/healthy.txt ${sharedir}/healthy.download.txt FAILED" + return 1 + fi + + return 0 +} + +check_healthy_write() +{ + rm -rf "${sharedir:?}"/* + + if ! echo "Hello Samba!" >"${sharedir}/healthy.txt"; then + echo "ERROR: Cannot create ${sharedir}/healthy.txt" + return 1 + fi + + ${SMBCLIENT} //"${SERVER_IP}"/"${SHARE}" -U"${USER}"%"${PASSWORD}" -c "put ${sharedir}/healthy.txt healthy.upload.txt" + + if ! cmp "${sharedir}/healthy.txt" "${sharedir}/healthy.upload.txt"; then + echo "ERROR: cmp ${sharedir}/healthy.txt ${sharedir}/healthy.upload.txt FAILED" + return 1 + fi + + return 0 +} + +testit "check_infected_read" check_infected_read || failed=$((failed + 1)) +testit "check_infected_write" check_infected_write || failed=$((failed + 1)) +testit "check_healthy_read" check_healthy_read || failed=$((failed + 1)) +testit "check_healthy_write" check_healthy_write || failed=$((failed + 1)) + +testok "$0" "$failed" diff --git a/source3/script/tests/test_volume_serial_number.sh b/source3/script/tests/test_volume_serial_number.sh new file mode 100755 index 0000000..b156d70 --- /dev/null +++ b/source3/script/tests/test_volume_serial_number.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# +# This verifies setting the volume serial number parameter for a share works. +# + +if [ $# -lt 5 ]; then + echo "Usage: $0 SERVER_IP USERNAME PASSWORD SHARENAME SMBCLIENT" + exit 1 +fi + +SERVER_IP="$1" +USERNAME="$2" +PASSWORD="$3" +SHARENAME="$4" +SMBCLIENT="$5" + +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +failed=0 + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. "$incdir/subunit.sh" + +test_serial_number() { + + output=$($SMBCLIENT "//$SERVER_IP/$SHARENAME" -U "$USERNAME%$PASSWORD" -c "volume") || return 1 + echo "smbclient volume on $SHARENAME returned: \"$output\"" + + expected="0xdeadbeef" + echo "$output" | grep $expected || { + echo "Expected output containing \"$expected\", got: \"$output\"" + return 1 + } +} + +testit "volume serial number for share $SHARENAME" test_serial_number || failed=$((failed+1)) + +exit "$failed" diff --git a/source3/script/tests/test_wbinfo_lookuprids_cache.sh b/source3/script/tests/test_wbinfo_lookuprids_cache.sh new file mode 100755 index 0000000..abb078b --- /dev/null +++ b/source3/script/tests/test_wbinfo_lookuprids_cache.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +WBINFO="$VALGRIND ${WBINFO:-$BINDIR/wbinfo}" +samba_tdbtool=tdbtool +if test -x $BINDIR/tdbtool; then + samba_tdbtool=$BINDIR/tdbtool +fi +TDBTOOL="${TDBTOOL:-$samba_tdbtool}" + +samba_tdbdump=tdbdump +if test -x $BINDIR/tdbdump; then + samba_tdbdump=$BINDIR/tdbdump +fi +TDBDUMP="${TDBDUMP:-$samba_tdbdump}" + +NET="$VALGRIND ${NET:-$BINDIR/net}" + +cache="$LOCK_DIR"/winbindd_cache.tdb + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +testit "flush" "$NET" "cache" "flush" || failed=$(expr $failed + 1) +testit "lookuprids1" "$WBINFO" "-R" "512,12345" || failed=$(expr $failed + 1) + +key=$("$TDBDUMP" "$cache" | grep ^key.*NDR.*/16/ | cut -d\" -f2) + +testit "delete" "$TDBTOOL" "$cache" delete "$key" +testit "lookuprids2" "$WBINFO" "-R" "512,12345" || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_wbinfo_sids2xids.sh b/source3/script/tests/test_wbinfo_sids2xids.sh new file mode 100755 index 0000000..b07aebf --- /dev/null +++ b/source3/script/tests/test_wbinfo_sids2xids.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +WBINFO="$VALGRIND ${WBINFO:-$BINDIR/wbinfo} $CONFIGURATION" +NET="$VALGRIND ${NET:-$BINDIR/net} $CONFIGURATION" +TEST_INT=$(dirname $0)/test_wbinfo_sids2xids_int.py + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +testit "sids2xids" ${TEST_INT} ${WBINFO} ${NET} || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_wbinfo_sids2xids_int.py b/source3/script/tests/test_wbinfo_sids2xids_int.py new file mode 100755 index 0000000..4f2715c --- /dev/null +++ b/source3/script/tests/test_wbinfo_sids2xids_int.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 + +import sys +import os +import subprocess +from samba.common import get_string + + +if len(sys.argv) != 3: + print("Usage: test_wbinfo_sids2xids_int.py wbinfo net") + sys.exit(1) + +wbinfo = sys.argv[1] +netcmd = sys.argv[2] + + +def run(cmd): + """ + Run a cmd, return bytes str for py2 and unicode str for py3. + + NOTE: subprocess api always return bytes, in both py2 and py3. + """ + output = subprocess.check_output(cmd).strip() + return get_string(output) + + +def flush_cache(sids=None, uids=None, gids=None): + if sids is None: + sids = [] + if uids is None: + uids = [] + if gids is None: + gids = [] + + for sid in sids: + os.system(netcmd + (" cache del IDMAP/SID2XID/%s" % (sid))) + for uid in uids: + os.system(netcmd + (" cache del IDMAP/UID2SID/%s" % (uid))) + for gid in gids: + os.system(netcmd + (" cache del IDMAP/GID2SID/%s" % (gid))) + + +def fill_cache(inids, idtype='gid'): + for inid in inids: + if inid is None: + continue + run([wbinfo, '--%s-to-sid=%s' % (idtype, inid)]) + + +domain = run([wbinfo, "--own-domain"]) +domsid = run([wbinfo, "-n", domain + "/"]) +domsid = domsid.split(' ')[0] + +# print domain +# print domsid + +sids = [domsid + '-512', 'S-1-5-32-545', domsid + '-513', 'S-1-1-0', 'S-1-3-1', 'S-1-5-1'] + +flush_cache(sids=sids) + +sids2xids = run([wbinfo, '--sids-to-unix-ids=' + ','.join(sids)]) + +gids = [] +uids = [] +idtypes = [] + +for line in sids2xids.split('\n'): + result = line.split(' ')[2:] + idtypes.append(result[0]) + + gid = None + uid = None + if result[0] == 'gid': + gid = result[1] + elif result[0] == 'uid': + uid = result[1] + elif result[0] == 'uid/gid': + gid = result[1] + uid = result[1] + + if gid == '-1': + gid = '' + gids.append(gid) + + if uid == '-1': + uid = '' + uids.append(uid) + +# Check the list produced by the sids-to-xids call with the +# singular variant (sid-to-xid) for each sid in turn. + + +def check_singular(sids, ids, idtype='gid'): + i = 0 + for sid in sids: + if ids[i] is None: + continue + + outid = run([wbinfo, '--sid-to-%s' % idtype, sid]) + if outid != ids[i]: + print("Expected %s, got %s\n" % (outid, ids[i])) + flush_cache(sids=sids, uids=uids, gids=gids) + sys.exit(1) + i += 1 + +# Check the list produced by the sids-to-xids call with the +# multiple variant (sid-to-xid) for each sid in turn. + + +def check_multiple(sids, idtypes): + sids2xids = run([wbinfo, '--sids-to-unix-ids=' + ','.join(sids)]) + # print sids2xids + i = 0 + for line in sids2xids.split('\n'): + result = line.split(' ')[2:] + + if result[0] != idtypes[i]: + print("Expected %s, got %s\n" % (idtypes[i], result[0])) + flush_cache(sids=sids, uids=uids, gids=gids) + sys.exit(1) + i += 1 + + +# first round: with filled cache via sid-to-id +check_singular(sids, gids, 'gid') +check_singular(sids, uids, 'uid') + +# second round: with empty cache +flush_cache(sids=sids, gids=gids) +check_singular(sids, gids, 'gid') +flush_cache(sids=sids, uids=uids) +check_singular(sids, uids, 'uid') + +# third round: with filled cache via uid-to-sid +flush_cache(sids=uids, uids=uids) +fill_cache(uids, 'uid') +check_multiple(sids, idtypes) + +# fourth round: with filled cache via gid-to-sid +flush_cache(sids=sids, gids=gids) +fill_cache(gids, 'gid') +check_multiple(sids, idtypes) + +# flush the cache so any incorrect mappings don't break other tests +flush_cache(sids=sids, uids=uids, gids=gids) + +sys.exit(0) diff --git a/source3/script/tests/test_wbinfo_u_large_ad.sh b/source3/script/tests/test_wbinfo_u_large_ad.sh new file mode 100755 index 0000000..ab5f0ca --- /dev/null +++ b/source3/script/tests/test_wbinfo_u_large_ad.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +LDBMODIFY="$VALGRIND ${LDBMODIFY:-$BINDIR/ldbmodify} $CONFIGURATION" +LDBSEARCH="$VALGRIND ${LDBSEARCH:-$BINDIR/ldbsearch} $CONFIGURATION" +WBINFO="$VALGRIND ${WBINFO:-$BINDIR/wbinfo} $CONFIGURATION" + +NUM_USERS=1234 + +BASE_DN=$($LDBSEARCH -H ldap://$DC_SERVER -b "" --scope=base defaultNamingContext | awk '/^defaultNamingContext/ {print $2}') + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +seq -w 1 "$NUM_USERS" | + xargs -INUM echo -e "dn:cn=large_ad_NUM,cn=users,$BASE_DN\nchangetype:add\nobjectclass:user\nsamaccountname:large_ad_NUM\n" | + $LDBMODIFY -H ldap://$DC_SERVER -U "$DOMAIN\Administrator%$DC_PASSWORD" + +testit_grep_count \ + "Make sure $NUM_USERS $DOMAIN users are returned" \ + "$DOMAIN/large_ad_" \ + "$NUM_USERS" \ + ${WBINFO} -u || failed=$(expr $failed + 1) + +seq -w 1 "$NUM_USERS" | + xargs -INUM echo -e "dn:cn=large_ad_NUM,cn=users,$BASE_DN\nchangetype:delete\n" | + $LDBMODIFY -H ldap://$DC_SERVER -U "$DOMAIN\Administrator%$DC_PASSWORD" + +testok $0 $failed diff --git a/source3/script/tests/test_winbind_call_depth_trace.sh b/source3/script/tests/test_winbind_call_depth_trace.sh new file mode 100755 index 0000000..6d978be --- /dev/null +++ b/source3/script/tests/test_winbind_call_depth_trace.sh @@ -0,0 +1,113 @@ +#!/bin/sh + +# Copyright (c) Pavel Filipenský +# License: GPLv3 + +if [ $# -lt 4 ]; then + echo "Usage: test_winbind_call_depth_trace SMBCONTROL CONFIGURATION PREFIX TESTENV" + exit 1 +fi + +SMBCONTROL="${1}" +CONFIGURATION=${2} +PREFIX="${3}" +TESTENV="${4}" +shift 4 + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. "$incdir"/subunit.sh + +failed=0 + +PREFIX_ABS="$(readlink -f "${PREFIX}")" +# Strip from TESTENV the ':local' if present +TESTENV_SUBDIR=${TESTENV%:*} + +LOGFILE="${PREFIX_ABS}/${TESTENV_SUBDIR}/logs/log.winbindd" +# Add support for "WINBINDD_DONT_LOG_STDOUT=1" +if [ ! -r "${LOGFILE}" ]; then + TEST_LOGFILE="${PREFIX_ABS}/${TESTENV_SUBDIR}/winbindd_test.log" + subunit_start_test "test winbind call depth trace" + subunit_skip_test "test winbind call depth trace" <$global_inject_conf +$smbcontrol winbindd reload-config +$wbinfo -p + +test_smbclient "test_winbind_ignore_domains_ok_ntlm_ip" "ls" "//$SERVER_IP/tmp" -U $TRUST_DOMAIN/$TRUST_USERNAME%$TRUST_PASSWORD || failed=$(expr $failed + 1) +test_smbclient "test_winbind_ignore_domains_ok_ntlm_fqdn" "ls" "//$SERVER_FQDN/tmp" -U $TRUST_DOMAIN/$TRUST_USERNAME%$TRUST_PASSWORD || failed=$(expr $failed + 1) +test_smbclient "test_winbind_ignore_domains_ok_krb5" "ls" "//$SERVER_FQDN/tmp" -U $TRUST_USERNAME@$TRUST_REALM%$TRUST_PASSWORD -k || failed=$(expr $failed + 1) + +echo "winbind:ignore domains = $TRUST_DOMAIN" >$global_inject_conf +$smbcontrol winbindd reload-config +$wbinfo -p + +test_smbclient_expect_failure "test_winbind_ignore_domains_fail_ntlm_ip" "ls" "//$SERVER_IP/tmp" -U $TRUST_DOMAIN/$TRUST_USERNAME%$TRUST_PASSWORD || failed=$(expr $failed + 1) +test_smbclient_expect_failure "test_winbind_ignore_domains_fail_ntlm_fqdn" "ls" "//$SERVER_FQDN/tmp" -U $TRUST_DOMAIN/$TRUST_USERNAME%$TRUST_PASSWORD || failed=$(expr $failed + 1) +test_smbclient_expect_failure "test_winbind_ignore_domains_fail_krb5" "ls" "//$SERVER_FQDN/tmp" -U $TRUST_USERNAME@$TRUST_REALM%$TRUST_PASSWORD -k || failed=$(expr $failed + 1) + +echo "" >$global_inject_conf +$smbcontrol winbindd reload-config +$wbinfo -p +remove_posix_ids + +testok $0 $failed diff --git a/source3/script/tests/test_worm.sh b/source3/script/tests/test_worm.sh new file mode 100755 index 0000000..f96c8ec --- /dev/null +++ b/source3/script/tests/test_worm.sh @@ -0,0 +1,121 @@ +#!/bin/sh + +if [ $# -lt 7 ]; then + cat < $tmpfile + # make sure the directory is not too old for worm: + touch $share_test_dir + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/worm -I$SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval "$cmd") + ret=$? + rm -f "$tmpfile" + + if [ $ret != 0 ]; then + printf "%s\n" "$out" + printf "failed worm smbclient run with error %s\n" "$ret" + return 1 + fi + test -e $share_test_dir/must-be-deleted && { + printf "$0: ERROR: must-be-deleted was NOT deleted\n" + return 1 + } + + # now sleep grace_period (1s) and check if worm works properly: + sleep 1 + echo " +posix +chmod 700 must-not-be-deleted +del must-not-be-deleted +del must-be-deleted-after-ctime-refresh +quit" > $tmpfile + # make sure the directory itself is not too old for worm: + touch $share_test_dir + # set a fresh ctime by doing a chmod: + chmod 644 $share_test_dir/must-be-deleted-after-ctime-refresh + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/worm -I$SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval "$cmd") + test -e $share_test_dir/must-not-be-deleted || { + printf "$0: ERROR: must-not-be-deleted WAS deleted\n" + return 1 + } + # if we're not root, return here: + test "$UID" = "0" || { + return 0 + } + + test -e $share_test_dir/must-be-deleted-after-ctime-refresh && { + printf "$0: ERROR: must-be-deleted-after-ctime-refresh was NOT deleted\n" + return 1 + } + return 0 +} + + +testit "worm" \ + test_worm || + failed=$((failed + 1)) + +# +# Cleanup. +do_cleanup + +testok "$0" "$failed" diff --git a/source3/script/tests/test_zero_data.sh b/source3/script/tests/test_zero_data.sh new file mode 100755 index 0000000..62ba856 --- /dev/null +++ b/source3/script/tests/test_zero_data.sh @@ -0,0 +1,54 @@ +#!/bin/sh +# +# Verify that smbtorture tests for manually testing ZERO_DATA +# +# Copyright (C) 2019 Christof Schmitt + +if [ $# -lt 4 ]; then + cat <"$global_inject_conf" + ${SMBCONTROL} ${CONF} smbd reload-config +} + +do_cleanup() +{ + rm -f "${PREFIX}/zero_read_testfile" + rm -f "${PREFIX}/zero_read_testfile_get" + global_inject_conf="$(dirname "${SERVERCONFFILE}")/global_inject.conf" + rm "$global_inject_conf" + ${SMBCONTROL} ${CONF} smbd reload-config +} + +test_smb2_zero_readsize() +{ + local tmpfile="$PREFIX/smbclient.in.$$" + + cat >"$tmpfile" < +#include +#include +#include +#include +#include +#include +#include + +static pid_t child_pid; + +static void usage(void) +{ + printf("usage: timelimit