Line data Source code
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 1025 : static NET_API_STATUS libnetapi_init_private_context(struct libnetapi_ctx *ctx)
36 : {
37 0 : struct libnetapi_private_ctx *priv;
38 :
39 1025 : if (!ctx) {
40 0 : return W_ERROR_V(WERR_INVALID_PARAMETER);
41 : }
42 :
43 1025 : priv = talloc_zero(ctx, struct libnetapi_private_ctx);
44 1025 : if (!priv) {
45 0 : return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
46 : }
47 :
48 1025 : ctx->private_data = priv;
49 :
50 1025 : return NET_API_STATUS_SUCCESS;
51 : }
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 1 : NET_API_STATUS libnetapi_init(struct libnetapi_ctx **context)
61 : {
62 0 : NET_API_STATUS ret;
63 0 : TALLOC_CTX *frame;
64 1 : struct loadparm_context *lp_ctx = NULL;
65 :
66 1 : if (stat_ctx && libnetapi_initialized) {
67 1 : *context = stat_ctx;
68 1 : return NET_API_STATUS_SUCCESS;
69 : }
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 : }
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 : }
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 : }
103 0 : TALLOC_FREE(frame);
104 0 : return ret;
105 : }
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 1253 : NET_API_STATUS libnetapi_net_init(struct libnetapi_ctx **context,
116 : struct loadparm_context *lp_ctx,
117 : struct cli_credentials *creds)
118 : {
119 0 : NET_API_STATUS status;
120 1253 : struct libnetapi_ctx *ctx = NULL;
121 1253 : TALLOC_CTX *frame = NULL;
122 :
123 1253 : if (stat_ctx != NULL && libnetapi_initialized) {
124 228 : *context = stat_ctx;
125 228 : return NET_API_STATUS_SUCCESS;
126 : }
127 :
128 1025 : frame = talloc_stackframe();
129 1025 : ctx = talloc_zero(frame, struct libnetapi_ctx);
130 1025 : if (!ctx) {
131 0 : TALLOC_FREE(frame);
132 0 : return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
133 : }
134 :
135 1025 : ctx->lp_ctx = lp_ctx;
136 :
137 1025 : ctx->creds = creds;
138 1025 : 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 : }
144 : /* Ignore return code, as we might not have a smb.conf */
145 0 : (void)cli_credentials_guess(ctx->creds, lp_ctx);
146 : }
147 :
148 1025 : BlockSignals(True, SIGPIPE);
149 :
150 1025 : status = libnetapi_init_private_context(ctx);
151 1025 : if (status != 0) {
152 0 : TALLOC_FREE(frame);
153 0 : return status;
154 : }
155 :
156 1025 : libnetapi_initialized = true;
157 :
158 1025 : talloc_steal(NULL, ctx);
159 1025 : *context = stat_ctx = ctx;
160 :
161 1025 : TALLOC_FREE(frame);
162 1025 : return NET_API_STATUS_SUCCESS;
163 : }
164 :
165 : /****************************************************************
166 : Return the static libnetapi context
167 : ****************************************************************/
168 :
169 210 : NET_API_STATUS libnetapi_getctx(struct libnetapi_ctx **ctx)
170 : {
171 210 : if (stat_ctx) {
172 210 : *ctx = stat_ctx;
173 210 : return NET_API_STATUS_SUCCESS;
174 : }
175 :
176 0 : return libnetapi_init(ctx);
177 : }
178 :
179 : /****************************************************************
180 : Free the static libnetapi context
181 : ****************************************************************/
182 :
183 3445 : NET_API_STATUS libnetapi_free(struct libnetapi_ctx *ctx)
184 : {
185 5 : TALLOC_CTX *frame;
186 :
187 3445 : if (!ctx) {
188 2415 : return NET_API_STATUS_SUCCESS;
189 : }
190 :
191 1025 : frame = talloc_stackframe();
192 1025 : libnetapi_samr_free(ctx);
193 :
194 1025 : libnetapi_shutdown_cm(ctx);
195 :
196 1025 : gfree_loadparm();
197 1025 : gfree_charcnv();
198 1025 : gfree_interfaces();
199 :
200 1025 : secrets_shutdown();
201 :
202 1025 : netlogon_creds_cli_close_global_db();
203 :
204 1025 : if (ctx == stat_ctx) {
205 1025 : stat_ctx = NULL;
206 : }
207 1025 : TALLOC_FREE(ctx);
208 :
209 1025 : gfree_debugsyms();
210 1025 : talloc_free(frame);
211 :
212 1025 : return NET_API_STATUS_SUCCESS;
213 : }
214 :
215 : /****************************************************************
216 : Override the current log level for libnetapi
217 : ****************************************************************/
218 :
219 0 : NET_API_STATUS libnetapi_set_debuglevel(struct libnetapi_ctx *ctx,
220 : const char *debuglevel)
221 : {
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 : }
229 0 : TALLOC_FREE(frame);
230 0 : return NET_API_STATUS_SUCCESS;
231 : }
232 :
233 : /****************************************************************
234 : ****************************************************************/
235 :
236 0 : NET_API_STATUS libnetapi_set_logfile(struct libnetapi_ctx *ctx,
237 : const char *logfile)
238 : {
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 : }
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 : }
251 :
252 : /****************************************************************
253 : ****************************************************************/
254 :
255 0 : NET_API_STATUS libnetapi_get_debuglevel(struct libnetapi_ctx *ctx,
256 : char **debuglevel)
257 : {
258 0 : *debuglevel = ctx->debuglevel;
259 0 : return NET_API_STATUS_SUCCESS;
260 : }
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 87 : NET_API_STATUS libnetapi_get_username(struct libnetapi_ctx *ctx,
275 : const char **username)
276 : {
277 87 : if (ctx == NULL) {
278 0 : return W_ERROR_V(WERR_INVALID_PARAMETER);
279 : }
280 :
281 87 : if (username != NULL) {
282 87 : *username = cli_credentials_get_username(ctx->creds);
283 : }
284 :
285 87 : return NET_API_STATUS_SUCCESS;
286 : }
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 87 : NET_API_STATUS libnetapi_get_password(struct libnetapi_ctx *ctx,
298 : const char **password)
299 : {
300 87 : if (ctx == NULL) {
301 0 : return W_ERROR_V(WERR_INVALID_PARAMETER);
302 : }
303 :
304 87 : if (password != NULL) {
305 87 : *password = cli_credentials_get_password(ctx->creds);
306 : }
307 :
308 87 : return NET_API_STATUS_SUCCESS;
309 : }
310 :
311 0 : NET_API_STATUS libnetapi_set_username(struct libnetapi_ctx *ctx,
312 : const char *username)
313 : {
314 0 : if (ctx == NULL || username == NULL) {
315 0 : return W_ERROR_V(WERR_INVALID_PARAMETER);
316 : }
317 :
318 0 : cli_credentials_parse_string(ctx->creds, username, CRED_SPECIFIED);
319 :
320 0 : return NET_API_STATUS_SUCCESS;
321 : }
322 :
323 0 : NET_API_STATUS libnetapi_set_password(struct libnetapi_ctx *ctx,
324 : const char *password)
325 : {
326 0 : bool ok;
327 :
328 0 : if (ctx == NULL || password == NULL) {
329 0 : return W_ERROR_V(WERR_INVALID_PARAMETER);
330 : }
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 : }
336 :
337 0 : return NET_API_STATUS_SUCCESS;
338 : }
339 :
340 0 : NET_API_STATUS libnetapi_set_workgroup(struct libnetapi_ctx *ctx,
341 : const char *workgroup)
342 : {
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 : }
349 :
350 0 : return NET_API_STATUS_SUCCESS;
351 : }
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 0 : NET_API_STATUS libnetapi_set_creds(struct libnetapi_ctx *ctx,
363 : struct cli_credentials *creds)
364 : {
365 0 : if (ctx == NULL || creds == NULL) {
366 0 : return W_ERROR_V(WERR_INVALID_PARAMETER);
367 : }
368 :
369 0 : ctx->creds = creds;
370 :
371 0 : return NET_API_STATUS_SUCCESS;
372 : }
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 12 : NET_API_STATUS libnetapi_get_creds(struct libnetapi_ctx *ctx,
384 : struct cli_credentials **creds)
385 : {
386 12 : if (ctx == NULL) {
387 0 : return W_ERROR_V(WERR_INVALID_PARAMETER);
388 : }
389 :
390 12 : if (creds != NULL) {
391 12 : *creds = ctx->creds;
392 : }
393 :
394 12 : return NET_API_STATUS_SUCCESS;
395 : }
396 :
397 : /****************************************************************
398 : ****************************************************************/
399 :
400 0 : NET_API_STATUS libnetapi_set_use_kerberos(struct libnetapi_ctx *ctx)
401 : {
402 0 : cli_credentials_set_kerberos_state(ctx->creds,
403 : CRED_USE_KERBEROS_REQUIRED,
404 : CRED_SPECIFIED);
405 :
406 0 : return NET_API_STATUS_SUCCESS;
407 : }
408 :
409 : /****************************************************************
410 : ****************************************************************/
411 :
412 0 : NET_API_STATUS libnetapi_get_use_kerberos(struct libnetapi_ctx *ctx,
413 : int *use_kerberos)
414 : {
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 : }
423 :
424 0 : return NET_API_STATUS_SUCCESS;
425 : }
426 :
427 : /****************************************************************
428 : ****************************************************************/
429 :
430 0 : NET_API_STATUS libnetapi_set_use_ccache(struct libnetapi_ctx *ctx)
431 : {
432 0 : uint32_t gensec_features;
433 :
434 0 : gensec_features = cli_credentials_get_gensec_features(ctx->creds);
435 0 : gensec_features |= GENSEC_FEATURE_NTLM_CCACHE;
436 0 : cli_credentials_set_gensec_features(ctx->creds,
437 : gensec_features,
438 : CRED_SPECIFIED);
439 :
440 0 : return NET_API_STATUS_SUCCESS;
441 : }
442 :
443 : /****************************************************************
444 : Return a libnetapi error as a string, caller must free with NetApiBufferFree
445 : ****************************************************************/
446 :
447 0 : char *libnetapi_errstr(NET_API_STATUS status)
448 : {
449 0 : TALLOC_CTX *frame = talloc_stackframe();
450 0 : char *ret;
451 0 : if (status & 0xc0000000) {
452 0 : ret = talloc_strdup(NULL,
453 0 : get_friendly_nt_error_msg(NT_STATUS(status)));
454 : } else {
455 0 : ret = talloc_strdup(NULL,
456 0 : get_friendly_werror_msg(W_ERROR(status)));
457 : }
458 0 : TALLOC_FREE(frame);
459 0 : return ret;
460 : }
461 :
462 : /****************************************************************
463 : ****************************************************************/
464 :
465 2 : NET_API_STATUS libnetapi_set_error_string(struct libnetapi_ctx *ctx,
466 : const char *format, ...)
467 : {
468 0 : va_list args;
469 :
470 2 : TALLOC_FREE(ctx->error_string);
471 :
472 2 : va_start(args, format);
473 2 : ctx->error_string = talloc_vasprintf(ctx, format, args);
474 2 : va_end(args);
475 :
476 2 : if (!ctx->error_string) {
477 0 : return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
478 : }
479 2 : return NET_API_STATUS_SUCCESS;
480 : }
481 :
482 : /****************************************************************
483 : Return a libnetapi_errstr(), caller must free with NetApiBufferFree
484 : ****************************************************************/
485 :
486 2 : char *libnetapi_get_error_string(struct libnetapi_ctx *ctx,
487 : NET_API_STATUS status_in)
488 : {
489 0 : NET_API_STATUS status;
490 2 : struct libnetapi_ctx *tmp_ctx = ctx;
491 :
492 2 : if (!tmp_ctx) {
493 0 : status = libnetapi_getctx(&tmp_ctx);
494 0 : if (status != 0) {
495 0 : return NULL;
496 : }
497 : }
498 :
499 2 : if (tmp_ctx->error_string) {
500 2 : return talloc_strdup(NULL, tmp_ctx->error_string);
501 : }
502 :
503 0 : return libnetapi_errstr(status_in);
504 : }
505 :
506 : /****************************************************************
507 : ****************************************************************/
508 :
509 1 : NET_API_STATUS NetApiBufferAllocate(uint32_t byte_count,
510 : void **buffer)
511 : {
512 1 : void *buf = NULL;
513 :
514 1 : if (!buffer) {
515 0 : return W_ERROR_V(WERR_INSUFFICIENT_BUFFER);
516 : }
517 :
518 1 : if (byte_count == 0) {
519 0 : goto done;
520 : }
521 :
522 1 : buf = talloc_size(NULL, byte_count);
523 1 : if (!buf) {
524 0 : return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
525 : }
526 :
527 1 : done:
528 1 : *buffer = buf;
529 :
530 1 : return NET_API_STATUS_SUCCESS;
531 : }
532 :
533 : /****************************************************************
534 : ****************************************************************/
535 :
536 33 : NET_API_STATUS NetApiBufferFree(void *buffer)
537 : {
538 33 : if (!buffer) {
539 3 : return W_ERROR_V(WERR_INSUFFICIENT_BUFFER);
540 : }
541 :
542 30 : talloc_free(buffer);
543 :
544 30 : return NET_API_STATUS_SUCCESS;
545 : }
|