Coverage Report

Created: 2025-07-23 07:04

/src/samba/source3/lib/netapi/group.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 *  Unix SMB/CIFS implementation.
3
 *  NetApi Group 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 "rpc_client/rpc_client.h"
27
#include "../librpc/gen_ndr/ndr_samr_c.h"
28
#include "rpc_client/init_lsa.h"
29
#include "../libcli/security/security.h"
30
31
/****************************************************************
32
****************************************************************/
33
34
WERROR NetGroupAdd_r(struct libnetapi_ctx *ctx,
35
         struct NetGroupAdd *r)
36
0
{
37
0
  struct rpc_pipe_client *pipe_cli = NULL;
38
0
  NTSTATUS status, result;
39
0
  WERROR werr;
40
0
  struct policy_handle connect_handle, domain_handle, group_handle;
41
0
  struct lsa_String lsa_group_name;
42
0
  struct dom_sid2 *domain_sid = NULL;
43
0
  uint32_t rid = 0;
44
0
  struct dcerpc_binding_handle *b = NULL;
45
46
0
  struct GROUP_INFO_0 *info0 = NULL;
47
0
  struct GROUP_INFO_1 *info1 = NULL;
48
0
  struct GROUP_INFO_2 *info2 = NULL;
49
0
  struct GROUP_INFO_3 *info3 = NULL;
50
0
  union samr_GroupInfo info;
51
52
0
  ZERO_STRUCT(connect_handle);
53
0
  ZERO_STRUCT(domain_handle);
54
0
  ZERO_STRUCT(group_handle);
55
56
0
  if (!r->in.buffer) {
57
0
    return WERR_INVALID_PARAMETER;
58
0
  }
59
60
0
  switch (r->in.level) {
61
0
    case 0:
62
0
      info0 = (struct GROUP_INFO_0 *)r->in.buffer;
63
0
      break;
64
0
    case 1:
65
0
      info1 = (struct GROUP_INFO_1 *)r->in.buffer;
66
0
      break;
67
0
    case 2:
68
0
      info2 = (struct GROUP_INFO_2 *)r->in.buffer;
69
0
      break;
70
0
    case 3:
71
0
      info3 = (struct GROUP_INFO_3 *)r->in.buffer;
72
0
      break;
73
0
    default:
74
0
      werr = WERR_INVALID_LEVEL;
75
0
      goto done;
76
0
  }
77
78
0
  werr = libnetapi_open_pipe(ctx, r->in.server_name,
79
0
           &ndr_table_samr,
80
0
           &pipe_cli);
81
0
  if (!W_ERROR_IS_OK(werr)) {
82
0
    goto done;
83
0
  }
84
85
0
  b = pipe_cli->binding_handle;
86
87
0
  werr = libnetapi_samr_open_domain(ctx, pipe_cli,
88
0
            SAMR_ACCESS_ENUM_DOMAINS |
89
0
            SAMR_ACCESS_LOOKUP_DOMAIN,
90
0
            SAMR_DOMAIN_ACCESS_CREATE_GROUP |
91
0
            SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
92
0
            &connect_handle,
93
0
            &domain_handle,
94
0
            &domain_sid);
95
0
  if (!W_ERROR_IS_OK(werr)) {
96
0
    goto done;
97
0
  }
98
99
0
  switch (r->in.level) {
100
0
    case 0:
101
0
      init_lsa_String(&lsa_group_name, info0->grpi0_name);
102
0
      break;
103
0
    case 1:
104
0
      init_lsa_String(&lsa_group_name, info1->grpi1_name);
105
0
      break;
106
0
    case 2:
107
0
      init_lsa_String(&lsa_group_name, info2->grpi2_name);
108
0
      break;
109
0
    case 3:
110
0
      init_lsa_String(&lsa_group_name, info3->grpi3_name);
111
0
      break;
112
0
  }
113
114
0
  status = dcerpc_samr_CreateDomainGroup(b, talloc_tos(),
115
0
                 &domain_handle,
116
0
                 &lsa_group_name,
117
0
                 SEC_STD_DELETE |
118
0
                 SAMR_GROUP_ACCESS_SET_INFO,
119
0
                 &group_handle,
120
0
                 &rid,
121
0
                 &result);
122
123
0
  if (any_nt_status_not_ok(status, result, &status)) {
124
0
    werr = ntstatus_to_werror(status);
125
0
    goto done;
126
0
  }
127
128
0
  switch (r->in.level) {
129
0
    case 1:
130
0
      if (info1->grpi1_comment) {
131
0
        init_lsa_String(&info.description,
132
0
            info1->grpi1_comment);
133
134
0
        status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
135
0
                  &group_handle,
136
0
                  GROUPINFODESCRIPTION,
137
0
                  &info,
138
0
                  &result);
139
0
      }
140
0
      break;
141
0
    case 2:
142
0
      if (info2->grpi2_comment) {
143
0
        init_lsa_String(&info.description,
144
0
            info2->grpi2_comment);
145
146
0
        status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
147
0
                  &group_handle,
148
0
                  GROUPINFODESCRIPTION,
149
0
                  &info,
150
0
                  &result);
151
0
        if (any_nt_status_not_ok(
152
0
              status, result, &status)) {
153
0
          werr = ntstatus_to_werror(status);
154
0
          goto failed;
155
0
        }
156
0
      }
157
158
0
      if (info2->grpi2_attributes != 0) {
159
0
        info.attributes.attributes = info2->grpi2_attributes;
160
0
        status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
161
0
                  &group_handle,
162
0
                  GROUPINFOATTRIBUTES,
163
0
                  &info,
164
0
                  &result);
165
166
0
      }
167
0
      break;
168
0
    case 3:
169
0
      if (info3->grpi3_comment) {
170
0
        init_lsa_String(&info.description,
171
0
            info3->grpi3_comment);
172
173
0
        status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
174
0
                  &group_handle,
175
0
                  GROUPINFODESCRIPTION,
176
0
                  &info,
177
0
                  &result);
178
0
        if (any_nt_status_not_ok(
179
0
              status, result, &status)) {
180
0
          werr = ntstatus_to_werror(status);
181
0
          goto failed;
182
0
        }
183
0
      }
184
185
0
      if (info3->grpi3_attributes != 0) {
186
0
        info.attributes.attributes = info3->grpi3_attributes;
187
0
        status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
188
0
                  &group_handle,
189
0
                  GROUPINFOATTRIBUTES,
190
0
                  &info,
191
0
                  &result);
192
0
      }
193
0
      break;
194
0
    default:
195
0
      break;
196
0
  }
197
198
0
  if (any_nt_status_not_ok(status, result, &status)) {
199
0
    werr = ntstatus_to_werror(status);
200
0
    goto failed;
201
0
  }
202
203
0
  werr = WERR_OK;
204
0
  goto done;
205
206
0
 failed:
207
0
  dcerpc_samr_DeleteDomainGroup(b, talloc_tos(),
208
0
              &group_handle, &result);
209
210
0
 done:
211
0
  if (is_valid_policy_hnd(&group_handle)) {
212
0
    dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
213
0
  }
214
215
0
  if (ctx->disable_policy_handle_cache) {
216
0
    libnetapi_samr_close_domain_handle(ctx, &domain_handle);
217
0
    libnetapi_samr_close_connect_handle(ctx, &connect_handle);
218
0
  }
219
220
0
  return werr;
221
0
}
222
223
/****************************************************************
224
****************************************************************/
225
226
WERROR NetGroupAdd_l(struct libnetapi_ctx *ctx,
227
         struct NetGroupAdd *r)
228
0
{
229
0
  LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAdd);
230
0
}
231
232
/****************************************************************
233
****************************************************************/
234
235
WERROR NetGroupDel_r(struct libnetapi_ctx *ctx,
236
         struct NetGroupDel *r)
