Coverage Report

Created: 2026-04-01 06:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source3/lib/netapi/netapi.c
Line
Count
Source
1
/*
2
 *  Unix SMB/CIFS implementation.
3
 *  NetApi Support
4
 *  Copyright (C) Guenther Deschner 2007-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
#include "../libcli/auth/netlogon_creds_cli.h"
22
#include "lib/netapi/netapi.h"
23
#include "lib/netapi/netapi_private.h"
24
#include "secrets.h"
25
#include "source3/param/loadparm.h"
26
#include "lib/param/param.h"
27
#include "auth/gensec/gensec.h"
28
29
struct libnetapi_ctx *stat_ctx = NULL;
30
static bool libnetapi_initialized = false;
31
32
/****************************************************************
33
****************************************************************/
34
35
static NET_API_STATUS libnetapi_init_private_context(struct libnetapi_ctx *ctx)
36
0
{
37
0
  struct libnetapi_private_ctx *priv;
38
39
0
  if (!ctx) {
40
0
    return W_ERROR_V(WERR_INVALID_PARAMETER);
41
0
  }
42
43
0
  priv = talloc_zero(ctx, struct libnetapi_private_ctx);
44
0
  if (!priv) {
45
0
    return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
46
0
  }
47
48
0
  ctx->private_data = priv;
49
50
0
  return NET_API_STATUS_SUCCESS;
51
0
}
52
53
/****************************************************************
54
Create a libnetapi context, for use in non-Samba applications.  This
55
loads the smb.conf file and sets the debug level to 0, so that
56
applications are not flooded with debug logs at level 10, when they
57
were not expecting it.
58
****************************************************************/
59
60
NET_API_STATUS libnetapi_init(struct libnetapi_ctx **context)
61
0
{
62
0
  NET_API_STATUS ret;
63
0
  TALLOC_CTX *frame;
64
0
  struct loadparm_context *lp_ctx = NULL;
65
66
0
  if (stat_ctx && libnetapi_initialized) {
67
0
    *context = stat_ctx;
68
0
    return NET_API_STATUS_SUCCESS;
69
0
  }
70
71
#if 0
72
  talloc_enable_leak_report();
73
#endif
74
0
  frame = talloc_stackframe();
75
76
0
  lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
77
0
  if (lp_ctx == NULL) {
78
0
    TALLOC_FREE(frame);
79
0
    return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
80
0
  }
81
82
  /* When libnetapi is invoked from an application, it does not
83
   * want to be swamped with level 10 debug messages, even if
84
   * this has been set for the server in smb.conf */
85
0
  lpcfg_set_cmdline(lp_ctx, "log level", "0");
86
0
  setup_logging("libnetapi", DEBUG_STDERR);
87
88
0
  if (!lp_load_global(get_dyn_CONFIGFILE())) {
89
0
    TALLOC_FREE(frame);
90
0
    fprintf(stderr, "error loading %s\n", get_dyn_CONFIGFILE() );
91
0
    return W_ERROR_V(WERR_GEN_FAILURE);
92
0
  }
93
94
0
  load_interfaces();
95
0
  reopen_logs();
96
97
0
  BlockSignals(True, SIGPIPE);
98
99
0
  ret = libnetapi_net_init(context, lp_ctx, NULL);
100
0
  if (ret == NET_API_STATUS_SUCCESS) {
101
0
    talloc_steal(*context, lp_ctx);
102
0
  }
103
0
  TALLOC_FREE(frame);
104
0
  return ret;
105
0
}
106
107
/****************************************************************
108
Create a libnetapi context, for use inside the 'net' binary.
109
110
As we know net has already loaded the smb.conf file, and set the debug
111
level etc, this avoids doing so again (which causes trouble with -d on
112
the command line).
113
****************************************************************/
114
115
NET_API_STATUS libnetapi_net_init(struct libnetapi_ctx **context,
116
          struct loadparm_context *lp_ctx,
117
          struct cli_credentials *creds)
