~ubuntu-branches/ubuntu/vivid/samba/vivid

« back to all changes in this revision

Viewing changes to source3/libsmb/libsmb_dir.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:
23
23
*/
24
24
 
25
25
#include "includes.h"
 
26
#include "libsmb/libsmb.h"
 
27
#include "popt_common.h"
26
28
#include "libsmbclient.h"
27
29
#include "libsmb_internal.h"
28
 
#include "../librpc/gen_ndr/cli_srvsvc.h"
 
30
#include "rpc_client/cli_pipe.h"
 
31
#include "../librpc/gen_ndr/ndr_srvsvc_c.h"
 
32
#include "libsmb/nmblib.h"
29
33
 
30
34
/*
31
35
 * Routine to open a directory
146
150
        dirent_type = dir->dir_type;
147
151
 
148
152
        if (add_dirent(dir, name, comment, dirent_type) < 0) {
149
 
 
150
153
                /* An error occurred, what do we do? */
151
154
                /* FIXME: Add some code here */
 
155
                /* Change cli_NetServerEnum to take a fn
 
156
                   returning NTSTATUS... JRA. */
152
157
        }
153
158
 
154
159
        /* Point to the one just added */
226
231
        }
227
232
 
228
233
        if (add_dirent(dir, name, comment, dirent_type) < 0) {
229
 
 
230
234
                /* An error occurred, what do we do? */
231
235
                /* FIXME: Add some code here */
232
 
 
 
236
                /* Change cli_NetServerEnum to take a fn
 
237
                   returning NTSTATUS... JRA. */
233
238
        }
234
239
}
235
240
 
236
 
static void
 
241
static NTSTATUS
237
242
dir_list_fn(const char *mnt,
238
 
            file_info *finfo,
 
243
            struct file_info *finfo,
239
244
            const char *mask,
240
245
            void *state)
241
246
{
242
247
 
243
248
        if (add_dirent((SMBCFILE *)state, finfo->name, "",
244
 
                       (finfo->mode&aDIR?SMBC_DIR:SMBC_FILE)) < 0) {
245
 
 
246
 
                /* Handle an error ... */
247
 
 
248
 
                /* FIXME: Add some code ... */
249
 
 
 
249
                       (finfo->mode&FILE_ATTRIBUTE_DIRECTORY?SMBC_DIR:SMBC_FILE)) < 0) {
 
250
                SMBCFILE *dir = (SMBCFILE *)state;
 
251
                return map_nt_error_from_unix(dir->dir_error);
250
252
        }
251
 
 
 
253
        return NT_STATUS_OK;
252
254
}
253
255
 
254
256
static int
271
273
        NTSTATUS nt_status;
272
274
        uint32_t resume_handle = 0;
273
275
        uint32_t total_entries = 0;
 
276
        struct dcerpc_binding_handle *b;
274
277
 
275
278
        /* Open the server service pipe */
276
279
        nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc.syntax_id,
286
289
        info_ctr.level = 1;
287
290
        info_ctr.ctr.ctr1 = &ctr1;
288
291
 
 
292
        b = pipe_hnd->binding_handle;
 
293
 
289
294
        /* Issue the NetShareEnum RPC call and retrieve the response */