237
0
{
238
0
  struct rpc_pipe_client *pipe_cli = NULL;
239
0
  NTSTATUS status, result;
240
0
  WERROR werr;
241
0
  struct policy_handle connect_handle, domain_handle, group_handle;
242
0
  struct lsa_String lsa_group_name;
243
0
  struct dom_sid2 *domain_sid = NULL;
244
0
  int i = 0;
245
0
  struct dcerpc_binding_handle *b = NULL;
246
247
0
  struct samr_Ids rids;
248
0
  struct samr_Ids types;
249
0
  union samr_GroupInfo *info = NULL;
250
0
  struct samr_RidAttrArray *rid_array = NULL;
251
252
0
  ZERO_STRUCT(connect_handle);
253
0
  ZERO_STRUCT(domain_handle);
254
0
  ZERO_STRUCT(group_handle);
255
256
0
  if (!r->in.group_name) {
257
0
    return WERR_INVALID_PARAMETER;
258
0
  }
259
260
0
  werr = libnetapi_open_pipe(ctx, r->in.server_name,
261
0
           &ndr_table_samr,
262
0
           &pipe_cli);
263
0
  if (!W_ERROR_IS_OK(werr)) {
264
0
    goto done;
265
0
  }
266
267
0
  b = pipe_cli->binding_handle;
268
269
0
  werr = libnetapi_samr_open_domain(ctx, pipe_cli,
270
0
            SAMR_ACCESS_ENUM_DOMAINS |
271
0
            SAMR_ACCESS_LOOKUP_DOMAIN,
272
0
            SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
273
0
            &connect_handle,
274
0
            &domain_handle,
275
0
            &domain_sid);
276
0
  if (!W_ERROR_IS_OK(werr)) {
277
0
    goto done;
278
0
  }
279
280
0
  init_lsa_String(&lsa_group_name, r->in.group_name);
281
282
0
  status = dcerpc_samr_LookupNames(b, talloc_tos(),
283
0
           &domain_handle,
284
0
           1,
285
0
           &lsa_group_name,
286
0
           &rids,
287
0
           &types,
288
0
           &result);
289
0
  if (any_nt_status_not_ok(status, result, &status)) {
290
0
    werr = ntstatus_to_werror(status);
291
0
    goto done;
292
0
  }
293
294
0
  if (rids.count != 1) {
295
0
    werr = WERR_BAD_NET_RESP;
296
0
    goto done;
297
0
  }
298
0
  if (types.count != 1) {
299
0
    werr = WERR_BAD_NET_RESP;
300
0
    goto done;
301
0
  }
302
303
0
  if (types.ids[0] != SID_NAME_DOM_GRP) {
304
0
    werr = WERR_INVALID_DATATYPE;
305
0
    goto done;
306
0
  }
307
308
0
  status = dcerpc_samr_OpenGroup(b, talloc_tos(),
309
0
               &domain_handle,
310
0
               SEC_STD_DELETE |
311
0
               SAMR_GROUP_ACCESS_GET_MEMBERS |
312
0
               SAMR_GROUP_ACCESS_REMOVE_MEMBER |
313
0
               SAMR_GROUP_ACCESS_ADD_MEMBER |
314
0
               SAMR_GROUP_ACCESS_LOOKUP_INFO,
315
0
               rids.ids[0],
316
0
               &group_handle,
317
0
               &result);
318
0
  if (any_nt_status_not_ok(status, result, &status)) {
319
0
    werr = ntstatus_to_werror(status);
320
0
    goto done;
321
0
  }
322
323
0
  status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
324
0
              &group_handle,
325
0
              GROUPINFOATTRIBUTES,
326
0
              &info,
327
0
              &result);
328
0
  if (any_nt_status_not_ok(status, result, &status)) {
329
0
    werr = ntstatus_to_werror(status);
330
0
    goto done;
331
0
  }
332
333
#if 0
334
  /* breaks against NT4 */
335
  if (!(info->attributes.attributes & SE_GROUP_ENABLED)) {
336
    werr = WERR_ACCESS_DENIED;
337
    goto done;
338
  }
339
#endif
340
0
  status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
341
0
                &group_handle,
342
0
                &rid_array,
343
0
                &result);
344
0
  if (any_nt_status_not_ok(status, result, &status)) {
345
0
    werr = ntstatus_to_werror(status);
346
0
    goto done;
347
0
  }
348
349
0
  {
350
0
  struct lsa_Strings names;
351
0
  struct samr_Ids member_types;
352
353
0
  status = dcerpc_samr_LookupRids(b, talloc_tos(),
354
0
          &domain_handle,
355
0
          rid_array->count,
356
0
          rid_array->rids,
357
0
          &names,
358
0
          &member_types,
359
0
          &result);
360
0
  if (any_nt_status_not_ok(status, result, &status)) {
361
0
    werr = ntstatus_to_werror(status);
362
0
    goto done;
363
0
  }
364
0
  if (names.count != rid_array->count) {
365
0
    werr = WERR_BAD_NET_RESP;
366
0
    goto done;
367
0
  }
368
0
  if (member_types.count != rid_array->count) {
369
0
    werr = WERR_BAD_NET_RESP;
370
0
    goto done;
371
0
  }
372
0
  }
373
374
0
  for (i=0; i < rid_array->count; i++) {
375
376
0
    status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
377
0
                   &group_handle,
378
0
                   rid_array->rids[i],
379
0
                   &result);
380
0
    if (any_nt_status_not_ok(status, result, &status)) {
381
0
      werr = ntstatus_to_werror(status);
382
0
      goto done;
383
0
    }
384
0
  }
385
386
0
  status = dcerpc_samr_DeleteDomainGroup(b, talloc_tos(),
387
0
                 &group_handle,
388
0
                 &result);
389
0
  if (any_nt_status_not_ok(status, result, &status)) {
390
0
    werr = ntstatus_to_werror(status);
391
0
    goto done;
392
0
  }
393
394
0
  ZERO_STRUCT(group_handle);
395
396
0
  werr = WERR_OK;
397
398
0
 done:
399
0
  if (is_valid_policy_hnd(&group_handle)) {
400
0
    dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
401
0
  }
402
403
0
  if (ctx->disable_policy_handle_cache) {
404
0
    libnetapi_samr_close_domain_handle(ctx, &domain_handle);
405
0
    libnetapi_samr_close_connect_handle(ctx, &connect_handle);
406
0
  }
407
408
0
  return werr;
409
0
}
410
411
/****************************************************************
412
****************************************************************/
413
414
WERROR NetGroupDel_l(struct libnetapi_ctx *ctx,
415
         struct NetGroupDel *r)
416
0
{
417
0
  LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDel);
418
0
}
419
420
/****************************************************************
421
****************************************************************/
422
423
WERROR NetGroupSetInfo_r(struct libnetapi_ctx *ctx,
424
       struct NetGroupSetInfo *r)
425
0
{
426
0
  struct rpc_pipe_client *pipe_cli = NULL;
427
0
  NTSTATUS status, result;
428
0
  WERROR werr;
429
0
  struct policy_handle connect_handle, domain_handle, group_handle;
430
0
  struct lsa_String lsa_group_name;
431
0
  struct dom_sid2 *domain_sid = NULL;
432
0
  struct dcerpc_binding_handle *b = NULL;
433
434
0
  struct samr_Ids rids;
435
0
  struct samr_Ids types;
436
0
  union samr_GroupInfo info;
437
0
  struct GROUP_INFO_0 *g0;
438
0
  struct GROUP_INFO_1 *g1;
439
0
  struct GROUP_INFO_2 *g2;
440
0
  struct GROUP_INFO_3 *g3;
441
0
  struct GROUP_INFO_1002 *g1002;
442
0
  struct GROUP_INFO_1005 *g1005;
443
444
0
  ZERO_STRUCT(connect_handle);
445
0
  ZERO_STRUCT(domain_handle);
446
0
  ZERO_STRUCT(group_handle);
447
448
0
  if (!r->in.group_name) {
449
0
    return WERR_INVALID_PARAMETER;
450
0
  }
451
452
0
  werr = libnetapi_open_pipe(ctx, r->in.server_name,
453
0
           &ndr_table_samr,
454
0
           &pipe_cli);
455
0
  if (!W_ERROR_IS_OK(werr)) {
456
0
    goto done;
457
0
  }
458
459
0
  b = pipe_cli->binding_handle;
460
461
0
  werr = libnetapi_samr_open_domain(ctx, pipe_cli,
462
0
            SAMR_ACCESS_ENUM_DOMAINS |
463
0
            SAMR_ACCESS_LOOKUP_DOMAIN,
464
0
            SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
465
0
            &connect_handle,
466
0
            &domain_handle,
467
0
            &domain_sid);
468
0
  if (!W_ERROR_IS_OK(werr)) {
469
0
    goto done;
470
0
  }
471
472
0
  init_lsa_String(&lsa_group_name, r->in.group_name);
473
474
0
  status = dcerpc_samr_LookupNames(b, talloc_tos(),
475
0
           &domain_handle,
476
0
           1,
477
0
           &lsa_group_name,
478
0
           &rids,
479
0
           &types,
480
0
           &result);
481
0
  if (any_nt_status_not_ok(status, result, &status)) {
482
0
    werr = ntstatus_to_werror(status);
483
0
    goto done;
484
0
  }
485
0
  if (rids.count != 1) {
486
0
    werr = WERR_BAD_NET_RESP;
487
0
    goto done;
488
0
  }
489
0
  if (types.count != 1) {
490
0
    werr = WERR_BAD_NET_RESP;
491
0
    goto done;
492
0
  }
493
494
0
  if (types.ids[0] != SID_NAME_DOM_GRP) {
495
0
    werr = WERR_INVALID_DATATYPE;
496
0
    goto done;
497
0
  }
498
499
0
  status = dcerpc_samr_OpenGroup(b, talloc_tos(),
500
0
               &domain_handle,
501
0
               SAMR_GROUP_ACCESS_SET_INFO |
502
0
               SAMR_GROUP_ACCESS_LOOKUP_INFO,
503
0
               rids.ids[0],
504
0
               &group_handle,
505
0
               &result);
506
0
  if (any_nt_status_not_ok(status, result, &status)) {
507
0
    werr = ntstatus_to_werror(status);
508
0
    goto done;
509
0
  }
510
511
0
  switch (r->in.level) {
512
0
    case 0:
513
0
      g0 = (struct GROUP_INFO_0 *)r->in.buffer;
514
0
      init_lsa_String(&info.name, g0->grpi0_name);
515
0
      status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
516
0
                &group_handle,
517
0
                GROUPINFONAME,
518
0
                &info,
519
0
                &result);
520
0
      break;
521
0
    case 1:
522
0
      g1 = (struct GROUP_INFO_1 *)r->in.buffer;
523
0
      init_lsa_String(&info.description, g1->grpi1_comment);
524
0
      status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
525
0
                &group_handle,
526
0
                GROUPINFODESCRIPTION,
527
0
                &info,
528
0
                &result);
