~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/torture/raw/samba3hide.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
   Unix SMB/CIFS implementation.
 
3
   Test samba3 hide unreadable/unwriteable
 
4
   Copyright (C) Volker Lendecke 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 3 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, see <http://www.gnu.org/licenses/>.
 
18
*/
 
19
 
 
20
#include "includes.h"
 
21
#include "torture/torture.h"
 
22
#include "libcli/raw/libcliraw.h"
 
23
#include "system/time.h"
 
24
#include "system/filesys.h"
 
25
#include "libcli/libcli.h"
 
26
#include "torture/util.h"
 
27
 
 
28
static void init_unixinfo_nochange(union smb_setfileinfo *info)
 
29
{
 
30
        ZERO_STRUCTP(info);
 
31
        info->unix_basic.level = RAW_SFILEINFO_UNIX_BASIC;
 
32
        info->unix_basic.in.mode = SMB_MODE_NO_CHANGE;
 
33
 
 
34
        info->unix_basic.in.end_of_file = SMB_SIZE_NO_CHANGE_HI;
 
35
        info->unix_basic.in.end_of_file <<= 32;
 
36
        info->unix_basic.in.end_of_file |= SMB_SIZE_NO_CHANGE_LO;
 
37
        
 
38
        info->unix_basic.in.num_bytes = SMB_SIZE_NO_CHANGE_HI;
 
39
        info->unix_basic.in.num_bytes <<= 32;
 
40
        info->unix_basic.in.num_bytes |= SMB_SIZE_NO_CHANGE_LO;
 
41
        
 
42
        info->unix_basic.in.status_change_time = SMB_TIME_NO_CHANGE_HI;
 
43
        info->unix_basic.in.status_change_time <<= 32;
 
44
        info->unix_basic.in.status_change_time |= SMB_TIME_NO_CHANGE_LO;
 
45
 
 
46
        info->unix_basic.in.access_time = SMB_TIME_NO_CHANGE_HI;
 
47
        info->unix_basic.in.access_time <<= 32;
 
48
        info->unix_basic.in.access_time |= SMB_TIME_NO_CHANGE_LO;
 
49
 
 
50
        info->unix_basic.in.change_time = SMB_TIME_NO_CHANGE_HI;
 
51
        info->unix_basic.in.change_time <<= 32;
 
52
        info->unix_basic.in.change_time |= SMB_TIME_NO_CHANGE_LO;
 
53
 
 
54
        info->unix_basic.in.uid = SMB_UID_NO_CHANGE;
 
55
        info->unix_basic.in.gid = SMB_GID_NO_CHANGE;
 
56
}
 
57
 
 
58
struct list_state {
 
59
        const char *fname;
 
60
        bool visible;
 
61
};
 
62
 
 
63
static void set_visible(struct clilist_file_info *i, const char *mask,
 
64
                        void *priv)
 
65
{
 
66
        struct list_state *state = (struct list_state *)priv;
 
67
 
 
68
        if (strcasecmp_m(state->fname, i->name) == 0)
 
69
                state->visible = true;
 
70
}
 
71
 
 
72
static bool is_visible(struct smbcli_tree *tree, const char *fname)
 
73
{
 
74
        struct list_state state;
 
75
 
 
76
        state.visible = false;
 
77
        state.fname = fname;
 
78
 
 
79
        if (smbcli_list(tree, "*.*", 0, set_visible, &state) < 0) {
 
80
                return false;
 
81
        }
 
82
        return state.visible;
 
83
}
 
84
 
 
85
static bool is_readable(struct smbcli_tree *tree, const char *fname)
 
86
{
 
87
        int fnum;
 
88
        fnum = smbcli_open(tree, fname, O_RDONLY, DENY_NONE);
 
89
        if (fnum < 0) {
 
90
                return false;
 
91
        }
 
92
        smbcli_close(tree, fnum);
 
93
        return true;
 
94
}
 
95
 
 
96
static bool is_writeable(TALLOC_CTX *mem_ctx, struct smbcli_tree *tree,
 
97
                         const char *fname)
 
98
{
 
99
        int fnum;
 
100
        fnum = smbcli_open(tree, fname, O_WRONLY, DENY_NONE);
 
101
        if (fnum < 0) {
 
102
                return false;
 
103
        }
 
104
        smbcli_close(tree, fnum);
 
105
        return true;
 
106
}
 
107
 
 
108
/*
 
109
 * This is not an exact method because there's a ton of reasons why a getatr
 
110
 * might fail. But for our purposes it's sufficient.
 
111
 */
 
112
 
 
113
static bool smbcli_file_exists(struct smbcli_tree *tree, const char *fname)
 
114
{
 
115
        return NT_STATUS_IS_OK(smbcli_getatr(tree, fname, NULL, NULL, NULL));
 
116
}
 
