s3-netapi: allow to use default krb5 credential cache for libnetapi users.
[Samba/vl.git] / source3 / lib / netapi / netapi.c
blob9ed13fcc71c528136c58fc4a083ee9756e618959
1 /*
2 * Unix SMB/CIFS implementation.
3 * NetApi Support
4 * Copyright (C) Guenther Deschner 2007-2008
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.
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.
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/>.
20 #include "includes.h"
21 #include "lib/netapi/netapi.h"
22 #include "lib/netapi/netapi_private.h"
23 #include "secrets.h"
24 #include "krb5_env.h"
26 struct libnetapi_ctx *stat_ctx = NULL;
27 static bool libnetapi_initialized = false;
29 /****************************************************************
30 ****************************************************************/
32 static NET_API_STATUS libnetapi_init_private_context(struct libnetapi_ctx *ctx)
34 struct libnetapi_private_ctx *priv;
36 if (!ctx) {
37 return W_ERROR_V(WERR_INVALID_PARAM);
40 priv = talloc_zero(ctx, struct libnetapi_private_ctx);
41 if (!priv) {
42 return W_ERROR_V(WERR_NOMEM);
45 ctx->private_data = priv;
47 return NET_API_STATUS_SUCCESS;
50 /****************************************************************
51 Create a libnetapi context, for use in non-Samba applications. This
52 loads the smb.conf file and sets the debug level to 0, so that
53 applications are not flooded with debug logs at level 10, when they
54 were not expecting it.
55 ****************************************************************/
57 NET_API_STATUS libnetapi_init(struct libnetapi_ctx **context)
59 NET_API_STATUS ret;
60 TALLOC_CTX *frame;
61 if (stat_ctx && libnetapi_initialized) {
62 *context = stat_ctx;
63 return NET_API_STATUS_SUCCESS;
66 #if 0
67 talloc_enable_leak_report();
68 #endif
69 frame = talloc_stackframe();
71 /* Case tables must be loaded before any string comparisons occour */
72 load_case_tables_library();
74 /* When libnetapi is invoked from an application, it does not
75 * want to be swamped with level 10 debug messages, even if
76 * this has been set for the server in smb.conf */
77 lp_set_cmdline("log level", "0");
78 setup_logging("libnetapi", DEBUG_STDERR);
80 if (!lp_load_global(get_dyn_CONFIGFILE())) {
81 TALLOC_FREE(frame);
82 fprintf(stderr, "error loading %s\n", get_dyn_CONFIGFILE() );
83 return W_ERROR_V(WERR_GENERAL_FAILURE);
86 init_names();
87 load_interfaces();
88 reopen_logs();
90 BlockSignals(True, SIGPIPE);
92 ret = libnetapi_net_init(context);
93 TALLOC_FREE(frame);
94 return ret;
97 /****************************************************************
98 Create a libnetapi context, for use inside the 'net' binary.
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 ****************************************************************/
105 NET_API_STATUS libnetapi_net_init(struct libnetapi_ctx **context)
107 NET_API_STATUS status;
108 struct libnetapi_ctx *ctx = NULL;
109 TALLOC_CTX *frame = talloc_stackframe();
111 ctx = talloc_zero(frame, struct libnetapi_ctx);
112 if (!ctx) {
113 TALLOC_FREE(frame);
114 return W_ERROR_V(WERR_NOMEM);
117 BlockSignals(True, SIGPIPE);
119 if (getenv("USER")) {
120 ctx->username = talloc_strdup(ctx, getenv("USER"));
121 } else {
122 ctx->username = talloc_strdup(ctx, "");
124 if (!ctx->username) {
125 TALLOC_FREE(frame);
126 fprintf(stderr, "libnetapi_init: out of memory\n");
127 return W_ERROR_V(WERR_NOMEM);
130 status = libnetapi_init_private_context(ctx);
131 if (status != 0) {
132 TALLOC_FREE(frame);
133 return status;
136 libnetapi_initialized = true;
138 talloc_steal(NULL, ctx);
139 *context = stat_ctx = ctx;
141 TALLOC_FREE(frame);
142 return NET_API_STATUS_SUCCESS;
145 /****************************************************************
146 Return the static libnetapi context
147 ****************************************************************/
149 NET_API_STATUS libnetapi_getctx(struct libnetapi_ctx **ctx)
151 if (stat_ctx) {
152 *ctx = stat_ctx;
153 return NET_API_STATUS_SUCCESS;
156 return libnetapi_init(ctx);
159 /****************************************************************
160 Free the static libnetapi context
161 ****************************************************************/
163 NET_API_STATUS libnetapi_free(struct libnetapi_ctx *ctx)
165 if (!ctx) {
166 return NET_API_STATUS_SUCCESS;
169 libnetapi_samr_free(ctx);
171 libnetapi_shutdown_cm(ctx);
173 if (ctx->krb5_cc_env) {
174 char *env = getenv(KRB5_ENV_CCNAME);
175 if (env && (strequal(ctx->krb5_cc_env, env))) {
176 unsetenv(KRB5_ENV_CCNAME);
180 gfree_names();
181 gfree_loadparm();
182 gfree_charcnv();
183 gfree_interfaces();
185 secrets_shutdown();
187 if (ctx == stat_ctx) {
188 stat_ctx = NULL;
190 TALLOC_FREE(ctx);
192 gfree_debugsyms();
194 return NET_API_STATUS_SUCCESS;
197 /****************************************************************
198 Override the current log level for libnetapi
199 ****************************************************************/
201 NET_API_STATUS libnetapi_set_debuglevel(struct libnetapi_ctx *ctx,
202 const char *debuglevel)
204 TALLOC_CTX *frame = talloc_stackframe();
205 ctx->debuglevel = talloc_strdup(ctx, debuglevel);
207 if (!lp_set_cmdline("log level", debuglevel)) {
208 TALLOC_FREE(frame);
209 return W_ERROR_V(WERR_GENERAL_FAILURE);
211 TALLOC_FREE(frame);
212 return NET_API_STATUS_SUCCESS;
215 /****************************************************************
216 ****************************************************************/
218 NET_API_STATUS libnetapi_get_debuglevel(struct libnetapi_ctx *ctx,
219 char **debuglevel)
221 *debuglevel = ctx->debuglevel;
222 return NET_API_STATUS_SUCCESS;
225 /****************************************************************
226 ****************************************************************/
228 NET_API_STATUS libnetapi_set_username(struct libnetapi_ctx *ctx,
229 const char *username)
231 TALLOC_FREE(ctx->username);
232 ctx->username = talloc_strdup(ctx, username ? username : "");
234 if (!ctx->username) {
235 return W_ERROR_V(WERR_NOMEM);
237 return NET_API_STATUS_SUCCESS;
240 NET_API_STATUS libnetapi_set_password(struct libnetapi_ctx *ctx,
241 const char *password)
243 TALLOC_FREE(ctx->password);
244 ctx->password = talloc_strdup(ctx, password);
245 if (!ctx->password) {
246 return W_ERROR_V(WERR_NOMEM);
248 return NET_API_STATUS_SUCCESS;
251 NET_API_STATUS libnetapi_set_workgroup(struct libnetapi_ctx *ctx,
252 const char *workgroup)
254 TALLOC_FREE(ctx->workgroup);
255 ctx->workgroup = talloc_strdup(ctx, workgroup);
256 if (!ctx->workgroup) {
257 return W_ERROR_V(WERR_NOMEM);
259 return NET_API_STATUS_SUCCESS;
262 /****************************************************************
263 ****************************************************************/
265 NET_API_STATUS libnetapi_set_use_kerberos(struct libnetapi_ctx *ctx)
267 ctx->use_kerberos = true;
268 return NET_API_STATUS_SUCCESS;
271 /****************************************************************
272 ****************************************************************/
274 NET_API_STATUS libnetapi_set_use_ccache(struct libnetapi_ctx *ctx)
276 ctx->use_ccache = true;
277 return NET_API_STATUS_SUCCESS;
280 /****************************************************************
281 ****************************************************************/
283 NET_API_STATUS libnetapi_set_use_memory_krb5_ccache(struct libnetapi_ctx *ctx)
285 ctx->krb5_cc_env = talloc_strdup(ctx, "MEMORY:libnetapi");
286 if (!ctx->krb5_cc_env) {
287 return W_ERROR_V(WERR_NOMEM);
289 setenv(KRB5_ENV_CCNAME, ctx->krb5_cc_env, 1);
290 ctx->use_memory_krb5_ccache = 1;
291 return NET_API_STATUS_SUCCESS;
294 /****************************************************************
295 Return a libnetapi error as a string, caller must free with NetApiBufferFree
296 ****************************************************************/
298 char *libnetapi_errstr(NET_API_STATUS status)
300 TALLOC_CTX *frame = talloc_stackframe();
301 char *ret;
302 if (status & 0xc0000000) {
303 ret = talloc_strdup(NULL,
304 get_friendly_nt_error_msg(NT_STATUS(status)));
305 } else {
306 ret = talloc_strdup(NULL,
307 get_friendly_werror_msg(W_ERROR(status)));
309 TALLOC_FREE(frame);
310 return ret;
313 /****************************************************************
314 ****************************************************************/
316 NET_API_STATUS libnetapi_set_error_string(struct libnetapi_ctx *ctx,
317 const char *format, ...)
319 va_list args;
321 TALLOC_FREE(ctx->error_string);
323 va_start(args, format);
324 ctx->error_string = talloc_vasprintf(ctx, format, args);
325 va_end(args);
327 if (!ctx->error_string) {
328 return W_ERROR_V(WERR_NOMEM);
330 return NET_API_STATUS_SUCCESS;
333 /****************************************************************
334 Return a libnetapi_errstr(), caller must free with NetApiBufferFree
335 ****************************************************************/
337 char *libnetapi_get_error_string(struct libnetapi_ctx *ctx,
338 NET_API_STATUS status_in)
340 NET_API_STATUS status;
341 struct libnetapi_ctx *tmp_ctx = ctx;
343 if (!tmp_ctx) {
344 status = libnetapi_getctx(&tmp_ctx);
345 if (status != 0) {
346 return NULL;
350 if (tmp_ctx->error_string) {
351 return talloc_strdup(NULL, tmp_ctx->error_string);
354 return libnetapi_errstr(status_in);
357 /****************************************************************
358 ****************************************************************/
360 NET_API_STATUS NetApiBufferAllocate(uint32_t byte_count,
361 void **buffer)
363 void *buf = NULL;
365 if (!buffer) {
366 return W_ERROR_V(WERR_INSUFFICIENT_BUFFER);
369 if (byte_count == 0) {
370 goto done;
373 buf = talloc_size(NULL, byte_count);
374 if (!buf) {
375 return W_ERROR_V(WERR_NOMEM);
378 done:
379 *buffer = buf;
381 return NET_API_STATUS_SUCCESS;
384 /****************************************************************
385 ****************************************************************/
387 NET_API_STATUS NetApiBufferFree(void *buffer)
389 if (!buffer) {
390 return W_ERROR_V(WERR_INSUFFICIENT_BUFFER);
393 talloc_free(buffer);
395 return NET_API_STATUS_SUCCESS;