529
0
      break;
530
0
    case 2:
531
0
      g2 = (struct GROUP_INFO_2 *)r->in.buffer;
532
0
      init_lsa_String(&info.description, g2->grpi2_comment);
533
0
      status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
534
0
                &group_handle,
535
0
                GROUPINFODESCRIPTION,
536
0
                &info,
537
0
                &result);
538
0
      if (any_nt_status_not_ok(status, result, &status)) {
539
0
        werr = ntstatus_to_werror(status);
540
0
        goto done;
541
0
      }
542
543
0
      info.attributes.attributes = g2->grpi2_attributes;
544
0
      status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
545
0
                &group_handle,
546
0
                GROUPINFOATTRIBUTES,
547
0
                &info,
548
0
                &result);
549
0
      break;
550
0
    case 3:
551
0
      g3 = (struct GROUP_INFO_3 *)r->in.buffer;
552
0
      init_lsa_String(&info.description, g3->grpi3_comment);
553
0
      status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
554
0
                &group_handle,
555
0
                GROUPINFODESCRIPTION,
556
0
                &info,
557
0
                &result);
558
0
      if (any_nt_status_not_ok(status, result, &status)) {
559
0
        werr = ntstatus_to_werror(status);
560
0
        goto done;
561
0
      }
562
563
0
      info.attributes.attributes = g3->grpi3_attributes;
564
0
      status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
565
0
                &group_handle,
566
0
                GROUPINFOATTRIBUTES,
567
0
                &info,
568
0
                &result);
569
0
      break;
570
0
    case 1002:
571
0
      g1002 = (struct GROUP_INFO_1002 *)r->in.buffer;
572
0
      init_lsa_String(&info.description, g1002->grpi1002_comment);
573
0
      status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
574
0
                &group_handle,
575
0
                GROUPINFODESCRIPTION,
576
0
                &info,
577
0
                &result);
578
0
      break;
579
0
    case 1005:
580
0
      g1005 = (struct GROUP_INFO_1005 *)r->in.buffer;
581
0
      info.attributes.attributes = g1005->grpi1005_attributes;
582
0
      status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
583
0
                &group_handle,
584
0
                GROUPINFOATTRIBUTES,
585
0
                &info,
586
0
                &result);
587
0
      break;
588
0
    default:
589
0
      status = NT_STATUS_INVALID_LEVEL;
590
0
      break;
591
0
  }
592
593
0
  if (any_nt_status_not_ok(status, result, &status)) {
594
0
    werr = ntstatus_to_werror(status);
595
0
    goto done;
596
0
  }
597
598
0
  werr = WERR_OK;
599
600
0
 done:
601
0
  if (is_valid_policy_hnd(&group_handle)) {
602
0
    dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
603
0
  }
604
605
0
  if (ctx->disable_policy_handle_cache) {
606
0
    libnetapi_samr_close_domain_handle(ctx, &domain_handle);
607
0
    libnetapi_samr_close_connect_handle(ctx, &connect_handle);
608
0
  }
609
610
0
  return werr;
611
0
}
612
613
/****************************************************************
614
****************************************************************/
615
616
WERROR NetGroupSetInfo_l(struct libnetapi_ctx *ctx,
617
       struct NetGroupSetInfo *r)
618
0
{
619
0
  LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetInfo);
620
0
}
621
622
/****************************************************************
623
****************************************************************/
624
625
static WERROR map_group_info_to_buffer(TALLOC_CTX *mem_ctx,
626
               uint32_t level,
627
               struct samr_GroupInfoAll *info,
628
               struct dom_sid2 *domain_sid,
629
               uint32_t rid,
630
               uint8_t **buffer)
631
0
{
632
0
  struct GROUP_INFO_0 info0;
633
0
  struct GROUP_INFO_1 info1;
634
0
  struct GROUP_INFO_2 info2;
635
0
  struct GROUP_INFO_3 info3;
636
0
  struct dom_sid sid;
637
638
0
  switch (level) {
639
0
    case 0:
640
0
      info0.grpi0_name  = info->name.string;
641
642
0
      *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0, sizeof(info0));
643
644
0
      break;
645
0
    case 1:
646
0
      info1.grpi1_name  = info->name.string;
647
0
      info1.grpi1_comment = info->description.string;
648
649
0
      *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1, sizeof(info1));
650
651
0
      break;
652
0
    case 2:
653
0
      info2.grpi2_name  = info->name.string;
654
0
      info2.grpi2_comment = info->description.string;
655
0
      info2.grpi2_group_id  = rid;
656
0
      info2.grpi2_attributes  = info->attributes;
657
658
0
      *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2, sizeof(info2));
659
660
0
      break;
661
0
    case 3:
662
0
      if (!sid_compose(&sid, domain_sid, rid)) {
663
0
        return WERR_NOT_ENOUGH_MEMORY;
664
0
      }
665
666
0
      info3.grpi3_name  = info->name.string;
667
0
      info3.grpi3_comment = info->description.string;
668
0
      info3.grpi3_attributes  = info->attributes;
669
0
      info3.grpi3_group_sid = (struct domsid *)dom_sid_dup(mem_ctx, &sid);
670
671
0
      *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3, sizeof(info3));
672
673
0
      break;
674
0
    default:
675
0
      return WERR_INVALID_LEVEL;
676
0
  }
677
678
0
  W_ERROR_HAVE_NO_MEMORY(*buffer);
679
680
0
  return WERR_OK;
681
0
}
682
683
/****************************************************************
684
****************************************************************/
685
686
WERROR NetGroupGetInfo_r(struct libnetapi_ctx *ctx,
687
       struct NetGroupGetInfo *r)
