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