117
 
 
118
static NTSTATUS smbcli_chmod(struct smbcli_tree *tree, const char *fname,
 
119
                             uint64_t permissions)
 
120
{
 
121
        union smb_setfileinfo sfinfo;
 
122
        init_unixinfo_nochange(&sfinfo);
 
123
        sfinfo.unix_basic.in.file.path = fname;
 
124
        sfinfo.unix_basic.in.permissions = permissions;
 
125
        return smb_raw_setpathinfo(tree, &sfinfo);
 
126
}
 
127
 
 
128
bool torture_samba3_hide(struct torture_context *torture)
 
129
{
 
130
        struct smbcli_state *cli;
 
131
        const char *fname = "test.txt";
 
132
        int fnum;
 
133
        NTSTATUS status;
 
134
        struct smbcli_tree *hideunread;
 
135
        struct smbcli_tree *hideunwrite;
 
136
 
 
137
        if (!torture_open_connection_share(
 
138
                    torture, &cli, torture, torture_setting_string(torture, "host", NULL),
 
139
                    torture_setting_string(torture, "share", NULL), torture->ev)) {
 
140
                d_printf("torture_open_connection_share failed\n");
 
141
                return false;
 
142
        }
 
143
 
 
144
        status = torture_second_tcon(torture, cli->session, "hideunread",
 
145
                                     &hideunread);
 
146
        if (!NT_STATUS_IS_OK(status)) {
 
147
                d_printf("second_tcon(hideunread) failed: %s\n",
 
148
                         nt_errstr(status));
 
149
                return false;
 
150
        }
 
151
 
 
152
        status = torture_second_tcon(torture, cli->session, "hideunwrite",
 
153
                                     &hideunwrite);
 
154
        if (!NT_STATUS_IS_OK(status)) {
 
155
                d_printf("second_tcon(hideunwrite) failed: %s\n",
 
156
                         nt_errstr(status));
 
157
                return false;
 
158
        }
 
159
 
 
160
        status = smbcli_unlink(cli->tree, fname);
 
161
        if (NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
 
162
                smbcli_setatr(cli->tree, fname, 0, -1);
 
163
                smbcli_unlink(cli->tree, fname);
 
164
        }
 
165
 
 
166
        fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
 
167
        if (fnum == -1) {
 
168
                d_printf("Failed to create %s - %s\n", fname,
 
169
                         smbcli_errstr(cli->tree));
 
170
                return false;
 
171
        }
 
172
 
 
173
        smbcli_close(cli->tree, fnum);
 
174
 
 
175
        if (!smbcli_file_exists(cli->tree, fname)) {
 
176
                d_printf("%s does not exist\n", fname);
 
177
                return false;
 
178
        }
 
179
 
 
180
        /* R/W file should be visible everywhere */
 
181
 
 
182
        status = smbcli_chmod(cli->tree, fname, UNIX_R_USR|UNIX_W_USR);
 
183
        if (!NT_STATUS_IS_OK(status)) {
 
184
                d_printf("smbcli_chmod failed: %s\n", nt_errstr(status));
 
185
                return false;
 
186
        }
 
187
        if (!is_writeable(torture, cli->tree, fname)) {
 
188
                d_printf("File not writable\n");
 
189
                return false;
 
190
        }
 
191
        if (!is_readable(cli->tree, fname)) {
 
192
                d_printf("File not readable\n");
 
193
                return false;
 
194
        }
 
195
        if (!is_visible(cli->tree, fname)) {
 
196
                d_printf("r/w file not visible via normal share\n");
 
197
                return false;
 
198
        }
 
199
        if (!is_visible(hideunread, fname)) {
 
200
                d_printf("r/w file not visible via hide unreadable\n");
 
201
                return false;
 
202
        }
 
203
        if (!is_visible(hideunwrite, fname)) {
 
204
                d_printf("r/w file not visible via hide unwriteable\n");
 
205
                return false;
 
206
        }
 
207
 
 
208
        /* R/O file should not be visible via hide unwriteable files */
 
209
 
 
210
        status = smbcli_chmod(cli->tree, fname, UNIX_R_USR);
 
211
 
 
212
        if (!NT_STATUS_IS_OK(status)) {
 
213
                d_printf("smbcli_chmod failed: %s\n", nt_errstr(status));
 
214
                return false;
 
215
        }
 
216
        if (is_writeable(torture, cli->tree, fname)) {
 
217
                d_printf("r/o is writable\n");
 
218
                return false;
 
219
        }
 
220
        if (!is_readable(cli->tree, fname)) {
 
221
                d_printf("r/o not readable\n");
 
222
                return false;
 
223
        }
 
224
        if (!is_visible(cli->tree, fname)) {
 
225
                d_printf("r/o file not visible via normal share\n");
 
226
                return false;
 
227
        }
 
228
        if (!is_visible(hideunread, fname)) {
 
229
                d_printf("r/o file not visible via hide unreadable\n");
 
230
                return false;
 
231
        }
 
232
        if (is_visible(hideunwrite, fname)) {
 
233
                d_printf("r/o file visible via hide unwriteable\n");
 
234
                return false;
 
235
        }
 
236
 
 
237
        /* inaccessible file should be only visible on normal share */
 
238
 
 
239
        status = smbcli_chmod(cli->tree, fname, 0);
 
240
        if (!NT_STATUS_IS_OK(status)) {
 
241
                d_printf("smbcli_chmod failed: %s\n", nt_errstr(status));
 
242
                return false;
 
243
        }
 
244
        if (is_writeable(torture, cli->tree, fname)) {
 
245
                d_printf("inaccessible file is writable\n");
 
246
                return false;
 
247
        }
 
248
        if (is_readable(cli->tree, fname)) {
 
249
                d_printf("inaccessible file is readable\n");
 
250
                return false;
 
251
        }
 
252
        if (!is_visible(cli->tree, fname)) {
 
253
                d_printf("inaccessible file not visible via normal share\n");
 
254
                return false;
 
255
        }
 
256
        if (is_visible(hideunread, fname)) {
 
257
                d_printf("inaccessible file visible via hide unreadable\n");
 
258
                return false;
 
259
        }
 
260
        if (is_visible(hideunwrite, fname)) {
 
261
                d_printf("inaccessible file visible via hide unwriteable\n");
 
262
                return false;
 
263
        }
 
264
 
 
265
        smbcli_chmod(cli->tree, fname, UNIX_R_USR|UNIX_W_USR);
 
266
        smbcli_unlink(cli->tree, fname);
 
267
        
 
268
        return true;
 
269
}
 