688
0
{
689
0
  struct rpc_pipe_client *pipe_cli = NULL;
690
0
  NTSTATUS status, result;
691
0
  WERROR werr;
692
0
  struct policy_handle connect_handle, domain_handle, group_handle;
693
0
  struct lsa_String lsa_group_name;
694
0
  struct dom_sid2 *domain_sid = NULL;
695
0
  struct dcerpc_binding_handle *b = NULL;
696
697
0
  struct samr_Ids rids;
698
0
  struct samr_Ids types;
699
0
  union samr_GroupInfo *info = NULL;
700
0
  bool group_info_all = false;
701
702
0
  ZERO_STRUCT(connect_handle);
703
0
  ZERO_STRUCT(domain_handle);
704
0
  ZERO_STRUCT(group_handle);
705
706
0
  if (!r->in.group_name) {
707
0
    return WERR_INVALID_PARAMETER;
708
0
  }
709
710
0
  werr = libnetapi_open_pipe(ctx, r->in.server_name,
711
0
           &ndr_table_samr,
712
0
           &pipe_cli);
713
0
  if (!W_ERROR_IS_OK(werr)) {
714
0
    goto done;
715
0
  }
716
717
0
  b = pipe_cli->binding_handle;
718
719
0
  werr = libnetapi_samr_open_domain(ctx, pipe_cli,
720
0
            SAMR_ACCESS_ENUM_DOMAINS |
721
0
            SAMR_ACCESS_LOOKUP_DOMAIN,
722
0
            SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
723
0
            &connect_handle,
724
0
            &domain_handle,
725
0
            &domain_sid);
726
0
  if (!W_ERROR_IS_OK(werr)) {
727
0
    goto done;
728
0
  }
729
730
0
  init_lsa_String(&lsa_group_name, r->in.group_name);
731
732
0
  status = dcerpc_samr_LookupNames(b, talloc_tos(),
733
0
           &domain_handle,
734
0
           1,
735
0
           &lsa_group_name,
736
0
           &rids,
737
0
           &types,
738
0
           &result);
739
0
  if (any_nt_status_not_ok(status, result, &status)) {
740
0
    werr = ntstatus_to_werror(status);
741
0
    goto done;
742
0
  }
743
0
  if (rids.count != 1) {
744
0
    werr = WERR_BAD_NET_RESP;
745
0
    goto done;
746
0
  }
747
0
  if (types.count != 1) {
748
0
    werr = WERR_BAD_NET_RESP;
749
0
    goto done;
750
0
  }
751
752
0
  if (types.ids[0] != SID_NAME_DOM_GRP) {
753
0
    werr = WERR_INVALID_DATATYPE;
754
0
    goto done;
755
0
  }
756
757
0
  status = dcerpc_samr_OpenGroup(b, talloc_tos(),
758
0
               &domain_handle,
759
0
               SAMR_GROUP_ACCESS_LOOKUP_INFO,
760
0
               rids.ids[0],
761
0
               &group_handle,
762
0
               &result);
763
0
  if (any_nt_status_not_ok(status, result, &status)) {
764
0
    werr = ntstatus_to_werror(status);
765
0
    goto done;
766
0
  }
767
768
0
  status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
769
0
              &group_handle,
770
0
              GROUPINFOALL2,
771
0
              &info,
772
0
              &result);
773
0
  if (!NT_STATUS_IS_OK(status)) {
774
0
    werr = ntstatus_to_werror(status);
775
0
    goto done;
776
0
  }
777
778
0
  if (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_INFO_CLASS)) {
779
0
    status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
780
0
                &group_handle,
781
0
                GROUPINFOALL,
782
0
                &info,
783
0
                &result);
784
0
    group_info_all = true;
785
0
    if (!NT_STATUS_IS_OK(status)) {
786
0
      werr = ntstatus_to_werror(status);
787
0
      goto done;
788
0
    }
789
0
  }
790
791
0
  if (!NT_STATUS_IS_OK(result)) {
792
0
    werr = ntstatus_to_werror(result);
793
0
    goto done;
794
0
  }
795
796
0
  werr = map_group_info_to_buffer(ctx, r->in.level,
797
0
          group_info_all ? &info->all : &info->all2,
798
0
          domain_sid, rids.ids[0],
799
0
          r->out.buffer);
800
0
  if (!W_ERROR_IS_OK(werr)) {
801
0
    goto done;
802
0
  }
803
0
 done:
804
0
  if (is_valid_policy_hnd(&group_handle)) {
805
0
    dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
806
0
  }
807
808
0
  if (ctx->disable_policy_handle_cache) {
809
0
    libnetapi_samr_close_domain_handle(ctx, &domain_handle);
810
0
    libnetapi_samr_close_connect_handle(ctx, &connect_handle);
811
0
  }
812
813
0
  return werr;
814
0
}
815
816
/****************************************************************
817
****************************************************************/
818
819
WERROR NetGroupGetInfo_l(struct libnetapi_ctx *ctx,
820
       struct NetGroupGetInfo *r)
821
0
{
822
0
  LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetInfo);
823
0
}
824
825
/****************************************************************
826
****************************************************************/
827
828
WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx,
829
       struct NetGroupAddUser *r)
830
0
{
831
0
  struct rpc_pipe_client *pipe_cli = NULL;
832
0
  NTSTATUS status, result;
833
0
  WERROR werr;
834
0
  struct policy_handle connect_handle, domain_handle, group_handle;
835
0
  struct lsa_String lsa_group_name, lsa_user_name;
836
0
  struct dom_sid2 *domain_sid = NULL;
837
0
  struct dcerpc_binding_handle *b = NULL;
838
839
0
  struct samr_Ids rids;
840
0
  struct samr_Ids types;
841
842
0
  ZERO_STRUCT(connect_handle);
843
0
  ZERO_STRUCT(domain_handle);
844
0
  ZERO_STRUCT(group_handle);
845
846
0
  if (!r->in.group_name) {
847
0
    return WERR_INVALID_PARAMETER;
848
0
  }
849
850
0
  werr = libnetapi_open_pipe(ctx, r->in.server_name,
851
0
           &ndr_table_samr,
852
0
           &pipe_cli);
853
0
  if (!W_ERROR_IS_OK(werr)) {
854
0
    goto done;
855
0
  }
856
857
0
  b = pipe_cli->binding_handle;
858
859
0
  werr = libnetapi_samr_open_domain(ctx, pipe_cli,
860
0
            SAMR_ACCESS_ENUM_DOMAINS |
861
0
            SAMR_ACCESS_LOOKUP_DOMAIN,
862
0
            SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
863
0
            &connect_handle,
864
0
            &domain_handle,
865
0
            &domain_sid);
866
0
  if (!W_ERROR_IS_OK(werr)) {
867
0
    goto done;
868
0
  }
869
870
0
  init_lsa_String(&lsa_group_name, r->in.group_name);
871
872
0
  status = dcerpc_samr_LookupNames(b, talloc_tos(),
873
0
           &domain_handle,
874
0
           1,
875
0
           &lsa_group_name,
876
0
           &rids,
877
0
           &types,
878
0
           &result);
879
0
  if (!NT_STATUS_IS_OK(status)) {
880
0
    werr = ntstatus_to_werror(status);
881
0
    goto done;
882
0
  }
883
0
  if (!NT_STATUS_IS_OK(result)) {
884
0
    werr = WERR_NERR_GROUPNOTFOUND;
885
0
    goto done;
886
0
  }
887
0
  if (rids.count != 1) {
888
0
    werr = WERR_BAD_NET_RESP;
889
0
    goto done;
890
0
  }
891
0
  if (types.count != 1) {
892
0
    werr = WERR_BAD_NET_RESP;
893
0
    goto done;
894
0
  }
895
896
0
  if (types.ids[0] != SID_NAME_DOM_GRP) {
897
0
    werr = WERR_NERR_GROUPNOTFOUND;
898
0
    goto done;
899
0
  }
900
901
0
  status = dcerpc_samr_OpenGroup(b, talloc_tos(),
902
0
               &domain_handle,
903
0
               SAMR_GROUP_ACCESS_ADD_MEMBER,
904
0
               rids.ids[0],
905
0
               &group_handle,
906
0
               &result);
907
0
  if (any_nt_status_not_ok(status, result, &status)) {
908
0
    werr = ntstatus_to_werror(status);
909
0
    goto done;
910
0
  }
911
912
0
  init_lsa_String(&lsa_user_name, r->in.user_name);
913
914
0
  status = dcerpc_samr_LookupNames(b, talloc_tos(),
915
0
           &domain_handle,
916
0
           1,
917
0
           &lsa_user_name,
918
0
           &rids,
919
0
           &types,
920
0
           &result);
921
0
  if (!NT_STATUS_IS_OK(status)) {
922
0
    werr = ntstatus_to_werror(status);
923
0
    goto done;
924
0
  }
925
0
  if (!NT_STATUS_IS_OK(result)) {
926
0
    werr = WERR_NERR_USERNOTFOUND;
927
0
    goto done;
928
0
  }
929
0
  if (rids.count != 1) {
930
0
    werr = WERR_BAD_NET_RESP;
931
0
    goto done;
932
0
  }
933
0
  if (types.count != 1) {
934
0
    werr = WERR_BAD_NET_RESP;
935
0
    goto done;
936
0
  }
937
938
0
  if (types.ids[0] != SID_NAME_USER) {
939
0
    werr = WERR_NERR_USERNOTFOUND;
940
0
    goto done;
941
0
  }
942
943
0
  status = dcerpc_samr_AddGroupMember(b, talloc_tos(),
944
0
              &group_handle,
945
0
              rids.ids[0],
946
0
              7, /* why ? */
947
0
              &result);
948
0
  if (any_nt_status_not_ok(status, result, &status)) {
949
0
    werr = ntstatus_to_werror(status);
950
0
    goto done;
951
0
  }
952
953
0
  werr = WERR_OK;
954
955
0
 done:
956
0
  if (is_valid_policy_hnd(&group_handle)) {
957
0
    dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
958
0
  }
959
960
0
  if (ctx->disable_policy_handle_cache) {
961
0
    libnetapi_samr_close_domain_handle(ctx, &domain_handle);
962
0
    libnetapi_samr_close_connect_handle(ctx, &connect_handle);
963
0
  }
964
965
0
  return werr;
966
0
}
967
968
/****************************************************************
969
****************************************************************/
970
971
WERROR NetGroupAddUser_l(struct libnetapi_ctx *ctx,
972
       struct NetGroupAddUser *r)
