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