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