973
0
{
974
0
  LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAddUser);
975
0
}
976
977
/****************************************************************
978
****************************************************************/
979
980
WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx,
981
       struct NetGroupDelUser *r)
982
0
{
983
0
  struct rpc_pipe_client *pipe_cli = NULL;
984
0
  NTSTATUS status, result;
985
0
  WERROR werr;
986
0
  struct policy_handle connect_handle, domain_handle, group_handle;
987
0
  struct lsa_String lsa_group_name, lsa_user_name;
988
0
  struct dom_sid2 *domain_sid = NULL;
989
0
  struct dcerpc_binding_handle *b = NULL;
990
991
0
  struct samr_Ids rids;
992
0
  struct samr_Ids types;
993
994
0
  ZERO_STRUCT(connect_handle);
995
0
  ZERO_STRUCT(domain_handle);
996
0
  ZERO_STRUCT(group_handle);
997
998
0
  if (!r->in.group_name) {
999
0
    return WERR_INVALID_PARAMETER;
1000
0
  }
1001
1002
0
  werr = libnetapi_open_pipe(ctx, r->in.server_name,
1003
0
           &ndr_table_samr,
1004
0
           &pipe_cli);
1005
0
  if (!W_ERROR_IS_OK(werr)) {
1006
0
    goto done;
1007
0
  }
1008
1009
0
  b = pipe_cli->binding_handle;
1010
1011
0
  werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1012
0
            SAMR_ACCESS_ENUM_DOMAINS |
1013
0
            SAMR_ACCESS_LOOKUP_DOMAIN,
1014
0
            SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1015
0
            &connect_handle,
1016
0
            &domain_handle,
1017
0
            &domain_sid);
1018
0
  if (!W_ERROR_IS_OK(werr)) {
1019
0
    goto done;
1020
0
  }
1021
1022
0
  init_lsa_String(&lsa_group_name, r->in.group_name);
1023
1024
0
  status = dcerpc_samr_LookupNames(b, talloc_tos(),
1025
0
           &domain_handle,
1026
0
           1,
1027
0
           &lsa_group_name,
1028
0
           &rids,
1029
0
           &types,
1030
0
           &result);
1031
0
  if (!NT_STATUS_IS_OK(status)) {
1032
0
    werr = ntstatus_to_werror(status);
1033
0
    goto done;
1034
0
  }
1035
0
  if (!NT_STATUS_IS_OK(result)) {
1036
0
    werr = WERR_NERR_GROUPNOTFOUND;
1037
0
    goto done;
1038
0
  }
1039
0
  if (rids.count != 1) {
1040
0
    werr = WERR_BAD_NET_RESP;
1041
0
    goto done;
1042
0
  }
1043
0
  if (types.count != 1) {
1044
0
    werr = WERR_BAD_NET_RESP;
1045
0
    goto done;
1046
0
  }
1047
1048
0
  if (types.ids[0] != SID_NAME_DOM_GRP) {
1049
0
    werr = WERR_NERR_GROUPNOTFOUND;
1050
0
    goto done;
1051
0
  }
1052
1053
0
  status = dcerpc_samr_OpenGroup(b, talloc_tos(),
1054
0
               &domain_handle,
1055
0
               SAMR_GROUP_ACCESS_REMOVE_MEMBER,
1056
0
               rids.ids[0],
1057
0
               &group_handle,
1058
0
               &result);
1059
0
  if (any_nt_status_not_ok(status, result, &status)) {
1060
0
    werr = ntstatus_to_werror(status);
1061
0
    goto done;
1062
0
  }
1063
1064
0
  init_lsa_String(&lsa_user_name, r->in.user_name);
1065
1066
0
  status = dcerpc_samr_LookupNames(b, talloc_tos(),
1067
0
           &domain_handle,
1068
0
           1,
1069
0
           &lsa_user_name,
1070
0
           &rids,
1071
0
           &types,
1072
0
           &result);
1073
0
  if (!NT_STATUS_IS_OK(status)) {
1074
0
    werr = ntstatus_to_werror(status);
1075
0
    goto done;
1076
0
  }
1077
1078
0
  if (!NT_STATUS_IS_OK(result)) {
1079
0
    werr = WERR_NERR_USERNOTFOUND;
1080
0
    goto done;
1081
0
  }
1082
0
  if (rids.count != 1) {
1083
0
    werr = WERR_BAD_NET_RESP;
1084
0
    goto done;
1085
0
  }
1086
0
  if (types.count != 1) {
1087
0
    werr = WERR_BAD_NET_RESP;
1088
0
    goto done;
1089
0
  }
1090
1091
0
  if (types.ids[0] != SID_NAME_USER) {
1092
0
    werr = WERR_NERR_USERNOTFOUND;
1093
0
    goto done;
1094
0
  }
1095
1096
0
  status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
1097
0
                 &group_handle,
1098
0
                 rids.ids[0],
1099
0
                 &result);
1100
0
  if (any_nt_status_not_ok(status, result, &status)) {
1101
0
    werr = ntstatus_to_werror(status);
1102
0
    goto done;
1103
0
  }
1104
1105
0
  werr = WERR_OK;
1106
1107
0
 done:
1108
0
  if (is_valid_policy_hnd(&group_handle)) {
1109
0
    dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
1110
0
  }
1111
1112
0
  if (ctx->disable_policy_handle_cache) {
1113
0
    libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1114
0
    libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1115
0
  }
1116
1117
0
  return werr;
1118
0
}
1119
1120
/****************************************************************
1121
****************************************************************/
1122
1123
WERROR NetGroupDelUser_l(struct libnetapi_ctx *ctx,
1124
       struct NetGroupDelUser *r)
1125
0
{
1126
0
  LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDelUser);
1127
0
}
1128
1129
/****************************************************************
1130
****************************************************************/
1131
1132
static WERROR convert_samr_disp_groups_to_GROUP_INFO_0_buffer(TALLOC_CTX *mem_ctx,
1133
                    struct samr_DispInfoFullGroups *groups,
1134
                    uint8_t **buffer)
1135
0
{
1136
0
  struct GROUP_INFO_0 *g0;
1137
0
  int i;
1138
1139
0
  g0 = talloc_zero_array(mem_ctx, struct GROUP_INFO_0, groups->count);
1140
0
  W_ERROR_HAVE_NO_MEMORY(g0);
1141
1142
0
  for (i=0; i<groups->count; i++) {
1143
0
    g0[i].grpi0_name = talloc_strdup(mem_ctx,
1144
0
      groups->entries[i].account_name.string);
1145
0
    W_ERROR_HAVE_NO_MEMORY(g0[i].grpi0_name);
1146
0
  }
1147
1148
0
  *buffer = (uint8_t *)talloc_memdup(mem_ctx, g0,
1149
0
             sizeof(struct GROUP_INFO_0) * groups->count);
1150
0
  W_ERROR_HAVE_NO_MEMORY(*buffer);
1151
1152
0
  return WERR_OK;
1153
0
}
1154
1155
/****************************************************************
1156
****************************************************************/
1157
1158
static WERROR convert_samr_disp_groups_to_GROUP_INFO_1_buffer(TALLOC_CTX *mem_ctx,
1159
                    struct samr_DispInfoFullGroups *groups,
1160
                    uint8_t **buffer)
1161
0
{
1162
0
  struct GROUP_INFO_1 *g1;
1163
0
  int i;
1164
1165
0
  g1 = talloc_zero_array(mem_ctx, struct GROUP_INFO_1, groups->count);
1166
0
  W_ERROR_HAVE_NO_MEMORY(g1);
1167
1168
0
  for (i=0; i<groups->count; i++) {
1169
0
    g1[i].grpi1_name = talloc_strdup(mem_ctx,
1170
0
      groups->entries[i].account_name.string);
1171
0
    g1[i].grpi1_comment = talloc_strdup(mem_ctx,
1172
0
      groups->entries[i].description.string);
1173
0
    W_ERROR_HAVE_NO_MEMORY(g1[i].grpi1_name);
1174
0
  }
1175
1176
0
  *buffer = (uint8_t *)talloc_memdup(mem_ctx, g1,
1177
0
             sizeof(struct GROUP_INFO_1) * groups->count);
1178
0
  W_ERROR_HAVE_NO_MEMORY(*buffer);
1179
1180
0
  return WERR_OK;
1181
0
}
1182
1183
/****************************************************************
1184
****************************************************************/
1185
1186
static WERROR convert_samr_disp_groups_to_GROUP_INFO_2_buffer(TALLOC_CTX *mem_ctx,
1187
                    struct samr_DispInfoFullGroups *groups,
1188
                    uint8_t **buffer)
