Coverage Report

Created: 2025-12-31 06:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source3/lib/netapi/share.c
Line
Count
Source
1
/*
2
 *  Unix SMB/CIFS implementation.
3
 *  NetApi Share Support
4
 *  Copyright (C) Guenther Deschner 2008
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 3 of the License, or
9
 *  (at your option) any later version.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18
 */
19
20
#include "includes.h"
21
22
#include "librpc/gen_ndr/libnetapi.h"
23
#include "lib/netapi/netapi.h"
24
#include "lib/netapi/netapi_private.h"
25
#include "lib/netapi/libnetapi.h"
26
#include "../librpc/gen_ndr/ndr_srvsvc_c.h"
27
#include "librpc/gen_ndr/ndr_security.h"
28
29
/****************************************************************
30
****************************************************************/
31
32
static NTSTATUS map_srvsvc_share_info_to_SHARE_INFO_buffer(TALLOC_CTX *mem_ctx,
33
                 uint32_t level,
34
                 union srvsvc_NetShareInfo *info,
35
                 uint8_t **buffer,
36
                 uint32_t *num_shares)
37
0
{
38
0
  struct SHARE_INFO_0 i0;
39
0
  struct SHARE_INFO_1 i1;
40
0
  struct SHARE_INFO_2 i2;
41
0
  struct SHARE_INFO_501 i501;
42
0
  struct SHARE_INFO_1005 i1005;
43
44
0
  struct srvsvc_NetShareInfo0 *s0;
45
0
  struct srvsvc_NetShareInfo1 *s1;
46
0
  struct srvsvc_NetShareInfo2 *s2;
47
0
  struct srvsvc_NetShareInfo501 *s501;
48
0
  struct srvsvc_NetShareInfo1005 *s1005;
49
50
0
  if (!buffer) {
51
0
    return NT_STATUS_INVALID_PARAMETER;
52
0
  }
53
54
0
  switch (level) {
55
0
    case 0:
56
0
      s0 = info->info0;
57
58
0
      i0.shi0_netname   = talloc_strdup(mem_ctx, s0->name);
59
60
0
      ADD_TO_ARRAY(mem_ctx, struct SHARE_INFO_0, i0,
61
0
             (struct SHARE_INFO_0 **)buffer,
62
0
             num_shares);
63
0
      break;
64
65
0
    case 1:
66
0
      s1 = info->info1;
67
68
0
      i1.shi1_netname   = talloc_strdup(mem_ctx, s1->name);
69
0
      i1.shi1_type    = s1->type;
70
0
      i1.shi1_remark    = talloc_strdup(mem_ctx, s1->comment);
71
72
0
      ADD_TO_ARRAY(mem_ctx, struct SHARE_INFO_1, i1,
73
0
             (struct SHARE_INFO_1 **)buffer,
74
0
             num_shares);
75
0
      break;
76
77
0
    case 2:
78
0
      s2 = info->info2;
79
80
0
      i2.shi2_netname   = talloc_strdup(mem_ctx, s2->name);
81
0
      i2.shi2_type    = s2->type;
82
0
      i2.shi2_remark    = talloc_strdup(mem_ctx, s2->comment);
83
0
      i2.shi2_permissions = s2->permissions;
84
0
      i2.shi2_max_uses  = s2->max_users;
85
0
      i2.shi2_current_uses  = s2->current_users;
86
0
      i2.shi2_path    = talloc_strdup(mem_ctx, s2->path);
87
0
      i2.shi2_passwd    = talloc_strdup(mem_ctx, s2->password);
88
89
0
      ADD_TO_ARRAY(mem_ctx, struct SHARE_INFO_2, i2,
90
0
             (struct SHARE_INFO_2 **)buffer,
91
0
             num_shares);
92
0
      break;
93
94
0
    case 501:
95
0
      s501 = info->info501;
96
97
0
      i501.shi501_netname   = talloc_strdup(mem_ctx, s501->name);
98
0
      i501.shi501_type    = s501->type;
99
0
      i501.shi501_remark    = talloc_strdup(mem_ctx, s501->comment);
100
0
      i501.shi501_flags   = s501->csc_policy;
101
102
0
      ADD_TO_ARRAY(mem_ctx, struct SHARE_INFO_501, i501,
103
0
             (struct SHARE_INFO_501 **)buffer,
104
0
             num_shares);
105
0
      break;
106
107
0
    case 1005:
108
0
      s1005 = info->info1005;
109
110
0
      i1005.shi1005_flags   = s1005->dfs_flags;
111
112
0
      ADD_TO_ARRAY(mem_ctx, struct SHARE_INFO_1005, i1005,
113
0
             (struct SHARE_INFO_1005 **)buffer,
114
0
             num_shares);
115
0
      break;
116
117
0
    default:
118
0
      return NT_STATUS_INVALID_PARAMETER;
119
0
  }
120
121
0
  return NT_STATUS_OK;
122
0
}
123
124
/****************************************************************
125
****************************************************************/
126
127
static NTSTATUS map_SHARE_INFO_buffer_to_srvsvc_share_info(TALLOC_CTX *mem_ctx,
128
                 uint8_t *buffer,
129
                 uint32_t level,
130
                 union srvsvc_NetShareInfo *info)