290
 
        nt_status = rpccli_srvsvc_NetShareEnumAll(pipe_hnd, talloc_tos(),
 
295
        nt_status = dcerpc_srvsvc_NetShareEnumAll(b, talloc_tos(),
291
296
                                                  pipe_hnd->desthost,
292
297
                                                  &info_ctr,
293
298
                                                  preferred_len,
296
301
                                                  &result);
297
302
 
298
303
        /* Was it successful? */
299
 
        if (!NT_STATUS_IS_OK(nt_status) || !W_ERROR_IS_OK(result) ||
300
 
            total_entries == 0) {
 
304
        if (!NT_STATUS_IS_OK(nt_status)) {
 
305
                /*  Nope.  Go clean up. */
 
306
                result = ntstatus_to_werror(nt_status);
 
307
                goto done;
 
308
        }
 
309
 
 
310
        if (!W_ERROR_IS_OK(result)) {
301
311
                /*  Nope.  Go clean up. */
302
312
                goto done;
303
313
        }
304
314
 
 
315
        if (total_entries == 0) {
 
316
                /*  Nope.  Go clean up. */
 
317
                result = WERR_GENERAL_FAILURE;
 
318
                goto done;
 
319
        }
 
320
 
305
321
        /* For each returned entry... */
306
322
        for (i = 0; i < info_ctr.ctr.ctr1->count; i++) {
307
323
 
369
385
 
370
386
        if (!context || !context->internal->initialized) {
371
387
                DEBUG(4, ("no valid context\n"));
 
388
                TALLOC_FREE(frame);
372
389
                errno = EINVAL + 8192;
373
 
                TALLOC_FREE(frame);
374
390
                return NULL;
375
391
 
376
392
        }
377
393
 
378
394
        if (!fname) {
379
395
                DEBUG(4, ("no valid fname\n"));
 
396
                TALLOC_FREE(frame);
380
397
                errno = EINVAL + 8193;
381
 
                TALLOC_FREE(frame);
382
398
                return NULL;
383
399
        }
384
400
 
393
409
                            &password,
394
410
                            &options)) {
395
411
                DEBUG(4, ("no valid path\n"));
 
412
                TALLOC_FREE(frame);
396
413
                errno = EINVAL + 8194;
397
 
                TALLOC_FREE(frame);
398
414
                return NULL;
399
415
        }
400
416
 
405
421
        /* Ensure the options are valid */
406
422
        if (SMBC_check_options(server, share, path, options)) {
407
423
                DEBUG(4, ("unacceptable options (%s)\n", options));
 
424
                TALLOC_FREE(frame);
408
425
                errno = EINVAL + 8195;
409
 
                TALLOC_FREE(frame);
410
426
                return NULL;
411
427
        }
412
428
 
413
429
        if (!user || user[0] == (char)0) {
414
430
                user = talloc_strdup(frame, smbc_getUser(context));
415
431
                if (!user) {
 
432
                        TALLOC_FREE(frame);
416
433
                        errno = ENOMEM;
417
 
                        TALLOC_FREE(frame);
418
434
                        return NULL;
419
435
                }
420
436
        }
422
438
        dir = SMB_MALLOC_P(SMBCFILE);
423
439
 
424
440
        if (!dir) {
 
441
                TALLOC_FREE(frame);
425
442
                errno = ENOMEM;
426
 
                TALLOC_FREE(frame);
427
443
                return NULL;
428
444
        }
429
445
 
441
457
                int i;
442
458
                int count;
443
459
                int max_lmb_count;
444
 
                struct ip_service *ip_list;
445
 
                struct ip_service server_addr;
 
460
                struct sockaddr_storage *ip_list;
 
461
                struct sockaddr_storage server_addr;
446
462
                struct user_auth_info u_info;
 
463
                NTSTATUS status;
447
464
 
448
465
                if (share[0] != (char)0 || path[0] != (char)0) {
449
466
 
 
467
                        if (dir) {
 
468
                                SAFE_FREE(dir->fname);
 
469
                                SAFE_FREE(dir);
 
470
                        }
 
471
                        TALLOC_FREE(frame);
450
472
                        errno = EINVAL + 8196;
451
 
                        if (dir) {
452
 
                                SAFE_FREE(dir->fname);
453
 
                                SAFE_FREE(dir);
454
 
                        }
455
 
                        TALLOC_FREE(frame);
456
473
                        return NULL;
457
474
                }
458
475
 
483
500
                 */
484
501
 
485
502
                ip_list = NULL;
486
 
                if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
487
 
                                                        &count)))
 
503
                status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
 
504
                                            &ip_list, &count);
 
505
                if (!NT_STATUS_IS_OK(status))
488
506
                {
489
507
 
490
 
                        SAFE_FREE(ip_list);
 
508
                        TALLOC_FREE(ip_list);
491
509
 
492
 
                        if (!find_master_ip(workgroup, &server_addr.ss)) {
 
510
                        if (!find_master_ip(workgroup, &server_addr)) {
493
511
 
494
512
                                if (dir) {
495
513
                                        SAFE_FREE(dir->fname);
496
514
                                        SAFE_FREE(dir);
497
515
                                }
 
516
                                TALLOC_FREE(frame);
498
517
                                errno = ENOENT;
499
 
                                TALLOC_FREE(frame);
500
518
                                return NULL;
501
519
                        }
502
520
 
503
 
                        ip_list = (struct ip_service *)memdup(
504
 
                                &server_addr, sizeof(server_addr));
 
521
                        ip_list = (struct sockaddr_storage *)talloc_memdup(
 
522
                                talloc_tos(), &server_addr,
 
523
                                sizeof(server_addr));
505
524
                        if (ip_list == NULL) {
 
525
                                if (dir) {
 
526
                                        SAFE_FREE(dir->fname);
 
527
                                        SAFE_FREE(dir);
 
528
                                }
 
529
                                TALLOC_FREE(frame);
506
530
                                errno = ENOMEM;
507
 
                                TALLOC_FREE(frame);
508
531
                                return NULL;
509
532
                        }
510
533
                        count = 1;
515
538
                        char *wg_ptr = NULL;
516
539
                        struct cli_state *cli = NULL;
517
540
 
518
 
                        print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
 
541
                        print_sockaddr(addr, sizeof(addr), &ip_list[i]);
519
542
                        DEBUG(99, ("Found master browser %d of %d: %s\n",
520
543
                                   i+1, MAX(count, max_lmb_count),
521
544
                                   addr));
536
559
                        cli_shutdown(cli);
537
560
 
538
561
                        if (!workgroup || !server) {
 
562
                                if (dir) {
 
563
                                        SAFE_FREE(dir->fname);
 
564
                                        SAFE_FREE(dir);
 
565
                                }
 
566
                                TALLOC_FREE(frame);
539
567
                                errno = ENOMEM;
540
 
                                TALLOC_FREE(frame);
541
568
                                return NULL;
542
569
                        }
543
570
 
571
598
                        }
572
599
                }
