~lefteris-nikoltsios/+junk/samba-lp1016895

« back to all changes in this revision

Viewing changes to source3/smbd/smb2_write.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2011-12-21 13:18:04 UTC
  • mfrom: (0.39.21 sid)
  • Revision ID: package-import@ubuntu.com-20111221131804-xtlr39wx6njehxxr
Tags: 2:3.6.1-3ubuntu1
* Merge from Debian testing.  Remaining changes:
  + debian/patches/VERSION.patch:
    - set SAMBA_VERSION_SUFFIX to Ubuntu.
  + debian/patches/error-trans.fix-276472:
    - Add the translation of Unix Error code -ENOTSUP to NT Error Code
    - NT_STATUS_NOT_SUPPORTED to prevent the Permission denied error.
  + debian/smb.conf:
    - add "(Samba, Ubuntu)" to server string.
    - comment out the default [homes] share, and add a comment about
      "valid users = %S" to show users how to restrict access to
      \\server\username to only username.
    - Set 'usershare allow guests', so that usershare admins are 
      allowed to create public shares in addition to authenticated
      ones.
    - add map to guest = Bad user, maps bad username to guest access.
  + debian/samba-common.config:
    - Do not change priority to high if dhclient3 is installed.
    - Use priority medium instead of high for the workgroup question.
  + debian/control:
    - Don't build against or suggest ctdb.
    - Add dependency on samba-common-bin to samba.
  + Add ufw integration:
    - Created debian/samba.ufw.profile
    - debian/rules, debian/samba.dirs, debian/samba.files: install
      profile
    - debian/control: have samba suggest ufw
  + Add apport hook:
    - Created debian/source_samba.py.
    - debian/rules, debian/samba.dirs, debian/samba-common-bin.files: install
  + Switch to upstart:
    - Add debian/samba.{nmbd,smbd}.upstart.
  + debian/samba.logrotate, debian/samba-common.dhcp, debian/samba.if-up:
    - Make them upstart compatible
  + debian/samba.postinst: 
    - Avoid scary pdbedit warnings on first import.
  + debian/samba-common.postinst: Add more informative error message for
    the case where smb.conf was manually deleted
  + debian/patches/fix-debuglevel-name-conflict.patch: don't use 'debug_level'
    as a global variable name in an NSS module 
  + Dropped:
    - debian/patches/error-trans.fix-276472
    - debian/patches/fix-debuglevel-name-conflict.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
*/
20
20
 
21
21
#include "includes.h"
 
22
#include "smbd/smbd.h"
22
23
#include "smbd/globals.h"
23
24
#include "../libcli/smb/smb_common.h"
 
25
#include "../lib/util/tevent_ntstatus.h"
 
26
#include "rpc_server/srv_pipe_hnd.h"
24
27
 