131
0
{
132
0
  struct SHARE_INFO_2 *i2 = NULL;
133
0
  struct SHARE_INFO_502 *i502 = NULL;
134
0
  struct SHARE_INFO_1004 *i1004 = NULL;
135
0
  struct srvsvc_NetShareInfo2 *s2 = NULL;
136
0
  struct srvsvc_NetShareInfo502 *s502 = NULL;
137
0
  struct srvsvc_NetShareInfo1004 *s1004 = NULL;
138
139
0
  if (!buffer) {
140
0
    return NT_STATUS_INVALID_PARAMETER;
141
0
  }
142
143
0
  switch (level) {
144
0
    case 2:
145
0
      i2 = (struct SHARE_INFO_2 *)buffer;
146
147
0
      s2 = talloc(mem_ctx, struct srvsvc_NetShareInfo2);
148
0
      NT_STATUS_HAVE_NO_MEMORY(s2);
149
150
0
      s2->name    = i2->shi2_netname;
151
0
      s2->type    = i2->shi2_type;
152
0
      s2->comment   = i2->shi2_remark;
153
0
      s2->permissions   = i2->shi2_permissions;
154
0
      s2->max_users   = i2->shi2_max_uses;
155
0
      s2->current_users = i2->shi2_current_uses;
156
0
      s2->path    = i2->shi2_path;
157
0
      s2->password    = i2->shi2_passwd;
158
159
0
      info->info2 = s2;
160
161
0
      break;
162
163
0
    case 502:
164
0
      i502 = (struct SHARE_INFO_502 *)buffer;
165
166
0
      s502 = talloc(mem_ctx, struct srvsvc_NetShareInfo502);
167
0
      NT_STATUS_HAVE_NO_MEMORY(s502);
168
169
0
      s502->name    = i502->shi502_netname;
170
0
      s502->type    = i502->shi502_type;
171
0
      s502->comment   = i502->shi502_remark;
172
0
      s502->permissions = i502->shi502_permissions;
173
0
      s502->max_users   = i502->shi502_max_uses;
174
0
      s502->current_users = i502->shi502_current_uses;
175
0
      s502->path    = i502->shi502_path;
176
0
      s502->password    = i502->shi502_passwd;
177
0
      s502->sd_buf.sd_size  =
178
0
        ndr_size_security_descriptor(i502->shi502_security_descriptor, 0);
179
0
      s502->sd_buf.sd   = i502->shi502_security_descriptor;
180
181
0
      info->info502 = s502;
182
183
0
      break;
184
185
0
    case 1004:
186
0
      i1004 = (struct SHARE_INFO_1004 *)buffer;
187
188
0
      s1004 = talloc(mem_ctx, struct srvsvc_NetShareInfo1004);
189
0
      NT_STATUS_HAVE_NO_MEMORY(s1004);
190
191
0
      s1004->comment    = i1004->shi1004_remark;
192
193
0
      info->info1004 = s1004;
194
195
0
      break;
196
0
    default:
197
0
      return NT_STATUS_INVALID_PARAMETER;
198
0
  }
199
200
0
  return NT_STATUS_OK;
201
0
}
202
203
/****************************************************************
204
****************************************************************/
205
206
WERROR NetShareAdd_r(struct libnetapi_ctx *ctx,
207
         struct NetShareAdd *r)
