~lefteris-nikoltsios/+junk/samba-lp1016895

« back to all changes in this revision

Viewing changes to source3/libsmb/libsmb_xattr.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:
7
7
   Copyright (C) Tom Jansen (Ninja ISD) 2002 
8
8
   Copyright (C) Derrell Lipman 2003-2008
9
9
   Copyright (C) Jeremy Allison 2007, 2008
10
 
   
 
10
 
11
11
   This program is free software; you can redistribute it and/or modify
12
12
   it under the terms of the GNU General Public License as published by
13
13
   the Free Software Foundation; either version 3 of the License, or
14
14
   (at your option) any later version.
15
 
   
 
15
 
16
16
   This program is distributed in the hope that it will be useful,
17
17
   but WITHOUT ANY WARRANTY; without even the implied warranty of
18
18
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
19
   GNU General Public License for more details.
20
 
   
 
20
 
21
21
   You should have received a copy of the GNU General Public License
22
22
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
23
23
*/
24
24
 
25
25
#include "includes.h"
 
26
#include "libsmb/libsmb.h"
26
27
#include "libsmbclient.h"
27
28
#include "libsmb_internal.h"
28
 
 
 
29
#include "../librpc/gen_ndr/ndr_lsa.h"
 
30
#include "rpc_client/rpc_client.h"
 
31
#include "rpc_client/cli_lsarpc.h"
 
32
#include "../libcli/security/security.h"
29
33
 
30
34
/*
31
35
 * Find an lsa pipe handle associated with a cli struct.
34
38
find_lsa_pipe_hnd(struct cli_state *ipc_cli)
35
39
{
36
40
        struct rpc_pipe_client *pipe_hnd;
37
 
        
 
41
 
38
42
        for (pipe_hnd = ipc_cli->pipe_list;
39
43
             pipe_hnd;
40
44
             pipe_hnd = pipe_hnd->next) {
41
 
                
42
45
                if (ndr_syntax_id_equal(&pipe_hnd->abstract_syntax,
43
46
                                        &ndr_table_lsarpc.syntax_id)) {
44
47
                        return pipe_hnd;
45
48
                }
46
49
        }
47
 
        
48
50
        return NULL;
49
51
}
50
52
 
55
57
 */
56
58
 
57
59
static int
58
 
ace_compare(SEC_ACE *ace1,
59
 
            SEC_ACE *ace2)
 
60
ace_compare(struct security_ace *ace1,
 
61
            struct security_ace *ace2)