573
600
 
574
 
                SAFE_FREE(ip_list);
 
601
                TALLOC_FREE(ip_list);
575
602
        } else {
576
603
                /*
577
604
                 * Server not an empty string ... Check the rest and see what
581
608
                        if (*path != '\0') {
582
609
 
583
610
                                /* Should not have empty share with path */
 
611
                                if (dir) {
 
612
                                        SAFE_FREE(dir->fname);
 
613
                                        SAFE_FREE(dir);
 
614
                                }
 
615
                                TALLOC_FREE(frame);
584
616
                                errno = EINVAL + 8197;
585
 
                                if (dir) {
586
 
                                        SAFE_FREE(dir->fname);
587
 
                                        SAFE_FREE(dir);
588
 
                                }
589
 
                                TALLOC_FREE(frame);
590
617
                                return NULL;
591
618
 
592
619
                        }
644
671
                                                SAFE_FREE(dir->fname);
645
672
                                                SAFE_FREE(dir);
646
673
                                        }
 
674
                                        TALLOC_FREE(frame);
647
675
                                        errno = EPERM;
648
 
                                        TALLOC_FREE(frame);
649
676
                                        return NULL;
650
677
 
651
678
                                }
748
775
                         */
749
776
                        char *targetpath;
750
777
                        struct cli_state *targetcli;
 
778
                        NTSTATUS status;
751
779
 
752
780
                        /* We connect to the server and list the directory */
753
781
                        dir->dir_type = SMBC_FILE_SHARE;
791
819
                                return NULL;
792
820
                        }
793
821
 
794
 
                        if (cli_list(targetcli, targetpath,
795
 
                                     aDIR | aSYSTEM | aHIDDEN,
796
 
                                     dir_list_fn, (void *)dir) < 0) {
797
 
 
 
822
                        status = cli_list(targetcli, targetpath,
 
823
                                          FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN,
 
824
                                          dir_list_fn, (void *)dir);
 
825
                        if (!NT_STATUS_IS_OK(status)) {
798
826
                                if (dir) {
799
827
                                        SAFE_FREE(dir->fname);
800
828
                                        SAFE_FREE(dir);
844
872
                                        }
845
873
                                }
846
874
 
 
875
                                TALLOC_FREE(frame);
847
876
                                errno = saved_errno;
848
 
                                TALLOC_FREE(frame);
849
877
                                return NULL;
850
878
                        }
851
879
                }
1048
1076
 
1049
1077
        while ((dirlist = dir->dir_next)) {
1050
1078
                struct smbc_dirent *dirent;
 
1079
                struct smbc_dirent *currentEntry = (struct smbc_dirent *)ndir;
1051
1080
 
1052
1081
                if (!dirlist->dirent) {
1053
1082
 
1084
1113
 
1085
1114
                }
1086
1115
 
1087
 
                memcpy(ndir, dirent, reqd); /* Copy the data in ... */
 
1116
                memcpy(currentEntry, dirent, reqd); /* Copy the data in ... */
1088
1117
 
1089
 
                ((struct smbc_dirent *)ndir)->comment =
1090
 
                        (char *)(&((struct smbc_dirent *)ndir)->name +
1091
 
                                 dirent->namelen +
1092
 
                                 1);
 
1118
                currentEntry->comment = &currentEntry->name[0] +
 
1119
                                                dirent->namelen + 1;
1093
1120
 
1094
1121
                ndir += reqd;
1095
 
 
1096
1122
                rem -= reqd;
1097
1123
 
 
1124
                /* Try and align the struct for the next entry
 
1125
                   on a valid pointer boundary by appending zeros */
 
1126
                while((rem > 0) && ((unsigned long long)ndir & (sizeof(void*) - 1))) {
 
1127
                        *ndir = '\0';
 
1128
                        rem--;
 
1129
                        ndir++;
 
1130
                        currentEntry->dirlen++;
 
1131
                }
 
1132
 
1098
1133
                dir->dir_next = dirlist = dirlist -> next;
1099
1134
        }