118
0
{
119
0
  NET_API_STATUS status;
120
0
  struct libnetapi_ctx *ctx = NULL;
121
0
  TALLOC_CTX *frame = NULL;
122
123
0
  if (stat_ctx != NULL && libnetapi_initialized) {
124
0
    *context = stat_ctx;
125
0
    return NET_API_STATUS_SUCCESS;
126
0
  }
127
128
0
  frame = talloc_stackframe();
129
0
  ctx = talloc_zero(frame, struct libnetapi_ctx);
130
0
  if (!ctx) {
131
0
    TALLOC_FREE(frame);
132
0
    return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
133
0
  }
134
135
0
  ctx->lp_ctx = lp_ctx;
136
137
0
  ctx->creds = creds;
138
0
  if (ctx->creds == NULL) {
139
0
    ctx->creds = cli_credentials_init(ctx);
140
0
    if (ctx->creds == NULL) {
141
0
      TALLOC_FREE(frame);
142
0
      return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
143
0
    }
144
    /* Ignore return code, as we might not have a smb.conf */
145
0
    (void)cli_credentials_guess(ctx->creds, lp_ctx);
146
0
  }
147
148
0
  BlockSignals(True, SIGPIPE);
149
150
0
  status = libnetapi_init_private_context(ctx);
151
0
  if (status != 0) {
152
0
    TALLOC_FREE(frame);
153
0
    return status;
154
0
  }
155
156
0
  libnetapi_initialized = true;
157
158
0
  talloc_steal(NULL, ctx);
159
0
  *context = stat_ctx = ctx;
160
161
0
  TALLOC_FREE(frame);
162
0
  return NET_API_STATUS_SUCCESS;
163
0
}
164
165
/****************************************************************
166
 Return the static libnetapi context
167
****************************************************************/
168
169
NET_API_STATUS libnetapi_getctx(struct libnetapi_ctx **ctx)
170
0
{
171
0
  if (stat_ctx) {
172
0
    *ctx = stat_ctx;
173
0
    return NET_API_STATUS_SUCCESS;
174
0
  }
175
176
0
  return libnetapi_init(ctx);
177
0
}
178
179
/****************************************************************
180
 Free the static libnetapi context
181
****************************************************************/
182
183
NET_API_STATUS libnetapi_free(struct libnetapi_ctx *ctx)
184
0
{
185
0
  TALLOC_CTX *frame;
186
187
0
  if (!ctx) {
188
0
    return NET_API_STATUS_SUCCESS;
189
0
  }
190
191
0
  frame = talloc_stackframe();
192
0
  libnetapi_samr_free(ctx);
193
194
0
  libnetapi_shutdown_cm(ctx);
195
196
0
  gfree_loadparm();
197
0
  gfree_charcnv();
198
0
  gfree_interfaces();
199
200
0
  secrets_shutdown();
201
202
0
  netlogon_creds_cli_close_global_db();
203
204
0
  if (ctx == stat_ctx) {
205
0
    stat_ctx = NULL;
206
0
  }
207
0
  TALLOC_FREE(ctx);
208
209
0
  gfree_debugsyms();
210
0
  talloc_free(frame);
211
212
0
  return NET_API_STATUS_SUCCESS;
213
0
}
214
215
/****************************************************************
216
 Override the current log level for libnetapi
217
****************************************************************/
218
219
NET_API_STATUS libnetapi_set_debuglevel(struct libnetapi_ctx *ctx,
220
          const char *debuglevel)
221
0
{
222
0
  TALLOC_CTX *frame = talloc_stackframe();
223
0
  ctx->debuglevel = talloc_strdup(ctx, debuglevel);
224
225
0
  if (!lpcfg_set_cmdline(ctx->lp_ctx, "log level", debuglevel)) {
226
0
    TALLOC_FREE(frame);
227
0
    return W_ERROR_V(WERR_GEN_FAILURE);
228
0
  }
229
0
  TALLOC_FREE(frame);
230
0
  return NET_API_STATUS_SUCCESS;
231
0
}
232
233
/****************************************************************
234
****************************************************************/
235
236
NET_API_STATUS libnetapi_set_logfile(struct libnetapi_ctx *ctx,
237
             const char *logfile)
238
0
{
239
0
  TALLOC_CTX *frame = talloc_stackframe();
240
0
  ctx->logfile = talloc_strdup(ctx, logfile);
241
242
0
  if (!lpcfg_set_cmdline(ctx->lp_ctx, "log file", logfile)) {
243
0
    TALLOC_FREE(frame);
244
0
    return W_ERROR_V(WERR_GEN_FAILURE);
245
0
  }
246
0
  debug_set_logfile(logfile);
247
0
  setup_logging("libnetapi", DEBUG_FILE);
248
0
  TALLOC_FREE(frame);
249
0
  return NET_API_STATUS_SUCCESS;
250
0
}
251
252
/****************************************************************
253
****************************************************************/
254
255
NET_API_STATUS libnetapi_get_debuglevel(struct libnetapi_ctx *ctx,
256
          char **debuglevel)
257
0
{
258
0
  *debuglevel = ctx->debuglevel;
259
0
  return NET_API_STATUS_SUCCESS;
260
0
}
261
262
/****************************************************************
263
****************************************************************/
264
265
/**
266
 * @brief Get the username of the libnet context
267
 *
268
 * @param[in]  ctx      The netapi context
269
 *
270
 * @param[in]  username A pointer to hold the username.
271
 *
272
 * @return 0 on success, an werror code otherwise.
273
 */