1189
0
{
1190
0
  struct GROUP_INFO_2 *g2;
1191
0
  int i;
1192
1193
0
  g2 = talloc_zero_array(mem_ctx, struct GROUP_INFO_2, groups->count);
1194
0
  W_ERROR_HAVE_NO_MEMORY(g2);
1195
1196
0
  for (i=0; i<groups->count; i++) {
1197
0
    g2[i].grpi2_name = talloc_strdup(mem_ctx,
1198
0
      groups->entries[i].account_name.string);
1199
0
    g2[i].grpi2_comment = talloc_strdup(mem_ctx,
1200
0
      groups->entries[i].description.string);
1201
0
    g2[i].grpi2_group_id = groups->entries[i].rid;
1202
0
    g2[i].grpi2_attributes = groups->entries[i].acct_flags;
1203
0
    W_ERROR_HAVE_NO_MEMORY(g2[i].grpi2_name);
1204
0
  }
1205
1206
0
  *buffer = (uint8_t *)talloc_memdup(mem_ctx, g2,
1207
0
             sizeof(struct GROUP_INFO_2) * groups->count);
1208
0
  W_ERROR_HAVE_NO_MEMORY(*buffer);
1209
1210
0
  return WERR_OK;
1211
0
}
1212
1213
/****************************************************************
1214
****************************************************************/
1215
1216
static WERROR convert_samr_disp_groups_to_GROUP_INFO_3_buffer(TALLOC_CTX *mem_ctx,
1217
                    struct samr_DispInfoFullGroups *groups,
1218
                    const struct dom_sid *domain_sid,
1219
                    uint8_t **buffer)
1220
0
{
1221
0
  struct GROUP_INFO_3 *g3;
1222
0
  int i;
1223
1224
0
  g3 = talloc_zero_array(mem_ctx, struct GROUP_INFO_3, groups->count);
1225
0
  W_ERROR_HAVE_NO_MEMORY(g3);
1226
1227
0
  for (i=0; i<groups->count; i++) {
1228
1229
0
    struct dom_sid sid;
1230
1231
0
    if (!sid_compose(&sid, domain_sid, groups->entries[i].rid)) {
1232
0
      return WERR_NOT_ENOUGH_MEMORY;
1233
0
    }
1234
1235
0
    g3[i].grpi3_name = talloc_strdup(mem_ctx,
1236
0
      groups->entries[i].account_name.string);
1237
0
    g3[i].grpi3_comment = talloc_strdup(mem_ctx,
1238
0
      groups->entries[i].description.string);
1239
0
    g3[i].grpi3_group_sid = (struct domsid *)dom_sid_dup(mem_ctx, &sid);
1240
0
    g3[i].grpi3_attributes = groups->entries[i].acct_flags;
1241
0
    W_ERROR_HAVE_NO_MEMORY(g3[i].grpi3_name);
1242
0
  }
1243
1244
0
  *buffer = (uint8_t *)talloc_memdup(mem_ctx, g3,
1245
0
             sizeof(struct GROUP_INFO_3) * groups->count);
1246
0
  W_ERROR_HAVE_NO_MEMORY(*buffer);
1247
1248
0
  return WERR_OK;
1249
0
}
1250
1251
/****************************************************************
1252
****************************************************************/
1253
1254
static WERROR convert_samr_disp_groups_to_GROUP_INFO_buffer(TALLOC_CTX *mem_ctx,
1255
                  uint32_t level,
1256
                  struct samr_DispInfoFullGroups *groups,
1257
                  const struct dom_sid *domain_sid,
1258
                  uint32_t *entries_read,
1259
                  uint8_t **buffer)
1260
0
{
1261
0
  if (entries_read) {
1262
0
    *entries_read = groups->count;
1263
0
  }
1264
1265
0
  switch (level) {
1266
0
    case 0:
1267
0
      return convert_samr_disp_groups_to_GROUP_INFO_0_buffer(mem_ctx, groups, buffer);
1268
0
    case 1:
1269
0
      return convert_samr_disp_groups_to_GROUP_INFO_1_buffer(mem_ctx, groups, buffer);
1270
0
    case 2:
1271
0
      return convert_samr_disp_groups_to_GROUP_INFO_2_buffer(mem_ctx, groups, buffer);
1272
0
    case 3:
1273
0
      return convert_samr_disp_groups_to_GROUP_INFO_3_buffer(mem_ctx, groups, domain_sid, buffer);
1274
0
    default:
1275
0
      return WERR_INVALID_LEVEL;
1276
0
  }
1277
0
}
1278
1279
/****************************************************************
1280
****************************************************************/
1281
1282
WERROR NetGroupEnum_r(struct libnetapi_ctx *ctx,
1283
          struct NetGroupEnum *r)
1284
0
{
1285
0
  struct rpc_pipe_client *pipe_cli = NULL;
1286
0
  struct policy_handle connect_handle;
1287
0
  struct dom_sid2 *domain_sid = NULL;
1288
0
  struct policy_handle domain_handle;
1289
0
  union samr_DispInfo info;
1290
0
  union samr_DomainInfo *domain_info = NULL;
1291
0
  struct dcerpc_binding_handle *b = NULL;
1292
1293
0
  uint32_t total_size = 0;
1294
0
  uint32_t returned_size = 0;
1295
1296
0
  NTSTATUS result = NT_STATUS_OK;
1297
0
  NTSTATUS status;
1298
0
  WERROR werr, tmp_werr;
1299
1300
0
  ZERO_STRUCT(connect_handle);
1301
0
  ZERO_STRUCT(domain_handle);
1302
1303
0
  switch (r->in.level) {
1304
0
    case 0:
1305
0
    case 1:
1306
0
    case 2:
1307
0
    case 3:
1308
0
      break;
1309
0
    default:
1310
0
      return WERR_INVALID_LEVEL;
1311
0
  }
1312
1313
0
  werr = libnetapi_open_pipe(ctx, r->in.server_name,
1314
0
           &ndr_table_samr,
1315
0
           &pipe_cli);
1316
0
  if (!W_ERROR_IS_OK(werr)) {
1317
0
    goto done;
1318
0
  }
1319
1320
0
  b = pipe_cli->binding_handle;
1321
1322
0
  werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1323
0
            SAMR_ACCESS_ENUM_DOMAINS |
1324
0
            SAMR_ACCESS_LOOKUP_DOMAIN,
1325
0
            SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1326
0
            SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1327
0
            SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1328
0
            &connect_handle,
1329
0
            &domain_handle,
1330
0
            &domain_sid);
1331
0
  if (!W_ERROR_IS_OK(werr)) {
1332
0
    goto done;
1333
0
  }
1334
1335
0
  status = dcerpc_samr_QueryDomainInfo(b, talloc_tos(),
1336
0
               &domain_handle,
1337
0
               2,
1338
0
               &domain_info,
1339
0
               &result);
1340
0
  if (any_nt_status_not_ok(status, result, &status)) {
1341
0
    werr = ntstatus_to_werror(status);
1342
0
    goto done;
1343
0
  }
1344
1345
0
  if (r->out.total_entries) {
1346
0
    *r->out.total_entries = domain_info->general.num_groups;
1347
0
  }
1348
1349
0
  status = dcerpc_samr_QueryDisplayInfo2(b,
1350
0
                 ctx,
1351
0
                 &domain_handle,
1352
0
                 3,
1353
0
                 r->in.resume_handle ?
1354
0
                 *r->in.resume_handle : 0,
1355
0
                 (uint32_t)-1,
1356
0
                 r->in.prefmaxlen,
1357
0
                 &total_size,
1358
0
                 &returned_size,
1359
0
                 &info,
1360
0
                 &result);
1361
0
  if (!NT_STATUS_IS_OK(status)) {
1362
0
    werr = ntstatus_to_werror(status);
1363
0
    goto done;
1364
0
  }
1365
1366
0
  werr = ntstatus_to_werror(result);
1367
0
  if (NT_STATUS_IS_ERR(result)) {
1368
0
    goto done;
1369
0
  }
1370
1371
0
  if (r->out.resume_handle && info.info3.count > 0) {
1372
0
    *r->out.resume_handle =
1373
0
      info.info3.entries[info.info3.count-1].idx;
1374
0
  }