60
62
{
61
63
        bool b1;
62
64
        bool b2;
63
 
        
 
65
 
64
66
        /* If the ACEs are equal, we have nothing more to do. */
65
67
        if (sec_ace_equal(ace1, ace2)) {
66
68
                return 0;
67
69
        }
68
 
        
 
70
 
69
71
        /* Inherited follow non-inherited */
70
72
        b1 = ((ace1->flags & SEC_ACE_FLAG_INHERITED_ACE) != 0);
71
73
        b2 = ((ace2->flags & SEC_ACE_FLAG_INHERITED_ACE) != 0);
72
74
        if (b1 != b2) {
73
75
                return (b1 ? 1 : -1);
74
76
        }
75
 
        
 
77
 
76
78
        /*
77
79
         * What shall we do with AUDITs and ALARMs?  It's undefined.  We'll
78
80
         * sort them after DENY and ALLOW.
88
90
        if (b1 != b2) {
89
91
                return (b1 ? 1 : -1);
90
92
        }
91
 
        
 
93
 
92
94
        /* Allowed ACEs follow denied ACEs */
93
95
        b1 = (ace1->type == SEC_ACE_TYPE_ACCESS_ALLOWED ||
94
96
              ace1->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT);
97
99
        if (b1 != b2) {
98
100
                return (b1 ? 1 : -1);
99
101
        }
100
 
        
 
102
 
101
103
        /*
102
104
         * ACEs applying to an entity's object follow those applying to the
103
105
         * entity itself
109
111
        if (b1 != b2) {
110
112
                return (b1 ? 1 : -1);
111
113
        }
112
 
        
 
114
 
113
115
        /*
114
116
         * If we get this far, the ACEs are similar as far as the
115
117
         * characteristics we typically care about (those defined by the
116
118
         * referenced MS document).  We'll now sort by characteristics that
117
119
         * just seems reasonable.
118
120
         */
119
 
        
 
121
 
120
122
        if (ace1->type != ace2->type) {
121
123
                return ace2->type - ace1->type;
122
124
        }
123
 
        
124
 
        if (sid_compare(&ace1->trustee, &ace2->trustee)) {
125
 
                return sid_compare(&ace1->trustee, &ace2->trustee);
 
125
 
 
126
        if (dom_sid_compare(&ace1->trustee, &ace2->trustee)) {
 
127
                return dom_sid_compare(&ace1->trustee, &ace2->trustee);
126
128
        }
127
 
        
 
129
 
128
130
        if (ace1->flags != ace2->flags) {
129
131
                return ace1->flags - ace2->flags;
130
132
        }
131
 
        
 
133
 
132
134
        if (ace1->access_mask != ace2->access_mask) {
133
135
                return ace1->access_mask - ace2->access_mask;
134
136
        }
135
 
        
 
137
 
136
138
        if (ace1->size != ace2->size) {
137
139
                return ace1->size - ace2->size;
138
140
        }
139
 
        
140
 
        return memcmp(ace1, ace2, sizeof(SEC_ACE));
 
141
 
 
142
        return memcmp(ace1, ace2, sizeof(struct security_ace));
141
143
}
142
144
 
143
145
 
144
146
static void
145
 
sort_acl(SEC_ACL *the_acl)
 
147
sort_acl(struct security_acl *the_acl)
146
148
{
147
149
        uint32 i;
148
150
        if (!the_acl) return;
149
 
        
150
 
        qsort(the_acl->aces, the_acl->num_aces, sizeof(the_acl->aces[0]),
151
 
              QSORT_CAST ace_compare);
152
 
        
 
151
 
 
152
        TYPESAFE_QSORT(the_acl->aces, the_acl->num_aces, ace_compare);
 
153
 
153
154
        for (i=1;i<the_acl->num_aces;) {
154
155
                if (sec_ace_equal(&the_acl->aces[i-1], &the_acl->aces[i])) {
155
156
                        int j;
169
170
                      struct policy_handle *pol,
170
171
                      fstring str,
171
172
                      bool numeric,
172
 
                      DOM_SID *sid)
 
173
                      struct dom_sid *sid)
173
174
{
174
175
        char **domains = NULL;
175
176
        char **names = NULL;
176
177
        enum lsa_SidType *types = NULL;
177
178
        struct rpc_pipe_client *pipe_hnd = find_lsa_pipe_hnd(ipc_cli);
178
179
        TALLOC_CTX *ctx;
179
 
        
 
180
 
180
181
        sid_to_fstring(str, sid);
181
 
        
 
182
 
182
183
        if (numeric) {
183
184
                return;     /* no lookup desired */
184
185
        }
185
 
        
 
186
 
186
187
        if (!pipe_hnd) {
187
188
                return;
188
189
        }
189
 
        
 
190
 
190
191
        /* Ask LSA to convert the sid to a name */
191
 
        
 
192
 
192
193
        ctx = talloc_stackframe();
193
 
        
 
194
 
194
195
        if (!NT_STATUS_IS_OK(rpccli_lsa_lookup_sids(pipe_hnd, ctx,
195
196
                                                    pol, 1, sid, &domains,
196
197
                                                    &names, &types)) ||
198
199
                TALLOC_FREE(ctx);
199
200
                return;
200
201
        }
201
 
        
 
202
 
202
203
        /* Converted OK */
203
 
        
 
204
 
204
205
        slprintf(str, sizeof(fstring) - 1, "%s%s%s",
205
206
                 domains[0], lp_winbind_separator(),
206
207
                 names[0]);
213
214
convert_string_to_sid(struct cli_state *ipc_cli,
214
215
                      struct policy_handle *pol,
215
216
                      bool numeric,
216
 
                      DOM_SID *sid,
 
217
                      struct dom_sid *sid,
217
218
                      const char *str)
218
219
{
219
220
        enum lsa_SidType *types = NULL;
220
 
        DOM_SID *sids = NULL;
 
221
        struct dom_sid *sids = NULL;
221
222
        bool result = True;
222
223
        TALLOC_CTX *ctx = NULL;
223
224
        struct rpc_pipe_client *pipe_hnd = find_lsa_pipe_hnd(ipc_cli);
224
 
        
 
225
 
225
226
        if (!pipe_hnd) {
226
227
                return False;
227
228
        }
228
 
        
 
229
 
229
230
        if (numeric) {
230
231
                if (strncmp(str, "S-", 2) == 0) {
231
232
                        return string_to_sid(sid, str);
232
233
                }
233
 
                
 
234
 
234
235
                result = False;
235
236
                goto done;
236
237
        }
237
 
        
 
238
 
238
239
        ctx = talloc_stackframe();
239
240
        if (!NT_STATUS_IS_OK(rpccli_lsa_lookup_names(pipe_hnd, ctx,
240
241
                                                     pol, 1, &str,
243
244
                result = False;
244
245
                goto done;
245
246
        }
246
 
        
 
247
 
247
248
        sid_copy(sid, &sids[0]);
248
249
done:
249
 
        
250
250
        TALLOC_FREE(ctx);
251
251
        return result;
252
252
}
253
253
 
254
254
 
255
 
/* parse an ACE in the same format as print_ace() */
 
255
/* parse an struct security_ace in the same format as print_ace() */
256
256
static bool
257
257
parse_ace(struct cli_state *ipc_cli,
258
258
          struct policy_handle *pol,
259
 
          SEC_ACE *ace,
 
259
          struct security_ace *ace,
260
260
          bool numeric,
261
261
          char *str)
262
262
{
266
266
        unsigned int atype;
267
267
        unsigned int aflags;
268
268
        unsigned int amask;
269
 
        DOM_SID sid;
 
269
        struct dom_sid sid;
270
270
        uint32_t mask;
271
271
        const struct perm_value *v;
272
272
        struct perm_value {
274
274
                uint32 mask;
275
275
        };
276
276
        TALLOC_CTX *frame = talloc_stackframe();
277
 
        
 
277
 
278
278
        /* These values discovered by inspection */
279
279
        static const struct perm_value special_values[] = {
280
280
                { "R", 0x00120089 },
285
285
                { "O", 0x00080000 },
286
286
                { "", 0 },
287
287
        };
288
 
        
 
288
 
289
289
        static const struct perm_value standard_values[] = {
290
290
                { "READ",   0x001200a9 },
291
291
                { "CHANGE", 0x001301bf },
292
292
                { "FULL",   0x001f01ff },
293
293
                { "", 0 },
294
294
        };
295
 
        
296
 
        
 
295
 
297
296
        ZERO_STRUCTP(ace);
298
297
        p = strchr_m(str,':');
299
298
        if (!p) {
303
302
        *p = '\0';
304
303
        p++;
305
304
        /* Try to parse numeric form */
306
 
        
 
305
 
307
306
        if (sscanf(p, "%i/%i/%i", &atype, &aflags, &amask) == 3 &&
308
307
            convert_string_to_sid(ipc_cli, pol, numeric, &sid, str)) {
309
308
                goto done;
310
309
        }
311
 
        
 
310
 
312
311
        /* Try to parse text form */
313
 
        
 
312
 
314
313
        if (!convert_string_to_sid(ipc_cli, pol, numeric, &sid, str)) {
315
314
                TALLOC_FREE(frame);
316
315
                return false;
317
316
        }
318
 
        
 
317
 
319
318
        cp = p;
320
319
        if (!next_token_talloc(frame, &cp, &tok, "/")) {
321
320
                TALLOC_FREE(frame);
322
321
                return false;
323
322
        }
324
 
        
 
323
 
325
324
        if (StrnCaseCmp(tok, "ALLOWED", strlen("ALLOWED")) == 0) {
326
325
                atype = SEC_ACE_TYPE_ACCESS_ALLOWED;
327
326
        } else if (StrnCaseCmp(tok, "DENIED", strlen("DENIED")) == 0) {
330
329
                TALLOC_FREE(frame);
331
330
                return false;
332
331
        }
333
 
        
 
332
 
334
333
        /* Only numeric form accepted for flags at present */
335
 
        
 
334
 
336
335
        if (!(next_token_talloc(frame, &cp, &tok, "/") &&
337
336
              sscanf(tok, "%i", &aflags))) {
338
337
                TALLOC_FREE(frame);
339
338
                return false;
340
339
        }
341
 
        
 
340
 
342
341
        if (!next_token_talloc(frame, &cp, &tok, "/")) {
343
342
                TALLOC_FREE(frame);
344
343
                return false;
345
344
        }
346
 
        
 
345
 
347
346
        if (strncmp(tok, "0x", 2) == 0) {
348
347
                if (sscanf(tok, "%i", &amask) != 1) {
349
348
                        TALLOC_FREE(frame);
351
350
                }
352
351
                goto done;
353
352
        }
354
 
        
 
353
 
355
354
        for (v = standard_values; v->perm; v++) {
356
355
                if (strcmp(tok, v->perm) == 0) {
357
356
                        amask = v->mask;
358
357
                        goto done;
359
358
                }
360
359
        }
361
 
        
 
360
 
362
361
        p = tok;
363
 
        
 
362
 
364
363
        while(*p) {
365
364
                bool found = False;
366
 
                
 
365
 
367
366
                for (v = special_values; v->perm; v++) {
368
367
                        if (v->perm[0] == *p) {
369
368
                                amask |= v->mask;
370
369
                                found = True;
371
370
                        }
372
371
                }
373
 
                
 
372
 
374
373
                if (!found) {
375
374
                        TALLOC_FREE(frame);
376
375
                        return false;
377
376
                }
378
377
                p++;
379
378
        }
380
 
        
 
379
 
381
380
        if (*p) {
382
381
                TALLOC_FREE(frame);
383
382
                return false;
384
383
        }
385
 
        
 
384
 
386
385
done:
387
386
        mask = amask;
388
387
        init_sec_ace(ace, &sid, atype, mask, aflags);
390
389
        return true;
391
390
}
392
391
 
393
 
/* add an ACE to a list of ACEs in a SEC_ACL */
 
392
/* add an struct security_ace to a list of struct security_aces in a struct security_acl */
394
393
static bool
395
 
add_ace(SEC_ACL **the_acl,
396
 
        SEC_ACE *ace,
 
394
add_ace(struct security_acl **the_acl,
 
395
        struct security_ace *ace,
397
396
        TALLOC_CTX *ctx)
398
397
{
399
 
        SEC_ACL *newacl;
400
 
        SEC_ACE *aces;
401
 
        
 
398
        struct security_acl *newacl;
 
399
        struct security_ace *aces;
 
400
 
402
401
        if (! *the_acl) {
403
402
                (*the_acl) = make_sec_acl(ctx, 3, 1, ace);
404
403
                return True;
405
404
        }
406
 
        
407
 
        if ((aces = SMB_CALLOC_ARRAY(SEC_ACE,
 
405
 
 
406
        if ((aces = SMB_CALLOC_ARRAY(struct security_ace,
408
407
                                     1+(*the_acl)->num_aces)) == NULL) {
409
408
                return False;
410
409
        }
411
 
        memcpy(aces, (*the_acl)->aces, (*the_acl)->num_aces * sizeof(SEC_ACE));
412
 
        memcpy(aces+(*the_acl)->num_aces, ace, sizeof(SEC_ACE));
 
410
        memcpy(aces, (*the_acl)->aces, (*the_acl)->num_aces * sizeof(struct security_ace));
 
411
        memcpy(aces+(*the_acl)->num_aces, ace, sizeof(struct security_ace));
413
412
        newacl = make_sec_acl(ctx, (*the_acl)->revision,
414
413
                              1+(*the_acl)->num_aces, aces);
415
414
        SAFE_FREE(aces);
419
418
 
420
419
 
421
420
/* parse a ascii version of a security descriptor */
422
 
static SEC_DESC *
 
421
static struct security_descriptor *
423
422
sec_desc_parse(TALLOC_CTX *ctx,
424
423
               struct cli_state *ipc_cli,
425
424
               struct policy_handle *pol,
428
427
{
429
428
        const char *p = str;
430
429
        char *tok;
431
 
        SEC_DESC *ret = NULL;
 
430
        struct security_descriptor *ret = NULL;
432
431
        size_t sd_size;
433
 
        DOM_SID *group_sid=NULL;
434
 
        DOM_SID *owner_sid=NULL;
435
 
        SEC_ACL *dacl=NULL;
 
432
        struct dom_sid *group_sid=NULL;
 
433
        struct dom_sid *owner_sid=NULL;
 
434
        struct security_acl *dacl=NULL;
436
435
        int revision=1;
437
 
        
 
436
 
438
437
        while (next_token_talloc(ctx, &p, &tok, "\t,\r\n")) {
439
 
                
 
438
 
440
439
                if (StrnCaseCmp(tok,"REVISION:", 9) == 0) {
441
440
                        revision = strtol(tok+9, NULL, 16);
442
441
                        continue;
443
442
                }
444
 
                
 
443
 
445
444
                if (StrnCaseCmp(tok,"OWNER:", 6) == 0) {
446
445
                        if (owner_sid) {
447
446
                                DEBUG(5,("OWNER specified more than once!\n"));
448
447
                                goto done;
449
448
                        }
450
 
                        owner_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
 
449
                        owner_sid = SMB_CALLOC_ARRAY(struct dom_sid, 1);
451
450
                        if (!owner_sid ||
452
451
                            !convert_string_to_sid(ipc_cli, pol,
453
452
                                                   numeric,
457
456
                        }
458
457
                        continue;
459
458
                }
460
 
                
 
459
 
461
460
                if (StrnCaseCmp(tok,"OWNER+:", 7) == 0) {
462
461
                        if (owner_sid) {
463
462
                                DEBUG(5,("OWNER specified more than once!\n"));
464
463
                                goto done;
465
464
                        }
466
 
                        owner_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
 
465
                        owner_sid = SMB_CALLOC_ARRAY(struct dom_sid, 1);
467
466
                        if (!owner_sid ||
468
467
                            !convert_string_to_sid(ipc_cli, pol,
469
468
                                                   False,
473
472
                        }
474
473
                        continue;
475
474
                }
476
 
                
 
475
 
477
476
                if (StrnCaseCmp(tok,"GROUP:", 6) == 0) {
478
477
                        if (group_sid) {
479
478
                                DEBUG(5,("GROUP specified more than once!\n"));
480
479
                                goto done;
481
480
                        }
482
 
                        group_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
 
481
                        group_sid = SMB_CALLOC_ARRAY(struct dom_sid, 1);
483
482
                        if (!group_sid ||
484
483
                            !convert_string_to_sid(ipc_cli, pol,
485
484
                                                   numeric,
489
488
                        }
490
489
                        continue;
491
490
                }
492
 
                
 
491
 
493
492
                if (StrnCaseCmp(tok,"GROUP+:", 7) == 0) {
494
493
                        if (group_sid) {
495
494
                                DEBUG(5,("GROUP specified more than once!\n"));
496
495
                                goto done;
497
496
                        }
498
 
                        group_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
 
497
                        group_sid = SMB_CALLOC_ARRAY(struct dom_sid, 1);
499
498
                        if (!group_sid ||
500
499
                            !convert_string_to_sid(ipc_cli, pol,
501
500
                                                   False,
505
504
                        }
506
505
                        continue;
507
506
                }
508
 
                
 
507
 
509
508
                if (StrnCaseCmp(tok,"ACL:", 4) == 0) {
510
 
                        SEC_ACE ace;
 
509
                        struct security_ace ace;
511
510
                        if (!parse_ace(ipc_cli, pol, &ace, numeric, tok+4)) {
512
511
                                DEBUG(5, ("Failed to parse ACL %s\n", tok));
513
512
                                goto done;
518
517
                        }
519
518
                        continue;
520
519
                }
521
 
                
 
520
 
522
521
                if (StrnCaseCmp(tok,"ACL+:", 5) == 0) {
523
 
                        SEC_ACE ace;
 
522
                        struct security_ace ace;
524
523
                        if (!parse_ace(ipc_cli, pol, &ace, False, tok+5)) {
525
524
                                DEBUG(5, ("Failed to parse ACL %s\n", tok));
526
525
                                goto done;
531
530
                        }
532
531
                        continue;
533
532
                }
534
 
                
 
533
 
535
534
                DEBUG(5, ("Failed to parse security descriptor\n"));
536
535
                goto done;
537
536
        }
538
 
        
 
537
 
539
538
        ret = make_sec_desc(ctx, revision, SEC_DESC_SELF_RELATIVE, 
540
539
                            owner_sid, group_sid, NULL, dacl, &sd_size);
541
 
        
 
540
 
542
541
done:
543
542
        SAFE_FREE(group_sid);
544
543
        SAFE_FREE(owner_sid);
545
 
        
546
544
        return ret;
547
545
}
548
546
 
562
560
        uint16 mode = 0;
563
561
        SMB_INO_T inode = 0;
564
562
        DOS_ATTR_DESC *ret;
565
 
        
 
563
 
566
564
        ret = TALLOC_P(ctx, DOS_ATTR_DESC);
567
565
        if (!ret) {
568
566
                errno = ENOMEM;
569
567
                return NULL;
570
568
        }
571
 
        
 
569
 
572
570
        /* Obtain the DOS attributes */
573
571
        if (!SMBC_getatr(context, srv, CONST_DISCARD(char *, filename),
574
572
                         &mode, &size,
581
579
                DEBUG(5, ("dos_attr_query Failed to query old attributes\n"));
582
580
                return NULL;
583
581
        }
584
 
        
 
582
 
585
583
        ret->mode = mode;
586
584
        ret->size = size;
587
585
        ret->create_time = convert_timespec_to_time_t(create_time_ts);
589
587
        ret->write_time = convert_timespec_to_time_t(write_time_ts);
590
588
        ret->change_time = convert_timespec_to_time_t(change_time_ts);
591
589
        ret->inode = inode;
592
 
        
 
590
 
593
591
        return ret;
594
592
}
595
593
 
611
609
                const char * write_time_attr;
612
610
                const char * change_time_attr;
613
611
        } attr_strings;
614
 
        
 
612
 
615
613
        /* Determine whether to use old-style or new-style attribute names */
616
614
        if (context->internal->full_time_names) {
617
615
                /* new-style names */
626
624
                attr_strings.write_time_attr = "M_TIME";
627
625
                attr_strings.change_time_attr = "C_TIME";
628
626
        }
629
 
        
 
627
 
630
628
        /* if this is to set the entire ACL... */
631
629
        if (*str == '*') {
632
630
                /* ... then increment past the first colon if there is one */
636
634
                        p = str;
637
635
                }
638
636
        }
639
 
        
 
637
 
640
638
        frame = talloc_stackframe();
641
639
        while (next_token_talloc(frame, &p, &tok, "\t,\r\n")) {
642
640
                if (StrnCaseCmp(tok, "MODE:", 5) == 0) {
651
649
                        }
652
650
                        continue;
653
651
                }
654
 
                
 
652
 
655
653
                if (StrnCaseCmp(tok, "SIZE:", 5) == 0) {
656
654
                        dad->size = (SMB_OFF_T)atof(tok+5);
657
655
                        continue;
658
656
                }
659
 
                
 
657
 
660
658
                n = strlen(attr_strings.access_time_attr);
661
659
                if (StrnCaseCmp(tok, attr_strings.access_time_attr, n) == 0) {
662
660
                        dad->access_time = (time_t)strtol(tok+n+1, NULL, 10);
663
661
                        continue;
664
662
                }
665
 
                
 
663
 
666
664
                n = strlen(attr_strings.change_time_attr);
667
665
                if (StrnCaseCmp(tok, attr_strings.change_time_attr, n) == 0) {
668
666
                        dad->change_time = (time_t)strtol(tok+n+1, NULL, 10);
669
667
                        continue;
670
668
                }
671
 
                
 
669
 
672
670
                n = strlen(attr_strings.write_time_attr);
673
671
                if (StrnCaseCmp(tok, attr_strings.write_time_attr, n) == 0) {
674
672
                        dad->write_time = (time_t)strtol(tok+n+1, NULL, 10);
675
673
                        continue;
676
674
                }
677
 
                
 
675
 
678
676
                if (attr_strings.create_time_attr != NULL) {
679
677
                        n = strlen(attr_strings.create_time_attr);
680
678
                        if (StrnCaseCmp(tok, attr_strings.create_time_attr,
684
682
                                continue;
685
683
                        }
686
684
                }
687
 
                
 
685
 
688
686
                if (StrnCaseCmp(tok, "INODE:", 6) == 0) {
689
687
                        dad->inode = (SMB_INO_T)atof(tok+6);
690
688
                        continue;
731
729
        bool numeric = True;
732
730
        bool determine_size = (bufsize == 0);
733
731
        uint16_t fnum;
734
 
        SEC_DESC *sd;
 
732
        struct security_descriptor *sd;
735
733
        fstring sidstr;
736
734
        fstring name_sandbox;
737
735
        char *name;
761
759
                const char * write_time_attr;
762
760
                const char * change_time_attr;
763
761
        } excl_attr_strings;
764
 
        
 
762
 
765
763
        /* Determine whether to use old-style or new-style attribute names */
766
764
        if (context->internal->full_time_names) {
767
765
                /* new-style names */
769
767
                attr_strings.access_time_attr = "ACCESS_TIME";
770
768
                attr_strings.write_time_attr = "WRITE_TIME";
771
769
                attr_strings.change_time_attr = "CHANGE_TIME";
772
 
                
 
770
 
773
771
                excl_attr_strings.create_time_attr = "CREATE_TIME";
774
772
                excl_attr_strings.access_time_attr = "ACCESS_TIME";
775
773
                excl_attr_strings.write_time_attr = "WRITE_TIME";
780
778
                attr_strings.access_time_attr = "A_TIME";
781
779
                attr_strings.write_time_attr = "M_TIME";
782
780
                attr_strings.change_time_attr = "C_TIME";
783
 
                
 
781
 
784
782
                excl_attr_strings.create_time_attr = NULL;
785
783
                excl_attr_strings.access_time_attr = "dos_attr.A_TIME";
786
784
                excl_attr_strings.write_time_attr = "dos_attr.M_TIME";
787
785
                excl_attr_strings.change_time_attr = "dos_attr.C_TIME";
788
786
        }
789
 
        
 
787
 
790
788
        /* Copy name so we can strip off exclusions (if any are specified) */
791
789
        strncpy(name_sandbox, attr_name, sizeof(name_sandbox) - 1);
792
 
        
 
790
 
793
791
        /* Ensure name is null terminated */
794
792
        name_sandbox[sizeof(name_sandbox) - 1] = '\0';
795
 
        
 
793
 
796
794
        /* Play in the sandbox */
797
795
        name = name_sandbox;
798
 
        
 
796
 
799
797
        /* If there are any exclusions, point to them and mask them from name */
800
798
        if ((pExclude = strchr(name, '!')) != NULL)
801
799
        {
802
800
                *pExclude++ = '\0';
803
801
        }
804
 
        
 
802
 
805
803
        all = (StrnCaseCmp(name, "system.*", 8) == 0);
806
804
        all_nt = (StrnCaseCmp(name, "system.nt_sec_desc.*", 20) == 0);
807
805
        all_nt_acls = (StrnCaseCmp(name, "system.nt_sec_desc.acl.*", 24) == 0);
809
807
        some_nt = (StrnCaseCmp(name, "system.nt_sec_desc.", 19) == 0);
810
808
        some_dos = (StrnCaseCmp(name, "system.dos_attr.", 16) == 0);
811
809
        numeric = (* (name + strlen(name) - 1) != '+');
812
 
        
 
810
 
813
811
        /* Look for exclusions from "all" requests */
814
812
        if (all || all_nt || all_dos) {
815
 
                
816
813
                /* Exclusions are delimited by '!' */
817
814
                for (;
818
815
                     pExclude != NULL;
819
816
                     pExclude = (p == NULL ? NULL : p + 1)) {
820
 
                        
 
817
 
821
818
                        /* Find end of this exclusion name */
822
819
                        if ((p = strchr(pExclude, '!')) != NULL)
823
820
                        {
824
821
                                *p = '\0';
825
822
                        }
826
 
                        
 
823
 
827
824
                        /* Which exclusion name is this? */
828
825
                        if (StrCaseCmp(pExclude,
829
826
                                       "nt_sec_desc.revision") == 0) {
877
874
                        }
878
875
                }
879
876
        }
880
 
        
 
877
 
881
878
        n_used = 0;
882
 
        
 
879
 
883
880
        /*
884
881
         * If we are (possibly) talking to an NT or new system and some NT
885
882
         * attributes have been requested...
950
947
                                                     sd->revision);
951
948
                                }
952
949
                        }
953
 
                        
 
950
 
954
951
                        if (!determine_size && n > bufsize) {
955
952
                                errno = ERANGE;
956
953
                                return -1;
960
957
                        bufsize -= n;
961
958
                        n = 0;
962
959
                }
963
 
                
 
960
 
964
961
                if (! exclude_nt_owner) {
965
962
                        /* Get owner and group sid */
966
963
                        if (sd->owner_sid) {
971
968
                        } else {
972
969
                                fstrcpy(sidstr, "");
973
970
                        }
974
 
                        
 
971
 
975
972
                        if (all || all_nt) {
976
973
                                if (determine_size) {
977
974
                                        p = talloc_asprintf(ctx, ",OWNER:%s",
998
995
                                                     sidstr);
999
996
                                }
1000
997
                        }
1001
 
                        
 
998
 
1002
999
                        if (!determine_size && n > bufsize) {
1003
1000
                                errno = ERANGE;
1004
1001
                                return -1;
1008
1005
                        bufsize -= n;
1009
1006
                        n = 0;
1010
1007
                }
1011
 
                
 
1008
 
1012
1009
                if (! exclude_nt_group) {
1013
1010
                        if (sd->group_sid) {
1014
1011
                                convert_sid_to_string(ipc_cli, pol,
1017
1014
                        } else {
1018
1015
                                fstrcpy(sidstr, "");
1019
1016
                        }
1020
 
                        
 
1017
 
1021
1018
                        if (all || all_nt) {
1022
1019
                                if (determine_size) {
1023
1020
                                        p = talloc_asprintf(ctx, ",GROUP:%s",
1044
1041
                                                     "%s", sidstr);
1045
1042
                                }
1046
1043
                        }
1047
 
                        
 
1044
 
1048
1045
                        if (!determine_size && n > bufsize) {
1049
1046
                                errno = ERANGE;
1050
1047
                                return -1;
1054
1051
                        bufsize -= n;
1055
1052
                        n = 0;
1056
1053
                }
1057
 
                
 
1054
 
1058
1055
                if (! exclude_nt_acl) {
1059
1056
                        /* Add aces to value buffer  */
1060
1057
                        for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
1061
 
                                
1062
 
                                SEC_ACE *ace = &sd->dacl->aces[i];
 
1058
 
 
1059
                                struct security_ace *ace = &sd->dacl->aces[i];
1063
1060
                                convert_sid_to_string(ipc_cli, pol,
1064
1061
                                                      sidstr, numeric,
1065
1062
                                                      &ace->trustee);
1066
 
                                
 
1063
 
1067
1064
                                if (all || all_nt) {
1068
1065
                                        if (determine_size) {
1069
1066
                                                p = talloc_asprintf(
1146
1143
                                n = 0;
1147
1144
                        }
1148
1145
                }
1149
 
                
 
1146
 
1150
1147
                /* Restore name pointer to its original value */
1151
1148
                name -= 19;
1152
1149
        }
1153
 
        
 
1150
 
1154
1151
        if (all || some_dos) {
1155
1152
                /* Point to the portion after "system.dos_attr." */
1156
1153
                name += 16;     /* if (all) this will be invalid but unused */
1157
 
                
 
1154
 
1158
1155
                /* Obtain the DOS attributes */
1159
1156
                if (!SMBC_getatr(context, srv, filename, &mode, &size, 
1160
1157
                                 &create_time_ts,
1162
1159
                                 &write_time_ts,
1163
1160
                                 &change_time_ts,
1164
1161
                                 &ino)) {
1165
 
                        
 
1162
 
1166
1163
                        errno = SMBC_errno(context, srv->cli);
1167
1164
                        return -1;
1168
 
                        
1169
1165
                }
1170
 
                
 
1166
 
1171
1167
                create_time = convert_timespec_to_time_t(create_time_ts);
1172
1168
                access_time = convert_timespec_to_time_t(access_time_ts);
1173
1169
                write_time = convert_timespec_to_time_t(write_time_ts);
1174
1170
                change_time = convert_timespec_to_time_t(change_time_ts);
1175
 
                
 
1171
 
1176
1172
                if (! exclude_dos_mode) {
1177
1173
                        if (all || all_dos) {
1178
1174
                                if (determine_size) {
1210
1206
                                                     "0x%x", mode);
1211
1207
                                }
1212
1208
                        }
1213
 
                        
 
1209
 
1214
1210
                        if (!determine_size && n > bufsize) {
1215
1211
                                errno = ERANGE;
1216
1212
                                return -1;
1220
1216
                        bufsize -= n;
1221
1217
                        n = 0;
1222
1218
                }
1223
 
                
 
1219
 
1224
1220
                if (! exclude_dos_size) {
1225
1221
                        if (all || all_dos) {
1226
1222
                                if (determine_size) {
1255
1251
                                                     (double)size);
1256
1252
                                }
1257
1253
                        }
1258
 
                        
 
1254
 
1259
1255
                        if (!determine_size && n > bufsize) {
1260
1256
                                errno = ERANGE;
1261
1257
                                return -1;
1265
1261
                        bufsize -= n;
1266
1262
                        n = 0;
1267
1263
                }
1268
 
                
 
1264
 
1269
1265
                if (! exclude_dos_create_time &&
1270
1266
                    attr_strings.create_time_attr != NULL) {
1271
1267
                        if (all || all_dos) {
1298
1294
                                                     "%lu", (unsigned long) create_time);
1299
1295
                                }
1300
1296
                        }
1301
 
                        
 
1297
 
1302
1298
                        if (!determine_size && n > bufsize) {
1303
1299
                                errno = ERANGE;
1304
1300
                                return -1;
1308
1304
                        bufsize -= n;
1309
1305
                        n = 0;
1310
1306
                }
1311
 
                
 
1307
 
1312
1308
                if (! exclude_dos_access_time) {
1313
1309
                        if (all || all_dos) {
1314
1310
                                if (determine_size) {
1340
1336
                                                     "%lu", (unsigned long) access_time);
1341
1337
                                }
1342
1338
                        }
1343
 
                        
 
1339
 
1344
1340
                        if (!determine_size && n > bufsize) {
1345
1341
                                errno = ERANGE;
1346
1342
                                return -1;
1350
1346
                        bufsize -= n;
1351
1347
                        n = 0;
1352
1348
                }
1353
 
                
 
1349
 
1354
1350
                if (! exclude_dos_write_time) {
1355
1351
                        if (all || all_dos) {
1356
1352
                                if (determine_size) {
1382
1378
                                                     "%lu", (unsigned long) write_time);
1383
1379
                                }
1384
1380
                        }
1385
 
                        
 
1381
 
1386
1382
                        if (!determine_size && n > bufsize) {
1387
1383
                                errno = ERANGE;
1388
1384
                                return -1;
1392
1388
                        bufsize -= n;
1393
1389
                        n = 0;
1394
1390
                }
1395
 
                
 
1391
 
1396
1392
                if (! exclude_dos_change_time) {
1397
1393
                        if (all || all_dos) {
1398
1394
                                if (determine_size) {
1424
1420
                                                     "%lu", (unsigned long) change_time);
1425
1421
                                }
1426
1422
                        }
1427
 
                        
 
1423
 
1428
1424
                        if (!determine_size && n > bufsize) {
1429
1425
                                errno = ERANGE;
1430
1426
                                return -1;
1434
1430
                        bufsize -= n;
1435
1431
                        n = 0;
1436
1432
                }
1437
 
                
 
1433
 
1438
1434
                if (! exclude_dos_inode) {
1439
1435
                        if (all || all_dos) {
1440
1436
                                if (determine_size) {
1469
1465
                                                     (double) ino);
1470
1466
                                }
1471
1467
                        }
1472
 
                        
 
1468
 
1473
1469
                        if (!determine_size && n > bufsize) {
1474
1470
                                errno = ERANGE;
1475
1471
                                return -1;
1479
1475
                        bufsize -= n;
1480
1476
                        n = 0;
1481
1477
                }
1482
 
                
 
1478
 
1483
1479
                /* Restore name pointer to its original value */
1484
1480
                name -= 16;
1485
1481
        }
1486
 
        
 
1482
 
1487
1483
        if (n_used == 0) {
1488
1484
                errno = ENOATTR;
1489
1485
                return -1;
1490
1486
        }
1491
 
        
 
1487
 
1492
1488
        return n_used;
1493
1489
}
1494
1490
 
1508
1504
{
1509
1505
        uint16_t fnum = (uint16_t)-1;
1510
1506
        int err = 0;
1511
 
        SEC_DESC *sd = NULL, *old;
1512
 
        SEC_ACL *dacl = NULL;
1513
 
        DOM_SID *owner_sid = NULL;
1514
 
        DOM_SID *group_sid = NULL;
 
1507
        struct security_descriptor *sd = NULL, *old;
 
1508
        struct security_acl *dacl = NULL;
 
1509
        struct dom_sid *owner_sid = NULL;
 
1510
        struct dom_sid *group_sid = NULL;
1515
1511
        uint32 i, j;
1516
1512
        size_t sd_size;
1517
1513
        int ret = 0;
1519
1515
        bool numeric = True;
1520
1516
        char *targetpath = NULL;
1521
1517
        struct cli_state *targetcli = NULL;
 
1518
        NTSTATUS status;
1522
1519
 
1523
1520
        /* the_acl will be null for REMOVE_ALL operations */
1524
1521
        if (the_acl) {
1525
1522
                numeric = ((p = strchr(the_acl, ':')) != NULL &&
1526
1523
                           p > the_acl &&
1527
1524
                           p[-1] != '+');
1528
 
                
 
1525
 
1529
1526
                /* if this is to set the entire ACL... */
1530
1527
                if (*the_acl == '*') {
1531
1528
                        /* ... then increment past the first colon */
1532
1529
                        the_acl = p + 1;
1533
1530
                }
1534
 
                
 
1531
 
1535
1532
                sd = sec_desc_parse(ctx, ipc_cli, pol, numeric, the_acl);
1536
 
                
1537
1533
                if (!sd) {
1538
1534
                        errno = EINVAL;
1539
1535
                        return -1;
1540
1536
                }
1541
1537
        }
1542
 
        
 
1538
 
1543
1539
        /* SMBC_XATTR_MODE_REMOVE_ALL is the only caller
1544
1540
           that doesn't deref sd */
1545
 
        
 
1541
 
1546
1542
        if (!sd && (mode != SMBC_XATTR_MODE_REMOVE_ALL)) {
1547
1543
                errno = EINVAL;
1548
1544
                return -1;
1601
1597
                                        break;
1602
1598
                                }
1603
1599
                        }
1604
 
                        
 
1600
 
1605
1601
                        if (!found) {
1606
1602
                                err = ENOATTR;
1607
1603
                                ret = -1;
1609
1605
                        }
1610
1606
                }
1611
1607
                break;
1612
 
                
 
1608
 
1613
1609
        case SMBC_XATTR_MODE_ADD:
1614
1610
                for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) {
1615
1611
                        bool found = False;
1616
 
                        
 
1612
 
1617
1613
                        for (j=0;old->dacl && j<old->dacl->num_aces;j++) {
1618
 
                                if (sid_equal(&sd->dacl->aces[i].trustee,
 
1614
                                if (dom_sid_equal(&sd->dacl->aces[i].trustee,
1619
1615
                                              &old->dacl->aces[j].trustee)) {
1620
1616
                                        if (!(flags & SMBC_XATTR_FLAG_CREATE)) {
1621
1617
                                                err = EEXIST;
1627
1623
                                        found = True;
1628
1624
                                }
1629
1625
                        }
1630
 
                        
 
1626
 
1631
1627
                        if (!found && (flags & SMBC_XATTR_FLAG_REPLACE)) {
1632
1628
                                err = ENOATTR;
1633
1629
                                ret = -1;
1634
1630
                                goto failed;
1635
1631
                        }
1636
 
                        
 
1632
 
1637
1633
                        for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) {
1638
1634
                                add_ace(&old->dacl, &sd->dacl->aces[i], ctx);
1639
1635
                        }
1640
1636
                }
1641
1637
                dacl = old->dacl;
1642
1638
                break;
1643
 
                
 
1639
 
1644
1640
        case SMBC_XATTR_MODE_SET:
1645
1641
                old = sd;
1646
1642
                owner_sid = old->owner_sid;
1647
1643
                group_sid = old->group_sid;
1648
1644
                dacl = old->dacl;
1649
1645
                break;
1650
 
                
 
1646
 
1651
1647
        case SMBC_XATTR_MODE_CHOWN:
1652
1648
                owner_sid = sd->owner_sid;
1653
1649
                break;
1654
 
                
 
1650
 
1655
1651
        case SMBC_XATTR_MODE_CHGRP:
1656
1652
                group_sid = sd->group_sid;
1657
1653
                break;
1658
1654
        }
1659
 
        
 
1655
 
1660
1656
        /* Denied ACE entries must come before allowed ones */
1661
1657
        sort_acl(old->dacl);
1662
 
        
 
1658
 
1663
1659
        /* Create new security descriptor and set it */
1664
1660
        sd = make_sec_desc(ctx, old->revision, SEC_DESC_SELF_RELATIVE,
1665
1661
                           owner_sid, group_sid, NULL, dacl, &sd_size);
1666
 
        
 
1662
 
1667
1663
        if (!NT_STATUS_IS_OK(cli_ntcreate(targetcli, targetpath, 0,
1668
1664
                             WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS, 0,
1669
1665
                             FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
1672
1668
                errno = 0;
1673
1669
                return -1;
1674
1670
        }
1675
 
        
1676
 
        if (!cli_set_secdesc(targetcli, fnum, sd)) {
 
1671
 
 
1672
        status = cli_set_secdesc(targetcli, fnum, sd);
 
1673
        if (!NT_STATUS_IS_OK(status)) {
1677
1674
                DEBUG(5, ("ERROR: secdesc set failed: %s\n",
1678
 
                        cli_errstr(targetcli)));
 
1675
                          nt_errstr(status)));
1679
1676
                ret = -1;
1680
1677
        }
1681
 
        
 
1678
 
1682
1679
        /* Clean up */
1683
 
        
 
1680
 
1684
1681
failed:
1685
1682
        cli_close(targetcli, fnum);
1686
 
        
 
1683
 
1687
1684
        if (err != 0) {
1688
1685
                errno = err;
1689
1686
        }
1690
 
        
 
1687
 
1691
1688
        return ret;
1692
1689
}
1693
1690
 
1718
1715
                const char * change_time_attr;
1719
1716
        } attr_strings;
1720
1717
        TALLOC_CTX *frame = talloc_stackframe();
1721
 
        
 
1718
 
1722
1719
        if (!context || !context->internal->initialized) {
1723
 
                
1724
1720
                errno = EINVAL;  /* Best I can think of ... */
1725
1721
                TALLOC_FREE(frame);
1726
1722
                return -1;
1727
1723
        }
1728
 
        
 
1724
 
1729
1725
        if (!fname) {
1730
1726
                errno = EINVAL;
1731
1727
                TALLOC_FREE(frame);
1732
1728
                return -1;
1733
1729
        }
1734
 
        
 
1730
 
1735
1731
        DEBUG(4, ("smbc_setxattr(%s, %s, %.*s)\n",
1736
1732
                  fname, name, (int) size, (const char*)value));
1737
 
        
 
1733
 
1738
1734
        if (SMBC_parse_path(frame,
1739
1735
                            context,
1740
1736
                            fname,
1749
1745
                TALLOC_FREE(frame);
1750
1746
                return -1;
1751
1747
        }
1752
 
        
 
1748
 
1753
1749
        if (!user || user[0] == (char)0) {
1754
1750
                user = talloc_strdup(frame, smbc_getUser(context));
1755
1751
                if (!user) {
1758
1754
                        return -1;
1759
1755
                }
1760
1756
        }
1761
 
        
 
1757
 
1762
1758
        srv = SMBC_server(frame, context, True,
1763
1759
                          server, share, &workgroup, &user, &password);
1764
1760
        if (!srv) {
1765
1761
                TALLOC_FREE(frame);
1766
1762
                return -1;  /* errno set by SMBC_server */
1767
1763
        }
1768
 
        
 
1764
 
1769
1765
        if (! srv->no_nt_session) {
1770
1766
                ipc_srv = SMBC_attr_server(frame, context, server, share,
1771
1767
                                           &workgroup, &user, &password);
1775
1771
        } else {
1776
1772
                ipc_srv = NULL;
1777
1773
        }
1778
 
        
 
1774
 
1779
1775
        /*
1780
1776
         * Are they asking to set the entire set of known attributes?
1781
1777
         */
1791
1787
                        TALLOC_FREE(frame);
1792
1788
                        return -1;
1793
1789
                }
1794
 
                
 
1790
 
1795
1791
                if (ipc_srv) {
1796
1792
                        ret = cacl_set(context, talloc_tos(), srv->cli,
1797
1793
                                       ipc_srv->cli, &ipc_srv->pol, path,
1803
1799
                } else {
1804
1800
                        ret = 0;
1805
1801
                }
1806
 
                
 
1802
 
1807
1803
                /* get a DOS Attribute Descriptor with current attributes */
1808
1804
                dad = dos_attr_query(context, talloc_tos(), path, srv);
1809
1805
                if (dad) {
1810
1806
                        /* Overwrite old with new, using what was provided */
1811
1807
                        dos_attr_parse(context, dad, srv, namevalue);
1812
 
                        
 
1808
 
1813
1809
                        /* Set the new DOS attributes */
1814
1810
                        if (! SMBC_setatr(context, srv, path,
1815
1811
                                          dad->create_time,
1817
1813
                                          dad->write_time,
1818
1814
                                          dad->change_time,
1819
1815
                                          dad->mode)) {
1820
 
                                
 
1816
 
1821
1817
                                /* cause failure if NT failed too */
1822
1818
                                dad = NULL; 
1823
1819
                        }
1824
1820
                }
1825
 
                
 
1821
 
1826
1822
                /* we only fail if both NT and DOS sets failed */
1827
1823
                if (ret < 0 && ! dad) {
1828
1824
                        ret = -1; /* in case dad was null */
1830
1826
                else {
1831
1827
                        ret = 0;
1832
1828
                }
1833
 
                
 
1829
 
1834
1830
                TALLOC_FREE(frame);
1835
1831
                return ret;
1836
1832
        }
1837
 
        
 
1833
 
1838
1834
        /*
1839
1835
         * Are they asking to set an access control element or to set
1840
1836
         * the entire access control list?
1844
1840
            StrCaseCmp(name, "system.nt_sec_desc.revision") == 0 ||
1845
1841
            StrnCaseCmp(name, "system.nt_sec_desc.acl", 22) == 0 ||
1846
1842
            StrnCaseCmp(name, "system.nt_sec_desc.acl+", 23) == 0) {
1847
 
                
 
1843
 
1848
1844
                /* Yup. */
1849
1845
                char *namevalue =
1850
1846
                        talloc_asprintf(talloc_tos(), "%s:%s",
1851
1847
                                        name+19, (const char *) value);
1852
 
                
 
1848
 
1853
1849
                if (! ipc_srv) {
1854
1850
                        ret = -1; /* errno set by SMBC_server() */
1855
1851
                }
1868
1864
                TALLOC_FREE(frame);
1869
1865
                return ret;
1870
1866
        }
1871
 
        
 
1867
 
1872
1868
        /*
1873
1869
         * Are they asking to set the owner?
1874
1870
         */
1875
1871
        if (StrCaseCmp(name, "system.nt_sec_desc.owner") == 0 ||
1876
1872
            StrCaseCmp(name, "system.nt_sec_desc.owner+") == 0) {
1877
 
                
 
1873
 
1878
1874
                /* Yup. */
1879
1875
                char *namevalue =
1880
1876
                        talloc_asprintf(talloc_tos(), "%s:%s",
1881
1877
                                        name+19, (const char *) value);
1882
 
                
 
1878
 
1883
1879
                if (! ipc_srv) {
1884
1880
                        ret = -1; /* errno set by SMBC_server() */
1885
1881
                }
1894
1890
                TALLOC_FREE(frame);
1895
1891
                return ret;
1896
1892
        }
1897
 
        
 
1893
 
1898
1894
        /*
1899
1895
         * Are they asking to set the group?
1900
1896
         */
1901
1897
        if (StrCaseCmp(name, "system.nt_sec_desc.group") == 0 ||
1902
1898
            StrCaseCmp(name, "system.nt_sec_desc.group+") == 0) {
1903
 
                
 
1899
 
1904
1900
                /* Yup. */
1905
1901
                char *namevalue =
1906
1902
                        talloc_asprintf(talloc_tos(), "%s:%s",
1907
1903
                                        name+19, (const char *) value);
1908
 
                
 
1904
 
1909
1905
                if (! ipc_srv) {
1910
1906
                        /* errno set by SMBC_server() */
1911
1907
                        ret = -1;
1921
1917
                TALLOC_FREE(frame);
1922
1918
                return ret;
1923
1919
        }
1924
 
        
 
1920
 
1925
1921
        /* Determine whether to use old-style or new-style attribute names */
1926
1922
        if (context->internal->full_time_names) {
1927
1923
                /* new-style names */
1936
1932
                attr_strings.write_time_attr = "system.dos_attr.M_TIME";
1937
1933
                attr_strings.change_time_attr = "system.dos_attr.C_TIME";
1938
1934
        }
1939
 
        
 
1935
 
1940
1936
        /*
1941
1937
         * Are they asking to set a DOS attribute?
1942
1938
         */
1947
1943
            StrCaseCmp(name, attr_strings.access_time_attr) == 0 ||
1948
1944
            StrCaseCmp(name, attr_strings.write_time_attr) == 0 ||
1949
1945
            StrCaseCmp(name, attr_strings.change_time_attr) == 0) {
1950
 
                
 
1946
 
1951
1947
                /* get a DOS Attribute Descriptor with current attributes */
1952
1948
                dad = dos_attr_query(context, talloc_tos(), path, srv);
1953
1949
                if (dad) {
1960
1956
                        } else {
1961
1957
                                /* Overwrite old with provided new params */
1962
1958
                                dos_attr_parse(context, dad, srv, namevalue);
1963
 
                                
 
1959
 
1964
1960
                                /* Set the new DOS attributes */
1965
1961
                                ret2 = SMBC_setatr(context, srv, path,
1966
1962
                                                   dad->create_time,
1968
1964
                                                   dad->write_time,
1969
1965
                                                   dad->change_time,
1970
1966
                                                   dad->mode);
1971
 
                                
 
1967
 
1972
1968
                                /* ret2 has True (success) / False (failure) */
1973
1969
                                if (ret2) {
1974
1970
                                        ret = 0;
1979
1975
                } else {
1980
1976
                        ret = -1;
1981
1977
                }
1982
 
                
 
1978
 
1983
1979
                TALLOC_FREE(frame);
1984
1980
                return ret;
1985
1981
        }
1986
 
        
 
1982
 
1987
1983
        /* Unsupported attribute name */
1988
1984
        errno = EINVAL;
1989
1985
        TALLOC_FREE(frame);
2013
2009
                const char * change_time_attr;
2014
2010
        } attr_strings;
2015
2011
        TALLOC_CTX *frame = talloc_stackframe();
2016
 
        
 
2012
 
2017
2013
        if (!context || !context->internal->initialized) {
2018
 
                
2019
2014
                errno = EINVAL;  /* Best I can think of ... */
2020
2015
                TALLOC_FREE(frame);
2021
2016
                return -1;
2022
2017
        }
2023
 
        
 
2018
 
2024
2019
        if (!fname) {
2025
2020
                errno = EINVAL;
2026
2021
                TALLOC_FREE(frame);
2027
2022
                return -1;
2028
2023
        }
2029
 
        
 
2024
 
2030
2025
        DEBUG(4, ("smbc_getxattr(%s, %s)\n", fname, name));
2031
 
        
 
2026
 
2032
2027
        if (SMBC_parse_path(frame,
2033
2028
                            context,
2034
2029
                            fname,
2043
2038
                TALLOC_FREE(frame);
2044
2039
                return -1;
2045
2040
        }
2046
 
        
 
2041
 
2047
2042
        if (!user || user[0] == (char)0) {
2048
2043
                user = talloc_strdup(frame, smbc_getUser(context));
2049
2044
                if (!user) {
2052
2047
                        return -1;
2053
2048
                }
2054
2049
        }
2055
 
        
 
2050
 
2056
2051
        srv = SMBC_server(frame, context, True,
2057
2052
                          server, share, &workgroup, &user, &password);
2058
2053
        if (!srv) {
2059
2054
                TALLOC_FREE(frame);
2060
2055
                return -1;  /* errno set by SMBC_server */
2061
2056
        }
2062
 
        
 
2057
 
2063
2058
        if (! srv->no_nt_session) {
2064
2059
                ipc_srv = SMBC_attr_server(frame, context, server, share,
2065
2060
                                           &workgroup, &user, &password);
2069
2064
        } else {
2070
2065
                ipc_srv = NULL;
2071
2066
        }
2072
 
        
 
2067
 
2073
2068
        /* Determine whether to use old-style or new-style attribute names */
2074
2069
        if (context->internal->full_time_names) {
2075
2070
                /* new-style names */
2084
2079
                attr_strings.write_time_attr = "system.dos_attr.M_TIME";
2085
2080
                attr_strings.change_time_attr = "system.dos_attr.C_TIME";
2086
2081
        }
2087
 
        
 
2082
 
2088
2083
        /* Are they requesting a supported attribute? */
2089
2084
        if (StrCaseCmp(name, "system.*") == 0 ||
2090
2085
            StrnCaseCmp(name, "system.*!", 9) == 0 ||
2111
2106
            StrCaseCmp(name, attr_strings.write_time_attr) == 0 ||
2112
2107
            StrCaseCmp(name, attr_strings.change_time_attr) == 0 ||
2113
2108
            StrCaseCmp(name, "system.dos_attr.inode") == 0) {
2114
 
                
 
2109
 
2115
2110
                /* Yup. */
2116
2111
                char *filename = (char *) name;
2117
2112
                ret = cacl_get(context, talloc_tos(), srv,
2126
2121
                TALLOC_FREE(frame);
2127
2122
                return ret;
2128
2123
        }
2129
 
        
 
2124
 
2130
2125
        /* Unsupported attribute name */
2131
2126
        errno = EINVAL;
2132
2127
        TALLOC_FREE(frame);
2149
2144
        char *workgroup = NULL;
2150
2145
        char *path = NULL;
2151
2146
        TALLOC_CTX *frame = talloc_stackframe();
2152
 
        
 
2147
 
2153
2148
        if (!context || !context->internal->initialized) {
2154
 
                
2155
2149
                errno = EINVAL;  /* Best I can think of ... */
2156
2150
                TALLOC_FREE(frame);
2157
2151
                return -1;
2158
2152
        }
2159
 
        
 
2153
 
2160
2154
        if (!fname) {
2161
2155
                errno = EINVAL;
2162
2156
                TALLOC_FREE(frame);
2163
2157
                return -1;
2164
2158
        }
2165
 
        
 
2159
 
2166
2160
        DEBUG(4, ("smbc_removexattr(%s, %s)\n", fname, name));
2167
 
        
 
2161
 
2168
2162
        if (SMBC_parse_path(frame,
2169
2163
                            context,
2170
2164
                            fname,
2179
2173
                TALLOC_FREE(frame);
2180
2174
                return -1;
2181
2175
        }
2182
 
        
 
2176
 
2183
2177
        if (!user || user[0] == (char)0) {
2184
2178
                user = talloc_strdup(frame, smbc_getUser(context));
2185
2179
                if (!user) {
2188
2182
                        return -1;
2189
2183
                }
2190
2184
        }
2191
 
        
 
2185
 
2192
2186
        srv = SMBC_server(frame, context, True,
2193
2187
                          server, share, &workgroup, &user, &password);
2194
2188
        if (!srv) {
2195
2189
                TALLOC_FREE(frame);
2196
2190
                return -1;  /* errno set by SMBC_server */
2197
2191
        }
2198
 
        
 
2192
 
2199
2193
        if (! srv->no_nt_session) {
2200
2194
                ipc_srv = SMBC_attr_server(frame, context, server, share,
2201
2195
                                           &workgroup, &user, &password);
2205
2199
        } else {
2206
2200
                ipc_srv = NULL;
2207
2201
        }
2208
 
        
 
2202
 
2209
2203
        if (! ipc_srv) {
2210
2204
                TALLOC_FREE(frame);
2211
2205
                return -1; /* errno set by SMBC_attr_server */
2212
2206
        }
2213
 
        
 
2207
 
2214
2208
        /* Are they asking to set the entire ACL? */
2215
2209
        if (StrCaseCmp(name, "system.nt_sec_desc.*") == 0 ||
2216
2210
            StrCaseCmp(name, "system.nt_sec_desc.*+") == 0) {
2217
 
                
 
2211
 
2218
2212
                /* Yup. */
2219
2213
                ret = cacl_set(context, talloc_tos(), srv->cli,
2220
2214
                               ipc_srv->cli, &ipc_srv->pol, path,
2222
2216
                TALLOC_FREE(frame);
2223
2217
                return ret;
2224
2218
        }
2225
 
        
 
2219
 
2226
2220
        /*
2227
2221
         * Are they asking to remove one or more spceific security descriptor
2228
2222
         * attributes?
2234
2228
            StrCaseCmp(name, "system.nt_sec_desc.group+") == 0 ||
2235
2229
            StrnCaseCmp(name, "system.nt_sec_desc.acl", 22) == 0 ||
2236
2230
            StrnCaseCmp(name, "system.nt_sec_desc.acl+", 23) == 0) {
2237
 
                
 
2231
 
2238
2232
                /* Yup. */
2239
2233
                ret = cacl_set(context, talloc_tos(), srv->cli,
2240
2234
                               ipc_srv->cli, &ipc_srv->pol, path,
2243
2237
                TALLOC_FREE(frame);
2244
2238
                return ret;
2245
2239
        }
2246
 
        
 
2240
 
2247
2241
        /* Unsupported attribute name */
2248
2242
        errno = EINVAL;
2249
2243
        TALLOC_FREE(frame);
2302
2296
                "system.dos_attr.change_time\0"
2303
2297
                ;
2304
2298
        const char * supported;
2305
 
        
 
2299
 
2306
2300
        if (context->internal->full_time_names) {
2307
2301
                supported = supported_new;
2308
2302
                retsize = sizeof(supported_new);
2310
2304
                supported = supported_old;
2311
2305
                retsize = sizeof(supported_old);
2312
2306
        }
2313
 
        
 
2307
 
2314
2308
        if (size == 0) {
2315
2309
                return retsize;
2316
2310
        }
2317
 
        
 
2311
 
2318
2312
        if (retsize > size) {
2319
2313
                errno = ERANGE;
2320
2314
                return -1;
2321
2315
        }
2322
 
        
 
2316
 
2323
2317
        /* this can't be strcpy() because there are embedded null characters */
2324
2318
        memcpy(list, supported, retsize);
2325
2319
        return retsize;