1 /*
2    Unix SMB/CIFS implementation.
3    SMB torture tester utility functions
4    Copyright (C) Jelmer Vernooij 2006
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20 
21 #include "includes.h"
22 #include "system/filesys.h"
23 #include "system/wait.h"
24 #include "torture/torture.h"
25 #include "libcli/raw/interfaces.h"
26 #include "libcli/raw/libcliraw.h"
27 
28 /**
29  create a temporary directory.
30 */
torture_temp_dir(TALLOC_CTX * mem_ctx,const char * prefix,char ** tempdir)31 _PUBLIC_ NTSTATUS torture_temp_dir(TALLOC_CTX *mem_ctx, const char *prefix,
32 								   char **tempdir)
33 {
34 	const char *basedir = lp_parm_string(-1, "torture", "basedir");
35 	if (basedir == NULL) basedir = ".";
36 	*tempdir = talloc_asprintf(mem_ctx, "%s/torture.tmp-%s.XXXXXX",
37 							   basedir, prefix);
38 
39 	if (mkdtemp(*tempdir) == NULL)
40 		return NT_STATUS_UNSUCCESSFUL;
41 
42 	return NT_STATUS_OK;
43 }
44 
45 /**
46   check if 2 NTTIMEs are equal.
47 */
nt_time_equal(NTTIME * t1,NTTIME * t2)48 BOOL nt_time_equal(NTTIME *t1, NTTIME *t2)
49 {
50 	return *t1 == *t2;
51 }
52 
53 /**
54  * Provision a Samba installation using @param setupdir_script and start smbd.
55  */
torture_setup_server(TALLOC_CTX * mem_ctx,const char * prefix,const char * setupdir_script,const char * smbd_path,pid_t * smbd_pid)56 NTSTATUS torture_setup_server(TALLOC_CTX *mem_ctx,
57 							  const char *prefix,
58 							  const char *setupdir_script,
59 							  const char *smbd_path,
60 							  pid_t *smbd_pid)
61 {
62 	char *tempdir;
63 	NTSTATUS status;
64 	pid_t pid;
65 	int child_status;
66 	char *configfile, *configparam;
67 	pid_t closed_pid;
68 
69 	*smbd_pid = -1;
70 
71 	status = torture_temp_dir(mem_ctx, prefix, &tempdir);
72 	if (NT_STATUS_IS_ERR(status)) {
73 		return status;
74 	}
75 
76 	if ((pid = fork()) == 0) {
77 		execl(setupdir_script, setupdir_script, tempdir, NULL);
78 		exit(1);
79 	} else if (pid == -1) {
80 		DEBUG(0, ("Unable to fork()\n"));
81 		return NT_STATUS_UNSUCCESSFUL;
82 	}
83 
84 	closed_pid = waitpid(pid, &child_status, 0);
85 
86 	if (closed_pid == -1) {
87 		DEBUG(1, ("Error waiting for child"));
88 		return NT_STATUS_UNSUCCESSFUL;
89 	}
90 
91 	SMB_ASSERT(closed_pid == pid);
92 
93 	if (!WIFEXITED(child_status) || WEXITSTATUS(child_status) != 0) {
94 		DEBUG(1, ("Invalid return code from setup script %s: %d\n",
95 				  setupdir_script,
96 				  WEXITSTATUS(child_status)));
97 		return NT_STATUS_UNSUCCESSFUL;
98 	}
99 
100 	configfile = talloc_asprintf(mem_ctx, "%s/etc/smb.conf",
101 								 tempdir);
102 	if (!file_exist(configfile)) {
103 		DEBUG(1, ("Setup script didn't create %s\n", configfile));
104 		return NT_STATUS_UNSUCCESSFUL;
105 	}
106 
107 	configparam = talloc_asprintf(mem_ctx, "--configfile=%s", configfile);
108 	talloc_free(configfile);
109 
110 	if ((pid = fork()) == 0) {
111 		execl(smbd_path, smbd_path, "-i", "--model=single",
112 						configparam, NULL);
113 		exit(1);
114 	} else if (pid == -1) {
115 		DEBUG(0, ("Unable to fork()\n"));
116 		return NT_STATUS_UNSUCCESSFUL;
117 	}
118 
119 	*smbd_pid = pid;
120 
121 	return NT_STATUS_OK;
122 }
123 
torture_second_tcon(TALLOC_CTX * mem_ctx,struct smbcli_session * session,const char * sharename,struct smbcli_tree ** res)124 NTSTATUS torture_second_tcon(TALLOC_CTX *mem_ctx,
125 			     struct smbcli_session *session,
126 			     const char *sharename,
127 			     struct smbcli_tree **res)
128 {
129 	union smb_tcon tcon;
130 	struct smbcli_tree *result;
131 	TALLOC_CTX *tmp_ctx;
132 	NTSTATUS status;
133 
134 	if ((tmp_ctx = talloc_new(mem_ctx)) == NULL) {
135 		return NT_STATUS_NO_MEMORY;
136 	}
137 
138 	result = smbcli_tree_init(session, tmp_ctx, False);
139 	if (result == NULL) {
140 		talloc_free(tmp_ctx);
141 		return NT_STATUS_NO_MEMORY;
142 	}
143 
144 	tcon.generic.level = RAW_TCON_TCONX;
145 	tcon.tconx.in.flags = 0;
146 
147 	/* Ignore share mode security here */
148 	tcon.tconx.in.password = data_blob(NULL, 0);
149 	tcon.tconx.in.path = sharename;
150 	tcon.tconx.in.device = "?????";
151 
152 	status = smb_raw_tcon(result, tmp_ctx, &tcon);
153 	if (!NT_STATUS_IS_OK(status)) {
154 		talloc_free(tmp_ctx);
155 		return status;
156 	}
157 
158 	result->tid = tcon.tconx.out.tid;
159 	*res = talloc_steal(mem_ctx, result);
160 	talloc_free(tmp_ctx);
161 	return NT_STATUS_OK;
162 }
163