1375
1376
0
  tmp_werr = convert_samr_disp_groups_to_GROUP_INFO_buffer(ctx,
1377
0
                 r->in.level,
1378
0
                 &info.info3,
1379
0
                 domain_sid,
1380
0
                 r->out.entries_read,
1381
0
                 r->out.buffer);
1382
0
  if (!W_ERROR_IS_OK(tmp_werr)) {
1383
0
    werr = tmp_werr;
1384
0
    goto done;
1385
0
  }
1386
1387
0
 done:
1388
  /* if last query */
1389
0
  if (NT_STATUS_IS_OK(result) ||
1390
0
      NT_STATUS_IS_ERR(result)) {
1391
1392
0
    if (ctx->disable_policy_handle_cache) {
1393
0
      libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1394
0
      libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1395
0
    }
1396
0
  }
1397
1398
0
  return werr;
1399
0
}
1400
1401
/****************************************************************
1402
****************************************************************/
1403
1404
WERROR NetGroupEnum_l(struct libnetapi_ctx *ctx,
1405
          struct NetGroupEnum *r)
1406
0
{
1407
0
  LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupEnum);
1408
0
}
1409
1410
/****************************************************************
1411
****************************************************************/
1412
1413
WERROR NetGroupGetUsers_r(struct libnetapi_ctx *ctx,
1414
        struct NetGroupGetUsers *r)
1415
0
{
1416
  /* FIXME: this call needs to cope with large replies */
1417
1418
0
  struct rpc_pipe_client *pipe_cli = NULL;
1419
0
  struct policy_handle connect_handle, domain_handle, group_handle;
1420
0
  struct lsa_String lsa_account_name;
1421
0
  struct dom_sid2 *domain_sid = NULL;
1422
0
  struct samr_Ids group_rids, name_types;
1423
0
  struct samr_RidAttrArray *rid_array = NULL;
1424
0
  struct lsa_Strings names;
1425
0
  struct samr_Ids member_types;
1426
0
  struct dcerpc_binding_handle *b = NULL;
1427
1428
0
  int i;
1429
0
  uint32_t entries_read = 0;
1430
1431
0
  NTSTATUS status;
1432
0
  NTSTATUS result = NT_STATUS_OK;
1433
0
  WERROR werr;
1434
1435
0
  ZERO_STRUCT(connect_handle);
1436
0
  ZERO_STRUCT(domain_handle);
1437
0
  ZERO_STRUCT(group_handle);
1438
1439
0
  if (!r->out.buffer) {
1440
0
    return WERR_INVALID_PARAMETER;
1441
0
  }
1442
1443
0
  *r->out.buffer = NULL;
1444
0
  *r->out.entries_read = 0;
1445
0
  *r->out.total_entries = 0;
1446
1447
0
  switch (r->in.level) {
1448
0
    case 0:
1449
0
    case 1:
1450
0
      break;
1451
0
    default:
1452
0
      return WERR_INVALID_LEVEL;
1453
0
  }
1454
1455
1456
0
  werr = libnetapi_open_pipe(ctx, r->in.server_name,
1457
0
           &ndr_table_samr,
1458
0
           &pipe_cli);
1459
0
  if (!W_ERROR_IS_OK(werr)) {
1460
0
    goto done;
1461
0
  }
1462
1463
0
  b = pipe_cli->binding_handle;
1464
1465
0
  werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1466
0
            SAMR_ACCESS_ENUM_DOMAINS |
1467
0
            SAMR_ACCESS_LOOKUP_DOMAIN,
1468
0
            SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1469
0
            &connect_handle,
1470
0
            &domain_handle,
1471
0
            &domain_sid);
1472
0
  if (!W_ERROR_IS_OK(werr)) {
1473
0
    goto done;
1474
0
  }
1475
1476
0
  init_lsa_String(&lsa_account_name, r->in.group_name);
1477
1478
0
  status = dcerpc_samr_LookupNames(b, talloc_tos(),
1479
0
           &domain_handle,
1480
0
           1,
1481
0
           &lsa_account_name,
1482
0
           &group_rids,
1483
0
           &name_types,
1484
0
           &result);
1485
0
  if (any_nt_status_not_ok(status, result, &status)) {
1486
0
    werr = ntstatus_to_werror(status);
1487
0
    goto done;
1488
0
  }
1489
0
  if (group_rids.count != 1) {
1490
0
    werr = WERR_BAD_NET_RESP;
1491
0
    goto done;
1492
0
  }
1493
0
  if (name_types.count != 1) {
1494
0
    werr = WERR_BAD_NET_RESP;
1495
0
    goto done;
1496
0
  }
1497
1498
0
  status = dcerpc_samr_OpenGroup(b, talloc_tos(),
1499
0
               &domain_handle,
1500
0
               SAMR_GROUP_ACCESS_GET_MEMBERS,
1501
0
               group_rids.ids[0],
1502
0
               &group_handle,
1503
0
               &result);
1504
0
  if (any_nt_status_not_ok(status, result, &status)) {
1505
0
    werr = ntstatus_to_werror(status);
1506
0
    goto done;
1507
0
  }
1508
1509
0
  status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
1510
0
                &group_handle,
1511
0
                &rid_array,
1512
0
                &result);
1513
0
  if (any_nt_status_not_ok(status, result, &status)) {
1514
0
    werr = ntstatus_to_werror(status);
1515
0
    goto done;
1516
0
  }
1517
1518
0
  status = dcerpc_samr_LookupRids(b, talloc_tos(),
1519
0
          &domain_handle,
1520
0
          rid_array->count,
1521
0
          rid_array->rids,
1522
0
          &names,
1523
0
          &member_types,
1524
0
          &result);
1525
0
  if (any_nt_status_not_ok(status, result, &status)) {
1526
0
    werr = ntstatus_to_werror(status);
1527
0
    goto done;
1528
0
  }
1529
0
  if (names.count != rid_array->count) {
1530
0
    werr = WERR_BAD_NET_RESP;
1531
0
    goto done;
1532
0
  }
1533
0
  if (member_types.count != rid_array->count) {
1534
0
    werr = WERR_BAD_NET_RESP;
1535
0
    goto done;
1536
0
  }
1537
1538
0
  for (i=0; i < names.count; i++) {
1539
1540
0
    if (member_types.ids[i] != SID_NAME_USER) {
1541
0
      continue;
1542
0
    }
1543
1544
0
    status = add_GROUP_USERS_INFO_X_buffer(ctx,
1545
0
                   r->in.level,
1546
0
                   names.names[i].string,
1547
0
                   7,
1548
0
                   r->out.buffer,
1549
0
                   &entries_read);
1550
0
    if (!NT_STATUS_IS_OK(status)) {
1551
0
      werr = ntstatus_to_werror(status);
1552
0
      goto done;
1553
0
    }
1554
0
  }
1555
1556
0
  *r->out.entries_read = entries_read;
1557
0
  *r->out.total_entries = entries_read;
1558
1559
0
  werr = WERR_OK;
1560
1561
0
 done:
1562
0
  if (is_valid_policy_hnd(&group_handle)) {
1563
0
    dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
1564
0
  }
1565
1566
0
  if (ctx->disable_policy_handle_cache) {
1567
0
    libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1568
0
    libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1569
0
  }
1570
1571
0
  return werr;
1572
0
}
1573
1574
/****************************************************************
1575
****************************************************************/
1576
1577
WERROR NetGroupGetUsers_l(struct libnetapi_ctx *ctx,
1578
        struct NetGroupGetUsers *r)
1579
0
{
1580
0
  LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetUsers);
1581
0
}
1582
1583
/****************************************************************
1584
****************************************************************/
1585
1586
WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx,
1587
        struct NetGroupSetUsers *r)