25
28
static struct tevent_req *smbd_smb2_write_send(TALLOC_CTX *mem_ctx,
26
29
                                               struct tevent_context *ev,
36
39
static void smbd_smb2_request_write_done(struct tevent_req *subreq);
37
40
NTSTATUS smbd_smb2_request_process_write(struct smbd_smb2_request *req)
38
41
{
 
42
        NTSTATUS status;
39
43
        const uint8_t *inhdr;
40
44
        const uint8_t *inbody;
41
45
        int i = req->current_idx;
42
 
        size_t expected_body_size = 0x31;
43
 
        size_t body_size;
44
46
        uint32_t in_smbpid;
45
47
        uint16_t in_data_offset;
46
48
        uint32_t in_data_length;
51
53
        uint32_t in_flags;
52
54
        struct tevent_req *subreq;
53
55
 
 
56
        status = smbd_smb2_request_verify_sizes(req, 0x31);
 
57
        if (!NT_STATUS_IS_OK(status)) {
 
58
                return smbd_smb2_request_error(req, status);
 
59
        }
54
60
        inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
55
 
        if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
56
 
                return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
57
 
        }
58
 
 
59
61
        inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
60
62
 
61
 
        body_size = SVAL(inbody, 0x00);
62
 
        if (body_size != expected_body_size) {
63
 
                return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
64
 
        }
65
 
 
66
63
        in_smbpid = IVAL(inhdr, SMB2_HDR_PID);
67
64
 
68
65
        in_data_offset          = SVAL(inbody, 0x02);
72
69
        in_file_id_volatile     = BVAL(inbody, 0x18);
73
70
        in_flags                = IVAL(inbody, 0x2C);
74
71
 
75
 
        if (in_data_offset != (SMB2_HDR_BODY + (body_size & 0xFFFFFFFE))) {
 
72
        if (in_data_offset != (SMB2_HDR_BODY + req->in.vector[i+1].iov_len)) {
76
73
                return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
77
74
        }
78
75
 
81
78
        }
82
79
 
83
80
        /* check the max write size */
84
 
        if (in_data_length > 0x00010000) {
85
 
                DEBUG(0,("here:%s: 0x%08X: 0x%08X\n",
86
 
                        __location__, in_data_length, 0x00010000));
 
81
        if (in_data_length > req->sconn->smb2.max_write) {
 
82
                DEBUG(2,("smbd_smb2_request_process_write : "
 
83
                        "client ignored max write :%s: 0x%08X: 0x%08X\n",
 
84
                        __location__, in_data_length, req->sconn->smb2.max_write));
87
85
                return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
88
86
        }
89
87
 
92
90
 
93
91
        if (req->compat_chain_fsp) {
94
92
                /* skip check */
95
 
        } else if (in_file_id_persistent != 0) {
 
93
        } else if (in_file_id_persistent != in_file_id_volatile) {
96
94
                return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
97
95
        }
98
96
 
167
165
 
168
166
struct smbd_smb2_write_state {
169
167
        struct smbd_smb2_request *smb2req;
 
168
        files_struct *fsp;
 
169
        bool write_through;
170
170
        uint32_t in_length;
 
171
        uint64_t in_offset;
171
172
        uint32_t out_count;
172
173
};
173
174
 
174
175
static void smbd_smb2_write_pipe_done(struct tevent_req *subreq);
175
176
 
 
177
NTSTATUS smb2_write_complete(struct tevent_req *req, ssize_t nwritten, int err)
 
178
{
 
179
        NTSTATUS status;
 
180
        struct smbd_smb2_write_state *state = tevent_req_data(req,
 
181
                                        struct smbd_smb2_write_state);
 
182
        files_struct *fsp = state->fsp;
 
183
 
 
184
        DEBUG(3,("smb2: fnum=[%d/%s] "
 
185
                "length=%lu offset=%lu wrote=%lu\n",
 
186
                fsp->fnum,
 
187
                fsp_str_dbg(fsp),
 
188
                (unsigned long)state->in_length,
 
189
                (unsigned long)state->in_offset,
 
190
                (unsigned long)nwritten));
 
191
 
 
192
        if (nwritten == -1) {
 
193
                return map_nt_error_from_unix(err);
 
194
        }
 
195
 
 
196
        if ((nwritten == 0) && (state->in_length != 0)) {
 
197
                DEBUG(5,("smb2: write [%s] disk full\n",
 
198
                        fsp_str_dbg(fsp)));
 
199
                return NT_STATUS_DISK_FULL;
 
200
        }
 
201
 
 
202
        status = sync_file(fsp->conn, fsp, state->write_through);
 
203
        if (!NT_STATUS_IS_OK(status)) {
 
204
                DEBUG(5,("smb2: sync_file for %s returned %s\n",
 
205
                        fsp_str_dbg(fsp),
 
206
                        nt_errstr(status)));
 
207
                return status;
 
208
        }
 
209
 
 
210
        state->out_count = nwritten;
 
211
 
 
212
        return NT_STATUS_OK;
 
213
}
 
214
 
176
215
static struct tevent_req *smbd_smb2_write_send(TALLOC_CTX *mem_ctx,
177
216
                                               struct tevent_context *ev,
178
217
                                               struct smbd_smb2_request *smb2req,
183
222
                                               uint32_t in_flags)
184
223
{
185
224
        NTSTATUS status;
186
 
        struct tevent_req *req;
187
 
        struct smbd_smb2_write_state *state;
188
 
        struct smb_request *smbreq;
 
225
        struct tevent_req *req = NULL;
 
226
        struct smbd_smb2_write_state *state = NULL;
 
227
        struct smb_request *smbreq = NULL;
189
228
        connection_struct *conn = smb2req->tcon->compat_conn;
190
 
        files_struct *fsp;
 
229
        files_struct *fsp = NULL;
191
230
        ssize_t nwritten;
192
 
        bool write_through = false;
193
231
        struct lock_struct lock;
194
232
 
195
233
        req = tevent_req_create(mem_ctx, &state,
198
236
                return NULL;
199
237
        }
200
238
        state->smb2req = smb2req;
 
239
        if (in_flags & 0x00000001) {
 
240
                state->write_through = true;
 
241
        }
201
242
        state->in_length = in_data.length;
202
243
        state->out_count = 0;
203
244
 
223
264
                return tevent_req_post(req, ev);
224
265
        }
225
266
 
 
267
        state->fsp = fsp;
 
268
 
226
269
        if (IS_IPC(smbreq->conn)) {
227
 
                struct tevent_req *subreq;
 
270
                struct tevent_req *subreq = NULL;
228
271
 
229
272
                if (!fsp_is_np(fsp)) {
230
273
                        tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
249
292
                return tevent_req_post(req, ev);
250
293
        }
251
294
 
 
295
        /* Try and do an asynchronous write. */
 
296
        status = schedule_aio_smb2_write(conn,
 
297
                                        smbreq,
 
298
                                        fsp,
 
299
                                        in_offset,
 
300
                                        in_data,
 
301
                                        state->write_through);
 
302
 
 
303
        if (NT_STATUS_IS_OK(status)) {
 
304
                /*
 
305
                 * Doing an async write. Don't
 
306
                 * send a "gone async" message
 
307
                 * as we expect this to be less
 
308
                 * than the client timeout period.
 
309
                 * JRA. FIXME for offline files..
 
310
                 * FIXME - add cancel code..
 
311
                 */
 
312
                smb2req->async = true;
 
313
                return req;
 
314
        }
 
315
 
 
316
        if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
 
317
                /* Real error in setting up aio. Fail. */
 
318
                tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
 
319
                return tevent_req_post(req, ev);
 
320
        }
 
321
 
 
322
        /* Fallback to synchronous. */
252
323
        init_strict_lock_struct(fsp,
253
 
                                in_smbpid,
 
324
                                in_file_id_volatile,
254
325
                                in_offset,
255
326
                                in_data.length,
256
327
                                WRITE_LOCK,
266
337
                              in_offset,
267
338
                              in_data.length);
268
339
 
269
 
        if (((nwritten == 0) && (in_data.length != 0)) || (nwritten < 0)) {
270
 
                DEBUG(5,("smbd_smb2_write: write_file[%s] disk full\n",
271
 
                         fsp_str_dbg(fsp)));
272
 
                SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
273
 
                tevent_req_nterror(req, NT_STATUS_DISK_FULL);
274
 
                return tevent_req_post(req, ev);
275
 
        }
276
 
 
277
 
        DEBUG(3,("smbd_smb2_write: fnum=[%d/%s] length=%d offset=%d wrote=%d\n",
278
 
                fsp->fnum, fsp_str_dbg(fsp), (int)in_data.length,
279
 
                (int)in_offset, (int)nwritten));
280
 
 
281
 
        if (in_flags & 0x00000001) {
282
 
                write_through = true;
283
 
        }
284
 
 
285
 
        status = sync_file(conn, fsp, write_through);
286
 
        if (!NT_STATUS_IS_OK(status)) {
287
 
                DEBUG(5,("smbd_smb2_write: sync_file for %s returned %s\n",
288
 
                        fsp_str_dbg(fsp), nt_errstr(status)));
289
 
                SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
290
 
                tevent_req_nterror(req, status);
291
 
                return tevent_req_post(req, ev);
292
 
        }
 
340
        status = smb2_write_complete(req, nwritten, errno);
293
341
 
294
342
        SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
295
343
 
296
 
        state->out_count = nwritten;
297
 
 
298
 
        tevent_req_done(req);
 
344
        DEBUG(10,("smb2: write on "
 
345
                "file %s, offset %.0f, requested %u, written = %u\n",
 
346
                fsp_str_dbg(fsp),
 
347
                (double)in_offset,
 
348
                (unsigned int)in_data.length,
 
349
                (unsigned int)nwritten ));
 
350
 
 
351
        if (!NT_STATUS_IS_OK(status)) {
 
352
                tevent_req_nterror(req, status);
 
353
        } else {
 
354
                /* Success. */
 
355
                tevent_req_done(req);
 
356
        }
 
357
 
299
358
        return tevent_req_post(req, ev);
300
359
}
301
360