274
NET_API_STATUS libnetapi_get_username(struct libnetapi_ctx *ctx,
275
              const char **username)
276
0
{
277
0
  if (ctx == NULL) {
278
0
    return W_ERROR_V(WERR_INVALID_PARAMETER);
279
0
  }
280
281
0
  if (username != NULL) {
282
0
    *username = cli_credentials_get_username(ctx->creds);
283
0
  }
284
285
0
  return NET_API_STATUS_SUCCESS;
286
0
}
287
288
/**
289
 * @brief Get the password of the libnet context
290
 *
291
 * @param[in]  ctx      The netapi context
292
 *
293
 * @param[in]  password A pointer to hold the password.
294
 *
295
 * @return 0 on success, an werror code otherwise.
296
 */
297
NET_API_STATUS libnetapi_get_password(struct libnetapi_ctx *ctx,
298
              const char **password)
299
0
{
300
0
  if (ctx == NULL) {
301
0
    return W_ERROR_V(WERR_INVALID_PARAMETER);
302
0
  }
303
304
0
  if (password != NULL) {
305
0
    *password = cli_credentials_get_password(ctx->creds);
306
0
  }
307
308
0
  return NET_API_STATUS_SUCCESS;
309
0
}
310
311
NET_API_STATUS libnetapi_set_username(struct libnetapi_ctx *ctx,
312
              const char *username)
313
0
{
314
0
  if (ctx == NULL || username == NULL) {
315
0
    return W_ERROR_V(WERR_INVALID_PARAMETER);
316
0
  }
317
318
0
  cli_credentials_parse_string(ctx->creds, username, CRED_SPECIFIED);
319
320
0
  return NET_API_STATUS_SUCCESS;
321
0
}
322
323
NET_API_STATUS libnetapi_set_password(struct libnetapi_ctx *ctx,
324
              const char *password)
325
0
{
326
0
  bool ok;
327
328
0
  if (ctx == NULL || password == NULL) {
329
0
    return W_ERROR_V(WERR_INVALID_PARAMETER);
330
0
  }
331
332
0
  ok = cli_credentials_set_password(ctx->creds, password, CRED_SPECIFIED);
333
0
  if (!ok) {
334
0
    return W_ERROR_V(WERR_INTERNAL_ERROR);
335
0
  }
336
337
0
  return NET_API_STATUS_SUCCESS;
338
0
}
339
340
NET_API_STATUS libnetapi_set_workgroup(struct libnetapi_ctx *ctx,
341
               const char *workgroup)
342
0
{
343
0
  bool ok;
344
345
0
  ok = cli_credentials_set_domain(ctx->creds, workgroup, CRED_SPECIFIED);
346
0
  if (!ok) {
347
0
    return W_ERROR_V(WERR_INTERNAL_ERROR);
348
0
  }
349
350
0
  return NET_API_STATUS_SUCCESS;
351
0
}
352
353
/**
354
 * @brief Set the cli_credentials to be used in the netapi context
355
 *
356
 * @param[in]  ctx    The netapi context
357
 *
358
 * @param[in]  creds  The cli_credentials which should be used by netapi.
359
 *
360
 * @return 0 on success, an werror code otherwise.
361
 */
362
NET_API_STATUS libnetapi_set_creds(struct libnetapi_ctx *ctx,
363
           struct cli_credentials *creds)
364
0
{
365
0
  if (ctx == NULL || creds == NULL) {
366
0
    return W_ERROR_V(WERR_INVALID_PARAMETER);
367
0
  }
368
369
0
  ctx->creds = creds;
370
371
0
  return NET_API_STATUS_SUCCESS;
372
0
}
373
374
/**
375
 * @brief Get the credentials of the libnet context
376
 *
377
 * @param[in]  ctx      The netapi context
378
 *
379
 * @param[in]  creds    A pointer to hold the creds.
380
 *
381
 * @return 0 on success, an werror code otherwise.
382
 */
383
NET_API_STATUS libnetapi_get_creds(struct libnetapi_ctx *ctx,
384
           struct cli_credentials **creds)
385
0
{
386
0
  if (ctx == NULL) {
387
0
    return W_ERROR_V(WERR_INVALID_PARAMETER);
388
0
  }
389
390
0
  if (creds != NULL) {
391
0
    *creds = ctx->creds;
392
0
  }
393
394
0
  return NET_API_STATUS_SUCCESS;
395
0
}
396
397
/****************************************************************
398
****************************************************************/
399
400
NET_API_STATUS libnetapi_set_use_kerberos(struct libnetapi_ctx *ctx)
401
0
{
402
0
  cli_credentials_set_kerberos_state(ctx->creds,
403
0
             CRED_USE_KERBEROS_REQUIRED,
404
0
             CRED_SPECIFIED);
405
406
0
  return NET_API_STATUS_SUCCESS;
407
0
}
408
409
/****************************************************************
410
****************************************************************/
411
412
NET_API_STATUS libnetapi_get_use_kerberos(struct libnetapi_ctx *ctx,
413
            int *use_kerberos)