208
0
{
209
0
  WERROR werr;
210
0
  NTSTATUS status;
211
0
  union srvsvc_NetShareInfo info;
212
0
  struct dcerpc_binding_handle *b;
213
214
0
  if (!r->in.buffer) {
215
0
    return WERR_INVALID_PARAMETER;
216
0
  }
217
218
0
  switch (r->in.level) {
219
0
    case 2:
220
0
    case 502:
221
0
      break;
222
0
    case 503:
223
0
      return WERR_NOT_SUPPORTED;
224
0
    default:
225
0
      return WERR_INVALID_LEVEL;
226
0
  }
227
228
0
  werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
229
0
              &ndr_table_srvsvc,
230
0
              &b);
231
0
  if (!W_ERROR_IS_OK(werr)) {
232
0
    goto done;
233
0
  }
234
235
0
  status = map_SHARE_INFO_buffer_to_srvsvc_share_info(ctx,
236
0
                  r->in.buffer,
237
0
                  r->in.level,
238
0
                  &info);
239
0
  if (!NT_STATUS_IS_OK(status)) {
240
0
    werr = ntstatus_to_werror(status);
241
0
    goto done;
242
0
  }
243
244
0
  status = dcerpc_srvsvc_NetShareAdd(b, talloc_tos(),
245
0
             r->in.server_name,
246
0
             r->in.level,
247
0
             &info,
248
0
             r->out.parm_err,
249
0
             &werr);
250
0
  if (!NT_STATUS_IS_OK(status)) {
251
0
    werr = ntstatus_to_werror(status);
252
0
    goto done;
253
0
  }
254
255
0
  if (!W_ERROR_IS_OK(werr)) {
256
0
    goto done;
257
0
  }
258
259
0
 done:
260
0
  return werr;
261
0
}
262
263
/****************************************************************
264
****************************************************************/
265
266
WERROR NetShareAdd_l(struct libnetapi_ctx *ctx,
267
         struct NetShareAdd *r)
268
0
{
269
0
  LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetShareAdd);
270
0
}
271
272
/****************************************************************
273
****************************************************************/
274
275
WERROR NetShareDel_r(struct libnetapi_ctx *ctx,
276
         struct NetShareDel *r)
277
0
{
278
0
  WERROR werr;
279
0
  NTSTATUS status;
280
0
  struct dcerpc_binding_handle *b;
281
282
0
  if (!r->in.net_name) {
283
0
    return WERR_INVALID_PARAMETER;
284
0
  }
285
286
0
  werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
287
0
              &ndr_table_srvsvc,
288
0
              &b);
289
0
  if (!W_ERROR_IS_OK(werr)) {
290
0
    goto done;
291
0
  }
292
293
0
  status = dcerpc_srvsvc_NetShareDel(b, talloc_tos(),
294
0
             r->in.server_name,
295
0
             r->in.net_name,
296
0
             r->in.reserved,
297
0
             &werr);
298
0
  if (!NT_STATUS_IS_OK(status)) {
299
0
    werr = ntstatus_to_werror(status);
300
0
    goto done;
301
0
  }
302
303
0
 done:
304
0
  return werr;
305
0
}
306
307
/****************************************************************
308
****************************************************************/
309
310
WERROR NetShareDel_l(struct libnetapi_ctx *ctx,
311
         struct NetShareDel *r)
312
0
{
313
0
  LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetShareDel);
314
0
}
315
316
/****************************************************************
317
****************************************************************/
318
319
WERROR NetShareEnum_r(struct libnetapi_ctx *ctx,
320
          struct NetShareEnum *r)