270
 
 
271
/*
 
272
 * Try to force smb_close to return an error. The only way I can think of is
 
273
 * to open a file with delete on close, chmod the parent dir to 000 and then
 
274
 * close. smb_close should return NT_STATUS_ACCESS_DENIED.
 
275
 */
 
276
 
 
277
bool torture_samba3_closeerr(struct torture_context *tctx)
 
278
{
 
279
        struct smbcli_state *cli = NULL;
 
280
        bool result = false;
 
281
        NTSTATUS status;
 
282
        const char *dname = "closeerr.dir";
 
283
        const char *fname = "closeerr.dir\\closerr.txt";
 
284
        int fnum;
 
285
 
 
286
        if (!torture_open_connection(&cli, tctx, 0)) {
 
287
                goto fail;
 
288
        }
 
289
 
 
290
        smbcli_deltree(cli->tree, dname);
 
291
 
 
292
        torture_assert_ntstatus_ok(
 
293
                tctx, smbcli_mkdir(cli->tree, dname),
 
294
                talloc_asprintf(tctx, "smbcli_mdir failed: (%s)\n",
 
295
                                smbcli_errstr(cli->tree)));
 
296
 
 
297
        fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR,
 
298
                            DENY_NONE);
 
299
        torture_assert(tctx, fnum != -1, 
 
300
                       talloc_asprintf(tctx, "smbcli_open failed: %s\n",
 
301
                                       smbcli_errstr(cli->tree)));
 
302
        smbcli_close(cli->tree, fnum);
 
303
 
 
304
        fnum = smbcli_nt_create_full(cli->tree, fname, 0, 
 
305
                                      SEC_RIGHTS_FILE_ALL,
 
306
                                      FILE_ATTRIBUTE_NORMAL,
 
307
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
308
                                      NTCREATEX_DISP_OPEN, 0, 0);
 
309
 
 
310
        torture_assert(tctx, fnum != -1, 
 
311
                       talloc_asprintf(tctx, "smbcli_open failed: %s\n",
 
312
                                       smbcli_errstr(cli->tree)));
 
313
 
 
314
        status = smbcli_nt_delete_on_close(cli->tree, fnum, true);
 
315
 
 
316
        torture_assert_ntstatus_ok(tctx, status, 
 
317
                                   "setting delete_on_close on file failed !");
 
318
 
 
319
        status = smbcli_chmod(cli->tree, dname, 0);
 
320
 
 
321
        torture_assert_ntstatus_ok(tctx, status, 
 
322
                                   "smbcli_chmod on file failed !");
 
323
 
 
324
        status = smbcli_close(cli->tree, fnum);
 
325
 
 
326
        smbcli_chmod(cli->tree, dname, UNIX_R_USR|UNIX_W_USR|UNIX_X_USR);
 
327
        smbcli_deltree(cli->tree, dname);
 
328
 
 
329
        torture_assert_ntstatus_equal(tctx, status, NT_STATUS_ACCESS_DENIED,
 
330
                                      "smbcli_close");
 
331
 
 
332
        result = true;
 
333
        
 
334
 fail:
 
335
        if (cli) {
 
336
                torture_close_connection(cli);
 
337
        }
 
338
        return result;
 
339
}