414
0
{
415
0
  enum credentials_use_kerberos creds_use_kerberos;
416
417
0
  *use_kerberos = 0;
418
419
0
  creds_use_kerberos = cli_credentials_get_kerberos_state(ctx->creds);
420
0
  if (creds_use_kerberos > CRED_USE_KERBEROS_DESIRED) {
421
0
    *use_kerberos = 1;
422
0
  }
423
424
0
  return NET_API_STATUS_SUCCESS;
425
0
}
426
427
/****************************************************************
428
****************************************************************/
429
430
NET_API_STATUS libnetapi_set_use_ccache(struct libnetapi_ctx *ctx)
431
0
{
432
0
  cli_credentials_add_gensec_features(ctx->creds,
433
0
              GENSEC_FEATURE_NTLM_CCACHE,
434
0
              CRED_SPECIFIED);
435
436
0
  return NET_API_STATUS_SUCCESS;
437
0
}
438
439
/****************************************************************
440
Return a libnetapi error as a string, caller must free with NetApiBufferFree
441
****************************************************************/
442
443
char *libnetapi_errstr(NET_API_STATUS status)
444
0
{
445
0
  TALLOC_CTX *frame = talloc_stackframe();
446
0
  char *ret;
447
0
  if (status & 0xc0000000) {
448
0
    ret = talloc_strdup(NULL,
449
0
             get_friendly_nt_error_msg(NT_STATUS(status)));
450
0
  } else {
451
0
    ret = talloc_strdup(NULL,
452
0
            get_friendly_werror_msg(W_ERROR(status)));
453
0
  }
454
0
  TALLOC_FREE(frame);
455
0
  return ret;
456
0
}
457
458
/****************************************************************
459
****************************************************************/
460
461
NET_API_STATUS libnetapi_set_error_string(struct libnetapi_ctx *ctx,
462
            const char *format, ...)
463
0
{
464
0
  va_list args;
465
466
0
  TALLOC_FREE(ctx->error_string);
467
468
0
  va_start(args, format);
469
0
  ctx->error_string = talloc_vasprintf(ctx, format, args);
470
0
  va_end(args);
471
472
0
  if (!ctx->error_string) {
473
0
    return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
474
0
  }
475
0
  return NET_API_STATUS_SUCCESS;
476
0
}
477
478
/****************************************************************
479
Return a libnetapi_errstr(), caller must free with NetApiBufferFree
480
****************************************************************/
481
482
char *libnetapi_get_error_string(struct libnetapi_ctx *ctx,
483
               NET_API_STATUS status_in)
484
0
{
485
0
  NET_API_STATUS status;
486
0
  struct libnetapi_ctx *tmp_ctx = ctx;
487
488
0
  if (!tmp_ctx) {
489
0
    status = libnetapi_getctx(&tmp_ctx);
490
0
    if (status != 0) {
491
0
      return NULL;
492
0
    }
493
0
  }
494
495
0
  if (tmp_ctx->error_string) {
496
0
    return talloc_strdup(NULL, tmp_ctx->error_string);
497
0
  }
498
499
0
  return libnetapi_errstr(status_in);
500
0
}
501
502
/****************************************************************
503
****************************************************************/
504
505
NET_API_STATUS NetApiBufferAllocate(uint32_t byte_count,
506
            void **buffer)
507
0
{
508
0
  void *buf = NULL;
509
510
0
  if (!buffer) {
511
0
    return W_ERROR_V(WERR_INSUFFICIENT_BUFFER);
512
0
  }
513
514
0
  if (byte_count == 0) {
515
0
    goto done;
516
0
  }
517
518
0
  buf = talloc_size(NULL, byte_count);
519
0
  if (!buf) {
520
0
    return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
521
0
  }
522
523
0
 done:
524
0
  *buffer = buf;
525
526
0
  return NET_API_STATUS_SUCCESS;
527
0
}
528
529
/****************************************************************
530
****************************************************************/
531
532
NET_API_STATUS NetApiBufferFree(void *buffer)
533
0
{
534
0
  if (!buffer) {
535
0
    return W_ERROR_V(WERR_INSUFFICIENT_BUFFER);
536
0
  }
537
538
0
  talloc_free(buffer);
539
540
0
  return NET_API_STATUS_SUCCESS;
541
0
}