Line data Source code
1 : /*
2 : * CAP VFS module for Samba 3.x Version 0.3
3 : *
4 : * Copyright (C) Tim Potter, 1999-2000
5 : * Copyright (C) Alexander Bokovoy, 2002-2003
6 : * Copyright (C) Stefan (metze) Metzmacher, 2003
7 : * Copyright (C) TAKAHASHI Motonobu (monyo), 2003
8 : * Copyright (C) Jeremy Allison, 2007
9 : *
10 : * This program is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License as published by
12 : * the Free Software Foundation; either version 3 of the License, or
13 : * (at your option) any later version.
14 : *
15 : * This program is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU General Public License
21 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 : */
23 :
24 :
25 : #include "includes.h"
26 : #include "smbd/smbd.h"
27 :
28 : /* cap functions */
29 : static char *capencode(TALLOC_CTX *ctx, const char *from);
30 : static char *capdecode(TALLOC_CTX *ctx, const char *from);
31 :
32 0 : static uint64_t cap_disk_free(vfs_handle_struct *handle,
33 : const struct smb_filename *smb_fname,
34 : uint64_t *bsize,
35 : uint64_t *dfree,
36 : uint64_t *dsize)
37 : {
38 0 : char *capname = capencode(talloc_tos(), smb_fname->base_name);
39 0 : struct smb_filename *cap_smb_fname = NULL;
40 :
41 0 : if (!capname) {
42 0 : errno = ENOMEM;
43 0 : return (uint64_t)-1;
44 : }
45 0 : cap_smb_fname = synthetic_smb_fname(talloc_tos(),
46 : capname,
47 : NULL,
48 : NULL,
49 0 : smb_fname->twrp,
50 0 : smb_fname->flags);
51 0 : if (cap_smb_fname == NULL) {
52 0 : TALLOC_FREE(capname);
53 0 : errno = ENOMEM;
54 0 : return (uint64_t)-1;
55 : }
56 0 : return SMB_VFS_NEXT_DISK_FREE(handle, cap_smb_fname,
57 : bsize, dfree, dsize);
58 : }
59 :
60 0 : static int cap_get_quota(vfs_handle_struct *handle,
61 : const struct smb_filename *smb_fname,
62 : enum SMB_QUOTA_TYPE qtype,
63 : unid_t id,
64 : SMB_DISK_QUOTA *dq)
65 : {
66 0 : char *cappath = capencode(talloc_tos(), smb_fname->base_name);
67 0 : struct smb_filename *cap_smb_fname = NULL;
68 :
69 0 : if (!cappath) {
70 0 : errno = ENOMEM;
71 0 : return -1;
72 : }
73 0 : cap_smb_fname = synthetic_smb_fname(talloc_tos(),
74 : cappath,
75 : NULL,
76 : NULL,
77 0 : smb_fname->twrp,
78 0 : smb_fname->flags);
79 0 : if (cap_smb_fname == NULL) {
80 0 : TALLOC_FREE(cappath);
81 0 : errno = ENOMEM;
82 0 : return -1;
83 : }
84 0 : return SMB_VFS_NEXT_GET_QUOTA(handle, cap_smb_fname, qtype, id, dq);
85 : }
86 :
87 : static struct dirent *
88 0 : cap_readdir(vfs_handle_struct *handle, struct files_struct *dirfsp, DIR *dirp)
89 : {
90 : struct dirent *result;
91 : struct dirent *newdirent;
92 : char *newname;
93 : size_t newnamelen;
94 0 : DEBUG(3,("cap: cap_readdir\n"));
95 :
96 0 : result = SMB_VFS_NEXT_READDIR(handle, dirfsp, dirp);
97 0 : if (!result) {
98 0 : return NULL;
99 : }
100 :
101 0 : newname = capdecode(talloc_tos(), result->d_name);
102 0 : if (!newname) {
103 0 : return NULL;
104 : }
105 0 : DEBUG(3,("cap: cap_readdir: %s\n", newname));
106 0 : newnamelen = strlen(newname)+1;
107 0 : newdirent = talloc_size(
108 : talloc_tos(), sizeof(struct dirent) + newnamelen);
109 0 : if (!newdirent) {
110 0 : return NULL;
111 : }
112 0 : talloc_set_name_const(newdirent, "struct dirent");
113 0 : memcpy(newdirent, result, sizeof(struct dirent));
114 0 : memcpy(&newdirent->d_name, newname, newnamelen);
115 0 : return newdirent;
116 : }
117 :
118 0 : static int cap_mkdirat(vfs_handle_struct *handle,
119 : struct files_struct *dirfsp,
120 : const struct smb_filename *smb_fname,
121 : mode_t mode)
122 : {
123 0 : char *cappath = capencode(talloc_tos(), smb_fname->base_name);
124 0 : struct smb_filename *cap_smb_fname = NULL;
125 :
126 0 : if (!cappath) {
127 0 : errno = ENOMEM;
128 0 : return -1;
129 : }
130 :
131 0 : cap_smb_fname = synthetic_smb_fname(talloc_tos(),
132 : cappath,
133 : NULL,
134 : NULL,
135 0 : smb_fname->twrp,
136 0 : smb_fname->flags);
137 0 : if (cap_smb_fname == NULL) {
138 0 : TALLOC_FREE(cappath);
139 0 : errno = ENOMEM;
140 0 : return -1;
141 : }
142 :
143 0 : return SMB_VFS_NEXT_MKDIRAT(handle,
144 : dirfsp,
145 : cap_smb_fname,
146 : mode);
147 : }
148 :
149 0 : static int cap_openat(vfs_handle_struct *handle,
150 : const struct files_struct *dirfsp,
151 : const struct smb_filename *smb_fname_in,
152 : files_struct *fsp,
153 : const struct vfs_open_how *how)
154 : {
155 0 : char *cappath = NULL;
156 0 : struct smb_filename *smb_fname = NULL;
157 : int ret;
158 0 : int saved_errno = 0;
159 :
160 0 : cappath = capencode(talloc_tos(), smb_fname_in->base_name);
161 0 : if (cappath == NULL) {
162 0 : errno = ENOMEM;
163 0 : return -1;
164 : }
165 :
166 0 : smb_fname = cp_smb_filename(talloc_tos(), smb_fname_in);
167 0 : if (smb_fname == NULL) {
168 0 : TALLOC_FREE(cappath);
169 0 : errno = ENOMEM;
170 0 : return -1;
171 : }
172 0 : smb_fname->base_name = cappath;
173 :
174 0 : DBG_DEBUG("cap_open for %s\n", smb_fname_str_dbg(smb_fname));
175 0 : ret = SMB_VFS_NEXT_OPENAT(handle,
176 : dirfsp,
177 : smb_fname,
178 : fsp,
179 : how);
180 0 : if (ret == -1) {
181 0 : saved_errno = errno;
182 : }
183 0 : TALLOC_FREE(cappath);
184 0 : TALLOC_FREE(smb_fname);
185 0 : if (saved_errno != 0) {
186 0 : errno = saved_errno;
187 : }
188 0 : return ret;
189 : }
190 :
191 0 : static int cap_renameat(vfs_handle_struct *handle,
192 : files_struct *srcfsp,
193 : const struct smb_filename *smb_fname_src,
194 : files_struct *dstfsp,
195 : const struct smb_filename *smb_fname_dst)
196 : {
197 0 : char *capold = NULL;
198 0 : char *capnew = NULL;
199 0 : struct smb_filename *smb_fname_src_tmp = NULL;
200 0 : struct smb_filename *smb_fname_dst_tmp = NULL;
201 0 : struct smb_filename *full_fname_src = NULL;
202 0 : struct smb_filename *full_fname_dst = NULL;
203 0 : int ret = -1;
204 0 : int saved_errno = 0;
205 :
206 0 : full_fname_src = full_path_from_dirfsp_atname(talloc_tos(),
207 : srcfsp,
208 : smb_fname_src);
209 0 : if (full_fname_src == NULL) {
210 0 : errno = ENOMEM;
211 0 : goto out;
212 : }
213 :
214 0 : full_fname_dst = full_path_from_dirfsp_atname(talloc_tos(),
215 : dstfsp,
216 : smb_fname_dst);
217 0 : if (full_fname_dst == NULL) {
218 0 : errno = ENOMEM;
219 0 : goto out;
220 : }
221 :
222 0 : capold = capencode(talloc_tos(), full_fname_src->base_name);
223 0 : capnew = capencode(talloc_tos(), full_fname_dst->base_name);
224 0 : if (!capold || !capnew) {
225 0 : errno = ENOMEM;
226 0 : goto out;
227 : }
228 :
229 : /* Setup temporary smb_filename structs. */
230 0 : smb_fname_src_tmp = cp_smb_filename(talloc_tos(), full_fname_src);
231 0 : if (smb_fname_src_tmp == NULL) {
232 0 : errno = ENOMEM;
233 0 : goto out;
234 : }
235 0 : smb_fname_dst_tmp = cp_smb_filename(talloc_tos(), full_fname_dst);
236 0 : if (smb_fname_dst_tmp == NULL) {
237 0 : errno = ENOMEM;
238 0 : goto out;
239 : }
240 :
241 0 : smb_fname_src_tmp->base_name = capold;
242 0 : smb_fname_dst_tmp->base_name = capnew;
243 :
244 0 : ret = SMB_VFS_NEXT_RENAMEAT(handle,
245 : srcfsp->conn->cwd_fsp,
246 : smb_fname_src_tmp,
247 : dstfsp->conn->cwd_fsp,
248 : smb_fname_dst_tmp);
249 :
250 0 : out:
251 :
252 0 : if (ret != 0) {
253 0 : saved_errno = errno;
254 : }
255 :
256 0 : TALLOC_FREE(full_fname_src);
257 0 : TALLOC_FREE(full_fname_dst);
258 0 : TALLOC_FREE(capold);
259 0 : TALLOC_FREE(capnew);
260 0 : TALLOC_FREE(smb_fname_src_tmp);
261 0 : TALLOC_FREE(smb_fname_dst_tmp);
262 :
263 0 : if (ret != 0) {
264 0 : errno = saved_errno;
265 : }
266 :
267 0 : return ret;
268 : }
269 :
270 0 : static int cap_stat(vfs_handle_struct *handle, struct smb_filename *smb_fname)
271 : {
272 : char *cappath;
273 0 : char *tmp_base_name = NULL;
274 : int ret;
275 :
276 0 : cappath = capencode(talloc_tos(), smb_fname->base_name);
277 :
278 0 : if (!cappath) {
279 0 : errno = ENOMEM;
280 0 : return -1;
281 : }
282 :
283 0 : tmp_base_name = smb_fname->base_name;
284 0 : smb_fname->base_name = cappath;
285 :
286 0 : ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
287 :
288 0 : smb_fname->base_name = tmp_base_name;
289 0 : TALLOC_FREE(cappath);
290 :
291 0 : return ret;
292 : }
293 :
294 0 : static int cap_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname)
295 : {
296 : char *cappath;
297 0 : char *tmp_base_name = NULL;
298 : int ret;
299 :
300 0 : cappath = capencode(talloc_tos(), smb_fname->base_name);
301 :
302 0 : if (!cappath) {
303 0 : errno = ENOMEM;
304 0 : return -1;
305 : }
306 :
307 0 : tmp_base_name = smb_fname->base_name;
308 0 : smb_fname->base_name = cappath;
309 :
310 0 : ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
311 :
312 0 : smb_fname->base_name = tmp_base_name;
313 0 : TALLOC_FREE(cappath);
314 :
315 0 : return ret;
316 : }
317 :
318 0 : static int cap_unlinkat(vfs_handle_struct *handle,
319 : struct files_struct *dirfsp,
320 : const struct smb_filename *smb_fname,
321 : int flags)
322 : {
323 0 : struct smb_filename *full_fname = NULL;
324 0 : struct smb_filename *smb_fname_tmp = NULL;
325 0 : char *cappath = NULL;
326 : int ret;
327 :
328 0 : full_fname = full_path_from_dirfsp_atname(talloc_tos(),
329 : dirfsp,
330 : smb_fname);
331 0 : if (full_fname == NULL) {
332 0 : return -1;
333 : }
334 :
335 0 : cappath = capencode(talloc_tos(), full_fname->base_name);
336 0 : if (!cappath) {
337 0 : TALLOC_FREE(full_fname);
338 0 : errno = ENOMEM;
339 0 : return -1;
340 : }
341 :
342 : /* Setup temporary smb_filename structs. */
343 0 : smb_fname_tmp = cp_smb_filename(talloc_tos(), full_fname);
344 0 : TALLOC_FREE(full_fname);
345 0 : if (smb_fname_tmp == NULL) {
346 0 : errno = ENOMEM;
347 0 : return -1;
348 : }
349 :
350 0 : smb_fname_tmp->base_name = cappath;
351 :
352 0 : ret = SMB_VFS_NEXT_UNLINKAT(handle,
353 : dirfsp->conn->cwd_fsp,
354 : smb_fname_tmp,
355 : flags);
356 :
357 0 : TALLOC_FREE(smb_fname_tmp);
358 0 : return ret;
359 : }
360 :
361 0 : static int cap_lchown(vfs_handle_struct *handle,
362 : const struct smb_filename *smb_fname,
363 : uid_t uid,
364 : gid_t gid)
365 : {
366 0 : struct smb_filename *cap_smb_fname = NULL;
367 0 : char *cappath = capencode(talloc_tos(), smb_fname->base_name);
368 : int ret;
369 : int saved_errno;
370 :
371 0 : if (!cappath) {
372 0 : errno = ENOMEM;
373 0 : return -1;
374 : }
375 :
376 0 : cap_smb_fname = synthetic_smb_fname(talloc_tos(),
377 : cappath,
378 : NULL,
379 : NULL,
380 0 : smb_fname->twrp,
381 0 : smb_fname->flags);
382 0 : if (cap_smb_fname == NULL) {
383 0 : TALLOC_FREE(cappath);
384 0 : errno = ENOMEM;
385 0 : return -1;
386 : }
387 :
388 0 : ret = SMB_VFS_NEXT_LCHOWN(handle, cap_smb_fname, uid, gid);
389 0 : saved_errno = errno;
390 0 : TALLOC_FREE(cappath);
391 0 : TALLOC_FREE(cap_smb_fname);
392 0 : errno = saved_errno;
393 0 : return ret;
394 : }
395 :
396 0 : static int cap_chdir(vfs_handle_struct *handle,
397 : const struct smb_filename *smb_fname)
398 : {
399 0 : struct smb_filename *cap_smb_fname = NULL;
400 0 : char *cappath = capencode(talloc_tos(), smb_fname->base_name);
401 : int ret;
402 0 : int saved_errno = 0;
403 :
404 0 : if (!cappath) {
405 0 : errno = ENOMEM;
406 0 : return -1;
407 : }
408 0 : DEBUG(3,("cap: cap_chdir for %s\n", smb_fname->base_name));
409 :
410 0 : cap_smb_fname = synthetic_smb_fname(talloc_tos(),
411 : cappath,
412 : NULL,
413 : NULL,
414 0 : smb_fname->twrp,
415 0 : smb_fname->flags);
416 0 : if (cap_smb_fname == NULL) {
417 0 : TALLOC_FREE(cappath);
418 0 : errno = ENOMEM;
419 0 : return -1;
420 : }
421 0 : ret = SMB_VFS_NEXT_CHDIR(handle, cap_smb_fname);
422 0 : if (ret == -1) {
423 0 : saved_errno = errno;
424 : }
425 0 : TALLOC_FREE(cappath);
426 0 : TALLOC_FREE(cap_smb_fname);
427 0 : if (saved_errno != 0) {
428 0 : errno = saved_errno;
429 : }
430 0 : return ret;
431 : }
432 :
433 0 : static int cap_symlinkat(vfs_handle_struct *handle,
434 : const struct smb_filename *link_contents,
435 : struct files_struct *dirfsp,
436 : const struct smb_filename *new_smb_fname)
437 : {
438 0 : struct smb_filename *full_fname = NULL;
439 0 : char *capold = capencode(talloc_tos(), link_contents->base_name);
440 0 : char *capnew = NULL;
441 0 : struct smb_filename *new_link_target = NULL;
442 0 : struct smb_filename *new_cap_smb_fname = NULL;
443 0 : int saved_errno = 0;
444 : int ret;
445 :
446 0 : if (capold == NULL) {
447 0 : errno = ENOMEM;
448 0 : return -1;
449 : }
450 :
451 0 : full_fname = full_path_from_dirfsp_atname(talloc_tos(),
452 : dirfsp,
453 : new_smb_fname);
454 0 : if (full_fname == NULL) {
455 0 : return -1;
456 : }
457 :
458 0 : capnew = capencode(talloc_tos(), full_fname->base_name);
459 0 : if (!capnew) {
460 0 : TALLOC_FREE(full_fname);
461 0 : errno = ENOMEM;
462 0 : return -1;
463 : }
464 :
465 0 : new_link_target = synthetic_smb_fname(talloc_tos(),
466 : capold,
467 : NULL,
468 : NULL,
469 0 : new_smb_fname->twrp,
470 0 : new_smb_fname->flags);
471 0 : if (new_link_target == NULL) {
472 0 : TALLOC_FREE(full_fname);
473 0 : TALLOC_FREE(capold);
474 0 : TALLOC_FREE(capnew);
475 0 : errno = ENOMEM;
476 0 : return -1;
477 : }
478 :
479 0 : new_cap_smb_fname = synthetic_smb_fname(talloc_tos(),
480 : capnew,
481 : NULL,
482 : NULL,
483 0 : new_smb_fname->twrp,
484 0 : new_smb_fname->flags);
485 0 : if (new_cap_smb_fname == NULL) {
486 0 : TALLOC_FREE(full_fname);
487 0 : TALLOC_FREE(capold);
488 0 : TALLOC_FREE(capnew);
489 0 : TALLOC_FREE(new_link_target);
490 0 : errno = ENOMEM;
491 0 : return -1;
492 : }
493 0 : ret = SMB_VFS_NEXT_SYMLINKAT(handle,
494 : new_link_target,
495 : handle->conn->cwd_fsp,
496 : new_cap_smb_fname);
497 0 : if (ret == -1) {
498 0 : saved_errno = errno;
499 : }
500 0 : TALLOC_FREE(full_fname);
501 0 : TALLOC_FREE(capold);
502 0 : TALLOC_FREE(capnew);
503 0 : TALLOC_FREE(new_link_target);
504 0 : TALLOC_FREE(new_cap_smb_fname);
505 0 : if (saved_errno != 0) {
506 0 : errno = saved_errno;
507 : }
508 0 : return ret;
509 : }
510 :
511 0 : static int cap_readlinkat(vfs_handle_struct *handle,
512 : const struct files_struct *dirfsp,
513 : const struct smb_filename *smb_fname,
514 : char *buf,
515 : size_t bufsiz)
516 : {
517 0 : struct smb_filename *full_fname = NULL;
518 0 : struct smb_filename *cap_smb_fname = NULL;
519 0 : char *cappath = NULL;
520 0 : int saved_errno = 0;
521 : int ret;
522 :
523 0 : full_fname = full_path_from_dirfsp_atname(talloc_tos(),
524 : dirfsp,
525 : smb_fname);
526 0 : if (full_fname == NULL) {
527 0 : return -1;
528 : }
529 :
530 0 : cappath = capencode(talloc_tos(), full_fname->base_name);
531 0 : if (cappath == NULL) {
532 0 : TALLOC_FREE(full_fname);
533 0 : errno = ENOMEM;
534 0 : return -1;
535 : }
536 0 : cap_smb_fname = synthetic_smb_fname(talloc_tos(),
537 : cappath,
538 : NULL,
539 : NULL,
540 0 : smb_fname->twrp,
541 0 : smb_fname->flags);
542 0 : if (cap_smb_fname == NULL) {
543 0 : TALLOC_FREE(full_fname);
544 0 : TALLOC_FREE(cappath);
545 0 : errno = ENOMEM;
546 0 : return -1;
547 : }
548 0 : ret = SMB_VFS_NEXT_READLINKAT(handle,
549 : handle->conn->cwd_fsp,
550 : cap_smb_fname,
551 : buf,
552 : bufsiz);
553 0 : if (ret == -1) {
554 0 : saved_errno = errno;
555 : }
556 0 : TALLOC_FREE(full_fname);
557 0 : TALLOC_FREE(cappath);
558 0 : TALLOC_FREE(cap_smb_fname);
559 0 : if (saved_errno != 0) {
560 0 : errno = saved_errno;
561 : }
562 0 : return ret;
563 : }
564 :
565 0 : static int cap_linkat(vfs_handle_struct *handle,
566 : files_struct *srcfsp,
567 : const struct smb_filename *old_smb_fname,
568 : files_struct *dstfsp,
569 : const struct smb_filename *new_smb_fname,
570 : int flags)
571 : {
572 0 : struct smb_filename *old_full_fname = NULL;
573 0 : struct smb_filename *new_full_fname = NULL;
574 0 : char *capold = NULL;
575 0 : char *capnew = NULL;
576 0 : struct smb_filename *old_cap_smb_fname = NULL;
577 0 : struct smb_filename *new_cap_smb_fname = NULL;
578 0 : int saved_errno = 0;
579 : int ret;
580 :
581 : /* Process 'old' name. */
582 0 : old_full_fname = full_path_from_dirfsp_atname(talloc_tos(),
583 : srcfsp,
584 : old_smb_fname);
585 0 : if (old_full_fname == NULL) {
586 0 : goto nomem_out;
587 : }
588 0 : capold = capencode(talloc_tos(), old_full_fname->base_name);
589 0 : if (capold == NULL) {
590 0 : goto nomem_out;
591 : }
592 0 : TALLOC_FREE(old_full_fname);
593 0 : old_cap_smb_fname = synthetic_smb_fname(talloc_tos(),
594 : capold,
595 : NULL,
596 : NULL,
597 0 : old_smb_fname->twrp,
598 0 : old_smb_fname->flags);
599 0 : if (old_cap_smb_fname == NULL) {
600 0 : goto nomem_out;
601 : }
602 :
603 : /* Process 'new' name. */
604 0 : new_full_fname = full_path_from_dirfsp_atname(talloc_tos(),
605 : dstfsp,
606 : new_smb_fname);
607 0 : if (new_full_fname == NULL) {
608 0 : goto nomem_out;
609 : }
610 0 : capnew = capencode(talloc_tos(), new_full_fname->base_name);
611 0 : if (capnew == NULL) {
612 0 : goto nomem_out;
613 : }
614 0 : TALLOC_FREE(new_full_fname);
615 0 : new_cap_smb_fname = synthetic_smb_fname(talloc_tos(),
616 : capnew,
617 : NULL,
618 : NULL,
619 0 : new_smb_fname->twrp,
620 0 : new_smb_fname->flags);
621 0 : if (new_cap_smb_fname == NULL) {
622 0 : goto nomem_out;
623 : }
624 :
625 0 : ret = SMB_VFS_NEXT_LINKAT(handle,
626 : handle->conn->cwd_fsp,
627 : old_cap_smb_fname,
628 : handle->conn->cwd_fsp,
629 : new_cap_smb_fname,
630 : flags);
631 0 : if (ret == -1) {
632 0 : saved_errno = errno;
633 : }
634 0 : TALLOC_FREE(old_full_fname);
635 0 : TALLOC_FREE(old_full_fname);
636 0 : TALLOC_FREE(capold);
637 0 : TALLOC_FREE(capnew);
638 0 : TALLOC_FREE(old_cap_smb_fname);
639 0 : TALLOC_FREE(new_cap_smb_fname);
640 0 : if (saved_errno != 0) {
641 0 : errno = saved_errno;
642 : }
643 0 : return ret;
644 :
645 0 : nomem_out:
646 :
647 0 : TALLOC_FREE(old_full_fname);
648 0 : TALLOC_FREE(old_full_fname);
649 0 : TALLOC_FREE(capold);
650 0 : TALLOC_FREE(capnew);
651 0 : TALLOC_FREE(old_cap_smb_fname);
652 0 : TALLOC_FREE(new_cap_smb_fname);
653 0 : errno = ENOMEM;
654 0 : return -1;
655 : }
656 :
657 0 : static int cap_mknodat(vfs_handle_struct *handle,
658 : files_struct *dirfsp,
659 : const struct smb_filename *smb_fname,
660 : mode_t mode,
661 : SMB_DEV_T dev)
662 : {
663 0 : struct smb_filename *full_fname = NULL;
664 0 : struct smb_filename *cap_smb_fname = NULL;
665 0 : char *cappath = NULL;
666 : int ret;
667 0 : int saved_errno = 0;
668 :
669 0 : full_fname = full_path_from_dirfsp_atname(talloc_tos(),
670 : dirfsp,
671 : smb_fname);
672 0 : if (full_fname == NULL) {
673 0 : return -1;
674 : }
675 :
676 0 : cappath = capencode(talloc_tos(), full_fname->base_name);
677 0 : if (!cappath) {
678 0 : TALLOC_FREE(full_fname);
679 0 : errno = ENOMEM;
680 0 : return -1;
681 : }
682 0 : cap_smb_fname = synthetic_smb_fname(talloc_tos(),
683 : cappath,
684 : NULL,
685 : NULL,
686 0 : smb_fname->twrp,
687 0 : smb_fname->flags);
688 0 : if (cap_smb_fname == NULL) {
689 0 : TALLOC_FREE(full_fname);
690 0 : TALLOC_FREE(cappath);
691 0 : errno = ENOMEM;
692 0 : return -1;
693 : }
694 0 : ret = SMB_VFS_NEXT_MKNODAT(handle,
695 : handle->conn->cwd_fsp,
696 : cap_smb_fname,
697 : mode,
698 : dev);
699 0 : if (ret == -1) {
700 0 : saved_errno = errno;
701 : }
702 0 : TALLOC_FREE(full_fname);
703 0 : TALLOC_FREE(cappath);
704 0 : TALLOC_FREE(cap_smb_fname);
705 0 : if (saved_errno != 0) {
706 0 : errno = saved_errno;
707 : }
708 0 : return ret;
709 : }
710 :
711 0 : static struct smb_filename *cap_realpath(vfs_handle_struct *handle,
712 : TALLOC_CTX *ctx,
713 : const struct smb_filename *smb_fname)
714 : {
715 : /* monyo need capencode'ed and capdecode'ed? */
716 0 : struct smb_filename *cap_smb_fname = NULL;
717 0 : struct smb_filename *return_fname = NULL;
718 0 : char *cappath = capencode(talloc_tos(), smb_fname->base_name);
719 0 : int saved_errno = 0;
720 :
721 0 : if (!cappath) {
722 0 : errno = ENOMEM;
723 0 : return NULL;
724 : }
725 0 : cap_smb_fname = synthetic_smb_fname(ctx,
726 : cappath,
727 : NULL,
728 : NULL,
729 0 : smb_fname->twrp,
730 0 : smb_fname->flags);
731 0 : if (cap_smb_fname == NULL) {
732 0 : TALLOC_FREE(cappath);
733 0 : errno = ENOMEM;
734 0 : return NULL;
735 : }
736 0 : return_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, cap_smb_fname);
737 0 : if (return_fname == NULL) {
738 0 : saved_errno = errno;
739 : }
740 0 : TALLOC_FREE(cappath);
741 0 : TALLOC_FREE(cap_smb_fname);
742 0 : if (saved_errno != 0) {
743 0 : errno = saved_errno;
744 : }
745 0 : return return_fname;
746 : }
747 :
748 0 : static ssize_t cap_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path, void *value, size_t size)
749 : {
750 0 : char *cappath = capencode(talloc_tos(), path);
751 :
752 0 : if (!cappath) {
753 0 : errno = ENOMEM;
754 0 : return -1;
755 : }
756 0 : return SMB_VFS_NEXT_FGETXATTR(handle, fsp, cappath, value, size);
757 : }
758 :
759 0 : static int cap_fremovexattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path)
760 : {
761 0 : char *cappath = capencode(talloc_tos(), path);
762 :
763 0 : if (!cappath) {
764 0 : errno = ENOMEM;
765 0 : return -1;
766 : }
767 0 : return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, cappath);
768 : }
769 :
770 0 : static int cap_fsetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path, const void *value, size_t size, int flags)
771 : {
772 0 : char *cappath = capencode(talloc_tos(), path);
773 :
774 0 : if (!cappath) {
775 0 : errno = ENOMEM;
776 0 : return -1;
777 : }
778 0 : return SMB_VFS_NEXT_FSETXATTR(handle, fsp, cappath, value, size, flags);
779 : }
780 :
781 0 : static NTSTATUS cap_create_dfs_pathat(vfs_handle_struct *handle,
782 : files_struct *dirfsp,
783 : const struct smb_filename *smb_fname,
784 : const struct referral *reflist,
785 : size_t referral_count)
786 : {
787 0 : char *cappath = capencode(talloc_tos(), smb_fname->base_name);
788 0 : struct smb_filename *cap_smb_fname = NULL;
789 : NTSTATUS status;
790 :
791 0 : if (cappath == NULL) {
792 0 : return NT_STATUS_NO_MEMORY;
793 : }
794 0 : cap_smb_fname = synthetic_smb_fname(talloc_tos(),
795 : cappath,
796 : NULL,
797 : NULL,
798 0 : smb_fname->twrp,
799 0 : smb_fname->flags);
800 0 : if (cap_smb_fname == NULL) {
801 0 : TALLOC_FREE(cappath);
802 0 : return NT_STATUS_NO_MEMORY;
803 : }
804 0 : status = SMB_VFS_NEXT_CREATE_DFS_PATHAT(handle,
805 : dirfsp,
806 : cap_smb_fname,
807 : reflist,
808 : referral_count);
809 0 : TALLOC_FREE(cappath);
810 0 : TALLOC_FREE(cap_smb_fname);
811 0 : return status;
812 : }
813 :
814 0 : static NTSTATUS cap_read_dfs_pathat(struct vfs_handle_struct *handle,
815 : TALLOC_CTX *mem_ctx,
816 : struct files_struct *dirfsp,
817 : struct smb_filename *smb_fname,
818 : struct referral **ppreflist,
819 : size_t *preferral_count)
820 : {
821 0 : struct smb_filename *full_fname = NULL;
822 0 : struct smb_filename *cap_smb_fname = NULL;
823 0 : char *cappath = NULL;
824 : NTSTATUS status;
825 :
826 0 : full_fname = full_path_from_dirfsp_atname(talloc_tos(),
827 : dirfsp,
828 : smb_fname);
829 0 : if (full_fname == NULL) {
830 0 : return NT_STATUS_NO_MEMORY;
831 : }
832 0 : cappath = capencode(talloc_tos(), full_fname->base_name);
833 0 : if (cappath == NULL) {
834 0 : TALLOC_FREE(full_fname);
835 0 : return NT_STATUS_NO_MEMORY;
836 : }
837 0 : cap_smb_fname = synthetic_smb_fname(talloc_tos(),
838 : cappath,
839 : NULL,
840 : NULL,
841 : smb_fname->twrp,
842 : smb_fname->flags);
843 0 : if (cap_smb_fname == NULL) {
844 0 : TALLOC_FREE(full_fname);
845 0 : TALLOC_FREE(cappath);
846 0 : return NT_STATUS_NO_MEMORY;
847 : }
848 :
849 0 : status = SMB_VFS_NEXT_READ_DFS_PATHAT(handle,
850 : mem_ctx,
851 : handle->conn->cwd_fsp,
852 : cap_smb_fname,
853 : ppreflist,
854 : preferral_count);
855 :
856 0 : if (NT_STATUS_IS_OK(status)) {
857 : /* Return any stat(2) info. */
858 0 : smb_fname->st = cap_smb_fname->st;
859 : }
860 :
861 0 : TALLOC_FREE(full_fname);
862 0 : TALLOC_FREE(cappath);
863 0 : TALLOC_FREE(cap_smb_fname);
864 0 : return status;
865 : }
866 :
867 : static struct vfs_fn_pointers vfs_cap_fns = {
868 : .disk_free_fn = cap_disk_free,
869 : .get_quota_fn = cap_get_quota,
870 : .readdir_fn = cap_readdir,
871 : .mkdirat_fn = cap_mkdirat,
872 : .openat_fn = cap_openat,
873 : .renameat_fn = cap_renameat,
874 : .stat_fn = cap_stat,
875 : .lstat_fn = cap_lstat,
876 : .unlinkat_fn = cap_unlinkat,
877 : .lchown_fn = cap_lchown,
878 : .chdir_fn = cap_chdir,
879 : .symlinkat_fn = cap_symlinkat,
880 : .readlinkat_fn = cap_readlinkat,
881 : .linkat_fn = cap_linkat,
882 : .mknodat_fn = cap_mknodat,
883 : .realpath_fn = cap_realpath,
884 : .getxattrat_send_fn = vfs_not_implemented_getxattrat_send,
885 : .getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv,
886 : .fgetxattr_fn = cap_fgetxattr,
887 : .fremovexattr_fn = cap_fremovexattr,
888 : .fsetxattr_fn = cap_fsetxattr,
889 : .create_dfs_pathat_fn = cap_create_dfs_pathat,
890 : .read_dfs_pathat_fn = cap_read_dfs_pathat
891 : };
892 :
893 : static_decl_vfs;
894 27 : NTSTATUS vfs_cap_init(TALLOC_CTX *ctx)
895 : {
896 27 : return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "cap",
897 : &vfs_cap_fns);
898 : }
899 :
900 : /* For CAP functions */
901 : #define hex_tag ':'
902 : #define hex2bin(c) hex2bin_table[(unsigned char)(c)]
903 : #define bin2hex(c) bin2hex_table[(unsigned char)(c)]
904 : #define is_hex(s) ((s)[0] == hex_tag)
905 :
906 : static unsigned char hex2bin_table[256] = {
907 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
908 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
909 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
910 : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
911 : 0000, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0000, /* 0x40 */
912 : 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
913 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
914 : 0000, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0000, /* 0x60 */
915 : 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
916 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 */
917 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 */
918 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 */
919 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 */
920 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 */
921 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 */
922 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 */
923 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 */
924 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xf0 */
925 : };
926 : static unsigned char bin2hex_table[256] = "0123456789abcdef";
927 :
928 : /*******************************************************************
929 : original code -> ":xx" - CAP format
930 : ********************************************************************/
931 :
932 0 : static char *capencode(TALLOC_CTX *ctx, const char *from)
933 : {
934 0 : char *out = NULL;
935 : const char *p1;
936 0 : char *to = NULL;
937 0 : size_t len = 0;
938 :
939 0 : for (p1 = from; *p1; p1++) {
940 0 : if ((unsigned char)*p1 >= 0x80) {
941 0 : len += 3;
942 : } else {
943 0 : len++;
944 : }
945 : }
946 0 : len++;
947 :
948 0 : to = talloc_array(ctx, char, len);
949 0 : if (!to) {
950 0 : return NULL;
951 : }
952 :
953 0 : for (out = to; *from;) {
954 : /* buffer husoku error */
955 0 : if ((unsigned char)*from >= 0x80) {
956 0 : *out++ = hex_tag;
957 0 : *out++ = bin2hex (((*from)>>4)&0x0f);
958 0 : *out++ = bin2hex ((*from)&0x0f);
959 0 : from++;
960 : } else {
961 0 : *out++ = *from++;
962 : }
963 : }
964 0 : *out = '\0';
965 0 : return to;
966 : }
967 :
968 : /*******************************************************************
969 : CAP -> original code
970 : ********************************************************************/
971 : /* ":xx" -> a byte */
972 :
973 0 : static char *capdecode(TALLOC_CTX *ctx, const char *from)
974 : {
975 : const char *p1;
976 0 : char *out = NULL;
977 0 : char *to = NULL;
978 0 : size_t len = 0;
979 :
980 0 : for (p1 = from; *p1; len++) {
981 0 : if (is_hex(p1)) {
982 0 : p1 += 3;
983 : } else {
984 0 : p1++;
985 : }
986 : }
987 0 : len++;
988 :
989 0 : to = talloc_array(ctx, char, len);
990 0 : if (!to) {
991 0 : return NULL;
992 : }
993 :
994 0 : for (out = to; *from;) {
995 0 : if (is_hex(from)) {
996 0 : *out++ = (hex2bin(from[1])<<4) | (hex2bin(from[2]));
997 0 : from += 3;
998 : } else {
999 0 : *out++ = *from++;
1000 : }
1001 : }
1002 0 : *out = '\0';
1003 0 : return to;
1004 : }
|