1100
1135
 
1202
1237
 * Our list function simply checks to see if a directory is not empty
1203
1238
 */
1204
1239
 
1205
 
static void
 
1240
static NTSTATUS
1206
1241
rmdir_list_fn(const char *mnt,
1207
 
              file_info *finfo,
 
1242
              struct file_info *finfo,
1208
1243
              const char *mask,
1209
1244
              void *state)
1210
1245
{
1213
1248
                bool *smbc_rmdir_dirempty = (bool *)state;
1214
1249
                *smbc_rmdir_dirempty = false;
1215
1250
        }
 
1251
        return NT_STATUS_OK;
1216
1252
}
1217
1253
 
1218
1254
/*
1302
1338
                        /* Local storage to avoid buffer overflows */
1303
1339
                        char *lpath;
1304
1340
                        bool smbc_rmdir_dirempty = true;
 
1341
                        NTSTATUS status;
1305
1342
 
1306
1343
                        lpath = talloc_asprintf(frame, "%s\\*",
1307
1344
                                                targetpath);
1311
1348
                                return -1;
1312
1349
                        }
1313
1350
 
1314
 
                        if (cli_list(targetcli, lpath,
1315
 
                                     aDIR | aSYSTEM | aHIDDEN,
1316
 
                                     rmdir_list_fn,
1317
 
                                     &smbc_rmdir_dirempty) < 0) {
 
1351
                        status = cli_list(targetcli, lpath,
 
1352
                                          FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN,
 
1353
                                          rmdir_list_fn,
 
1354
                                          &smbc_rmdir_dirempty);
1318
1355
 
 
1356
                        if (!NT_STATUS_IS_OK(status)) {
1319
1357
                                /* Fix errno to ignore latest error ... */
1320
1358
                                DEBUG(5, ("smbc_rmdir: "
1321
1359
                                          "cli_list returned an error: %d\n",
1577
1615
 
1578
1616
        mode = 0;
1579
1617
 
1580
 
        if (!(newmode & (S_IWUSR | S_IWGRP | S_IWOTH))) mode |= aRONLY;
1581
 
        if ((newmode & S_IXUSR) && lp_map_archive(-1)) mode |= aARCH;
1582
 
        if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= aSYSTEM;
1583
 
        if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= aHIDDEN;
 
1618
        if (!(newmode & (S_IWUSR | S_IWGRP | S_IWOTH))) mode |= FILE_ATTRIBUTE_READONLY;
 
1619
        if ((newmode & S_IXUSR) && lp_map_archive(-1)) mode |= FILE_ATTRIBUTE_ARCHIVE;
 
1620
        if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= FILE_ATTRIBUTE_SYSTEM;
 
1621
        if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= FILE_ATTRIBUTE_HIDDEN;
1584
1622
 
1585
1623
        if (!NT_STATUS_IS_OK(cli_setatr(targetcli, targetpath, mode, 0))) {
1586
1624
                errno = SMBC_errno(context, targetcli);
1769
1807
        }
1770
1808
        /*d_printf(">>>unlink: resolved path as %s\n", targetpath);*/
1771
1809
 
1772
 
        if (!NT_STATUS_IS_OK(cli_unlink(targetcli, targetpath, aSYSTEM | aHIDDEN))) {
 
1810
        if (!NT_STATUS_IS_OK(cli_unlink(targetcli, targetpath, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN))) {
1773
1811
 
1774
1812
                errno = SMBC_errno(context, targetcli);
1775
1813
 
1975
2013
                int eno = SMBC_errno(ocontext, targetcli1);
1976
2014
 
1977
2015
                if (eno != EEXIST ||
1978
 
                    !NT_STATUS_IS_OK(cli_unlink(targetcli1, targetpath2, aSYSTEM | aHIDDEN)) ||
 
2016
                    !NT_STATUS_IS_OK(cli_unlink(targetcli1, targetpath2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)) ||
1979
2017
                    !NT_STATUS_IS_OK(cli_rename(targetcli1, targetpath1, targetpath2))) {
1980
2018
 
1981
2019
                        errno = eno;