321
0
{
322
0
  WERROR werr;
323
0
  NTSTATUS status;
324
0
  struct srvsvc_NetShareInfoCtr info_ctr;
325
0
  struct srvsvc_NetShareCtr0 ctr0;
326
0
  struct srvsvc_NetShareCtr1 ctr1;
327
0
  struct srvsvc_NetShareCtr2 ctr2;
328
0
  uint32_t i;
329
0
  struct dcerpc_binding_handle *b;
330
331
0
  if (!r->out.buffer) {
332
0
    return WERR_INVALID_PARAMETER;
333
0
  }
334
335
0
  switch (r->in.level) {
336
0
    case 0:
337
0
    case 1:
338
0
    case 2:
339
0
      break;
340
0
    case 502:
341
0
    case 503:
342
0
      return WERR_NOT_SUPPORTED;
343
0
    default:
344
0
      return WERR_INVALID_LEVEL;
345
0
  }
346
347
0
  ZERO_STRUCT(info_ctr);
348
349
0
  werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
350
0
              &ndr_table_srvsvc,
351
0
              &b);
352
0
  if (!W_ERROR_IS_OK(werr)) {
353
0
    goto done;
354
0
  }
355
356
0
  info_ctr.level = r->in.level;
357
0
  switch (r->in.level) {
358
0
    case 0:
359
0
      ZERO_STRUCT(ctr0);
360
0
      info_ctr.ctr.ctr0 = &ctr0;
361
0
      break;
362
0
    case 1:
363
0
      ZERO_STRUCT(ctr1);
364
0
      info_ctr.ctr.ctr1 = &ctr1;
365
0
      break;
366
0
    case 2:
367
0
      ZERO_STRUCT(ctr2);
368
0
      info_ctr.ctr.ctr2 = &ctr2;
369
0
      break;
370
0
  }
371
372
0
  status = dcerpc_srvsvc_NetShareEnumAll(b, talloc_tos(),
373
0
                 r->in.server_name,
374
0
                 &info_ctr,
375
0
                 r->in.prefmaxlen,
376
0
                 r->out.total_entries,
377
0
                 r->out.resume_handle,
378
0
                 &werr);
379
0
  if (!NT_STATUS_IS_OK(status)) {
380
0
    werr = ntstatus_to_werror(status);
381
0
    goto done;
382
0
  }
383
384
0
  if (!W_ERROR_IS_OK(werr) && !W_ERROR_EQUAL(werr, WERR_MORE_DATA)) {
385
0
    goto done;
386
0
  }
387
388
0
  for (i=0; i < info_ctr.ctr.ctr1->count; i++) {
389
0
    union srvsvc_NetShareInfo _i = {0};
390
0
    switch (r->in.level) {
391
0
      case 0:
392
0
        _i.info0 = &info_ctr.ctr.ctr0->array[i];
393
0
        break;
394
0
      case 1:
395
0
        _i.info1 = &info_ctr.ctr.ctr1->array[i];
396
0
        break;
397
0
      case 2:
398
0
        _i.info2 = &info_ctr.ctr.ctr2->array[i];
399
0
        break;
400
0
    }
401
402
0
    status = map_srvsvc_share_info_to_SHARE_INFO_buffer(ctx,
403
0
                    r->in.level,
404
0
                    &_i,
405
0
                    r->out.buffer,
406
0
                    r->out.entries_read);
407
0
    if (!NT_STATUS_IS_OK(status)) {
408
0
      werr = ntstatus_to_werror(status);
409
0
      goto done;
410
0
    }
411
0
  }
412
413
0
 done:
414
0
  return werr;
415
0
}
416
417
/****************************************************************
418
****************************************************************/
419
420
WERROR NetShareEnum_l(struct libnetapi_ctx *ctx,
421
          struct NetShareEnum *r)
422
0
{
423
0
  LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetShareEnum);
424
0
}
425
426
/****************************************************************
427
****************************************************************/
428
429
WERROR NetShareGetInfo_r(struct libnetapi_ctx *ctx,
430
       struct NetShareGetInfo *r)
431
0
{
432
0
  WERROR werr;
433
0
  NTSTATUS status;
434
0
  union srvsvc_NetShareInfo info;
435
0
  uint32_t num_entries = 0;
436
0
  struct dcerpc_binding_handle *b;
437
438
0
  if (!r->in.net_name || !r->out.buffer) {
439
0
    return WERR_INVALID_PARAMETER;
440
0
  }
441
442
0
  switch (r->in.level) {
443
0
    case 0:
444
0
    case 1:
445
0
    case 2:
446
0
    case 501:
447
0
    case 1005:
448
0
      break;
449
0
    case 502:
450
0
    case 503:
451
0
      return WERR_NOT_SUPPORTED;
452
0
    default:
453
0
      return WERR_INVALID_LEVEL;
454
0
  }
455
456
0
  werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
457
0
              &ndr_table_srvsvc,
458
0
              &b);