1588
0
{
1589
0
  struct rpc_pipe_client *pipe_cli = NULL;
1590
0
  struct policy_handle connect_handle, domain_handle, group_handle;
1591
0
  struct lsa_String lsa_account_name;
1592
0
  struct dom_sid2 *domain_sid = NULL;
1593
0
  union samr_GroupInfo *group_info = NULL;
1594
0
  struct samr_Ids user_rids, name_types;
1595
0
  struct samr_Ids group_rids, group_types;
1596
0
  struct samr_RidAttrArray *rid_array = NULL;
1597
0
  struct lsa_String *lsa_names = NULL;
1598
0
  struct dcerpc_binding_handle *b = NULL;
1599
1600
0
  uint32_t *add_rids = NULL;
1601
0
  uint32_t *del_rids = NULL;
1602
0
  size_t num_add_rids = 0;
1603
0
  size_t num_del_rids = 0;
1604
1605
0
  uint32_t *member_rids = NULL;
1606
1607
0
  struct GROUP_USERS_INFO_0 *i0 = NULL;
1608
0
  struct GROUP_USERS_INFO_1 *i1 = NULL;
1609
1610
0
  int i, k;
1611
1612
0
  NTSTATUS status;
1613
0
  NTSTATUS result = NT_STATUS_OK;
1614
0
  WERROR werr;
1615
1616
0
  ZERO_STRUCT(connect_handle);
1617
0
  ZERO_STRUCT(domain_handle);
1618
0
  ZERO_STRUCT(group_handle);
1619
1620
0
  if (!r->in.buffer) {
1621
0
    return WERR_INVALID_PARAMETER;
1622
0
  }
1623
1624
0
  switch (r->in.level) {
1625
0
    case 0:
1626
0
    case 1:
1627
0
      break;
1628
0
    default:
1629
0
      return WERR_INVALID_LEVEL;
1630
0
  }
1631
1632
0
  werr = libnetapi_open_pipe(ctx, r->in.server_name,
1633
0
           &ndr_table_samr,
1634
0
           &pipe_cli);
1635
0
  if (!W_ERROR_IS_OK(werr)) {
1636
0
    goto done;
1637
0
  }
1638
1639
0
  b = pipe_cli->binding_handle;
1640
1641
0
  werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1642
0
            SAMR_ACCESS_ENUM_DOMAINS |
1643
0
            SAMR_ACCESS_LOOKUP_DOMAIN,
1644
0
            SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1645
0
            &connect_handle,
1646
0
            &domain_handle,
1647
0
            &domain_sid);
1648
0
  if (!W_ERROR_IS_OK(werr)) {
1649
0
    goto done;
1650
0
  }
1651
1652
0
  init_lsa_String(&lsa_account_name, r->in.group_name);
1653
1654
0
  status = dcerpc_samr_LookupNames(b, talloc_tos(),
1655
0
           &domain_handle,
1656
0
           1,
1657
0
           &lsa_account_name,
1658
0
           &group_rids,
1659
0
           &group_types,
1660
0
           &result);
1661
0
  if (any_nt_status_not_ok(status, result, &status)) {
1662
0
    werr = ntstatus_to_werror(status);
1663
0
    goto done;
1664
0
  }
1665
0
  if (group_rids.count != 1) {
1666
0
    werr = WERR_BAD_NET_RESP;
1667
0
    goto done;
1668
0
  }
1669
0
  if (group_types.count != 1) {
1670
0
    werr = WERR_BAD_NET_RESP;
1671
0
    goto done;
1672
0
  }
1673
1674
0
  status = dcerpc_samr_OpenGroup(b, talloc_tos(),
1675
0
               &domain_handle,
1676
0
               SAMR_GROUP_ACCESS_GET_MEMBERS |
1677
0
               SAMR_GROUP_ACCESS_ADD_MEMBER |
1678
0
               SAMR_GROUP_ACCESS_REMOVE_MEMBER |
1679
0
               SAMR_GROUP_ACCESS_LOOKUP_INFO,
1680
0
               group_rids.ids[0],
1681
0
               &group_handle,
1682
0
               &result);
1683
0
  if (any_nt_status_not_ok(status, result, &status)) {
1684
0
    werr = ntstatus_to_werror(status);
1685
0
    goto done;
1686
0
  }
1687
1688
0
  status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
1689
0
              &group_handle,
1690
0
              GROUPINFOATTRIBUTES,
1691
0
              &group_info,
1692
0
              &result);
1693
0
  if (any_nt_status_not_ok(status, result, &status)) {
1694
0
    werr = ntstatus_to_werror(status);
1695
0
    goto done;
1696
0
  }
1697
1698
0
  switch (r->in.level) {
1699
0
    case 0:
1700
0
      i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
1701
0
      break;
1702
0
    case 1:
1703
0
      i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
1704
0
      break;
1705
0
  }
1706
1707
0
  lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
1708
0
  if (!lsa_names) {
1709
0
    werr = WERR_NOT_ENOUGH_MEMORY;
1710
0
    goto done;
1711
0
  }
1712
1713
0
  for (i=0; i < r->in.num_entries; i++) {
1714
1715
0
    switch (r->in.level) {
1716
0
      case 0:
1717
0
        init_lsa_String(&lsa_names[i], i0->grui0_name);
1718
0
        i0++;
1719
0
        break;
1720
0
      case 1:
1721
0
        init_lsa_String(&lsa_names[i], i1->grui1_name);
1722
0
        i1++;
1723
0
        break;
1724
0
    }
1725
0
  }
1726
1727
0
  status = dcerpc_samr_LookupNames(b, talloc_tos(),
1728
0
           &domain_handle,
1729
0
           r->in.num_entries,
1730
0
           lsa_names,
1731
0
           &user_rids,
1732
0
           &name_types,
1733
0
           &result);
1734
0
  if (any_nt_status_not_ok(status, result, &status)) {
1735
0
    werr = ntstatus_to_werror(status);
1736
0
    goto done;
1737
0
  }
1738
1739
0
  if (r->in.num_entries != user_rids.count) {
1740
0
    werr = WERR_BAD_NET_RESP;
1741
0
    goto done;
1742
0
  }
1743
0
  if (r->in.num_entries != name_types.count) {
1744
0
    werr = WERR_BAD_NET_RESP;
1745
0
    goto done;
1746
0
  }
1747
1748
0
  member_rids = user_rids.ids;
1749
1750
0
  status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
1751
0
                &group_handle,
1752
0
                &rid_array,
1753
0
                &result);
1754
0
  if (any_nt_status_not_ok(status, result, &status)) {
1755
0
    werr = ntstatus_to_werror(status);
1756
0
    goto done;
1757
0
  }
1758
1759
  /* add list */
1760
1761
0
  for (i=0; i < r->in.num_entries; i++) {
1762
0
    bool already_member = false;
1763
0
    for (k=0; k < rid_array->count; k++) {
1764
0
      if (member_rids[i] == rid_array->rids[k]) {
1765
0
        already_member = true;
1766
0
        break;
1767
0
      }
1768
0
    }
1769
0
    if (!already_member) {
1770
0
      if (!add_rid_to_array_unique(ctx,
1771
0
                 member_rids[i],
1772
0
                 &add_rids, &num_add_rids)) {
1773
0
        werr = WERR_GEN_FAILURE;
1774
0
        goto done;
1775
0
      }
1776
0
    }
1777
0
  }
1778
1779
  /* del list */
1780
1781
0
  for (k=0; k < rid_array->count; k++) {
1782
0
    bool keep_member = false;
1783
0
    for (i=0; i < r->in.num_entries; i++) {
1784
0
      if (member_rids[i] == rid_array->rids[k]) {
1785
0
        keep_member = true;
1786
0
        break;
1787
0
      }
1788
0
    }
1789
0
    if (!keep_member) {
1790
0
      if (!add_rid_to_array_unique(ctx,
1791
0
                 rid_array->rids[k],
1792
0
                 &del_rids, &num_del_rids)) {
1793
0
        werr = WERR_GEN_FAILURE;
1794
0
        goto done;
1795
0
      }
1796
0
    }
1797
0
  }
1798
1799
  /* add list */
1800
1801
0
  for (i=0; i < num_add_rids; i++) {
1802
0
    status = dcerpc_samr_AddGroupMember(b, talloc_tos(),
1803
0
                &group_handle,
1804
0
                add_rids[i],
1805
0
                7 /* ? */,
1806
0
                &result);
1807
0
    if (any_nt_status_not_ok(status, result, &status)) {
1808
0
      werr = ntstatus_to_werror(status);
1809
0
      goto done;
1810
0
    }
1811
0
  }
1812
1813
  /* del list */
1814
1815
0
  for (i=0; i < num_del_rids; i++) {
1816
0
    status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
1817
0
                   &group_handle,
1818
0
                   del_rids[i],
1819
0
                   &result);
1820
0
    if (any_nt_status_not_ok(status, result, &status)) {
1821
0
      werr = ntstatus_to_werror(status);
1822
0
      goto done;
1823
0
    }
1824
0
  }
1825
1826
0
  werr = WERR_OK;
1827
1828
0
 done:
1829
0
  if (is_valid_policy_hnd(&group_handle)) {
1830
0
    dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
1831
0
  }
1832
1833
0
  if (ctx->disable_policy_handle_cache) {
1834
0
    libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1835
0
    libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1836
0
  }
1837
1838
0
  return werr;
1839
0
}
1840
1841
/****************************************************************
1842
****************************************************************/
1843
1844
WERROR NetGroupSetUsers_l(struct libnetapi_ctx *ctx,
1845
        struct NetGroupSetUsers *r)
1846
0
{
1847
0
  LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetUsers);
1848
0
}