459
0
  if (!W_ERROR_IS_OK(werr)) {
460
0
    goto done;
461
0
  }
462
463
0
  status = dcerpc_srvsvc_NetShareGetInfo(b, talloc_tos(),
464
0
                 r->in.server_name,
465
0
                 r->in.net_name,
466
0
                 r->in.level,
467
0
                 &info,
468
0
                 &werr);
469
0
  if (!NT_STATUS_IS_OK(status)) {
470
0
    werr = ntstatus_to_werror(status);
471
0
    goto done;
472
0
  }
473
474
0
  if (!W_ERROR_IS_OK(werr)) {
475
0
    goto done;
476
0
  }
477
478
0
  status = map_srvsvc_share_info_to_SHARE_INFO_buffer(ctx,
479
0
                  r->in.level,
480
0
                  &info,
481
0
                  r->out.buffer,
482
0
                  &num_entries);
483
0
  if (!NT_STATUS_IS_OK(status)) {
484
0
    werr = ntstatus_to_werror(status);
485
0
  }
486
487
0
 done:
488
0
  return werr;
489
0
}
490
491
/****************************************************************
492
****************************************************************/
493
494
WERROR NetShareGetInfo_l(struct libnetapi_ctx *ctx,
495
       struct NetShareGetInfo *r)
496
0
{
497
0
  LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetShareGetInfo);
498
0
}
499
500
/****************************************************************
501
****************************************************************/
502
503
WERROR NetShareSetInfo_r(struct libnetapi_ctx *ctx,
504
       struct NetShareSetInfo *r)
505
0
{
506
0
  WERROR werr;
507
0
  NTSTATUS status;
508
0
  union srvsvc_NetShareInfo info;
509
0
  struct dcerpc_binding_handle *b;
510
511
0
  if (!r->in.buffer) {
512
0
    return WERR_INVALID_PARAMETER;
513
0
  }
514
515
0
  switch (r->in.level) {
516
0
    case 2:
517
0
    case 1004:
518
0
      break;
519
0
    case 1:
520
0
    case 502:
521
0
    case 503:
522
0
    case 1005:
523
0
    case 1006:
524
0
    case 1501:
525
0
      return WERR_NOT_SUPPORTED;
526
0
    default:
527
0
      return WERR_INVALID_LEVEL;
528
0
  }
529
530
0
  werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
531
0
              &ndr_table_srvsvc,
532
0
              &b);
533
0
  if (!W_ERROR_IS_OK(werr)) {
534
0
    goto done;
535
0
  }
536
537
0
  status = map_SHARE_INFO_buffer_to_srvsvc_share_info(ctx,
538
0
                  r->in.buffer,
539
0
                  r->in.level,
540
0
                  &info);
541
0
  if (!NT_STATUS_IS_OK(status)) {
542
0
    werr = ntstatus_to_werror(status);
543
0
    goto done;
544
0
  }
545
546
0
  status = dcerpc_srvsvc_NetShareSetInfo(b, talloc_tos(),
547
0
                 r->in.server_name,
548
0
                 r->in.net_name,
549
0
                 r->in.level,
550
0
                 &info,
551
0
                 r->out.parm_err,
552
0
                 &werr);
553
0
  if (!NT_STATUS_IS_OK(status)) {
554
0
    werr = ntstatus_to_werror(status);
555
0
    goto done;
556
0
  }
557
558
0
  if (!W_ERROR_IS_OK(werr)) {
559
0
    goto done;
560
0
  }
561
562
0
 done:
563
0
  return werr;
564
0
}
565
566
/****************************************************************
567
****************************************************************/
568
569
WERROR NetShareSetInfo_l(struct libnetapi_ctx *ctx,
570
       struct NetShareSetInfo *r)
571
0
{
572
0
  LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetShareSetInfo);
573
0
}