s3-netapi Add libnetapi_net_init(), don't double-init common Samba subsystems
[Samba.git] / source3 / lib / netapi / netapi.c
blob7eb076484944d5298b5c61d27a8b91844dd88c84
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 TALLOC_CTX *frame = NULL;
28 static bool libnetapi_initialized = false;
30 /****************************************************************
31 ****************************************************************/
33 static NET_API_STATUS libnetapi_init_private_context(struct libnetapi_ctx *ctx)
35 struct libnetapi_private_ctx *priv;
37 if (!ctx) {
38 return W_ERROR_V(WERR_INVALID_PARAM);
41 priv = TALLOC_ZERO_P(ctx, struct libnetapi_private_ctx);
42 if (!priv) {
43 return W_ERROR_V(WERR_NOMEM);
46 ctx->private_data = priv;
48 return NET_API_STATUS_SUCCESS;
51 /****************************************************************
52 Create a libnetapi context, for use in non-Samba applications. This
53 loads the smb.conf file and sets the debug level to 0, so that
54 applications are not flooded with debug logs at level 10, when they
55 were not expecting it.
56 ****************************************************************/
58 NET_API_STATUS libnetapi_init(struct libnetapi_ctx **context)
60 if (stat_ctx && libnetapi_initialized) {
61 *context = stat_ctx;
62 return NET_API_STATUS_SUCCESS;
65 #if 0
66 talloc_enable_leak_report();
67 #endif
68 frame = talloc_stackframe();
70 /* When libnetapi is invoked from an application, it does not
71 * want to be swamped with level 10 debug messages, even if
72 * this has been set for the server in smb.conf */
73 lp_set_cmdline("log level", "0");
74 setup_logging("libnetapi", DEBUG_STDERR);
76 load_case_tables();
78 if (!lp_load(get_dyn_CONFIGFILE(), true, false, false, false)) {
79 TALLOC_FREE(frame);
80 fprintf(stderr, "error loading %s\n", get_dyn_CONFIGFILE() );
81 return W_ERROR_V(WERR_GENERAL_FAILURE);
84 init_names();
85 load_interfaces();
86 reopen_logs();
88 BlockSignals(True, SIGPIPE);
90 return libnetapi_net_init(context);
93 /****************************************************************
94 Create a libnetapi context, for use inside the 'net' binary.
96 As we know net has already loaded the smb.conf file, and set the debug
97 level etc, this avoids doing so again (which causes trouble with -d on
98 the command line).
99 ****************************************************************/
101 NET_API_STATUS libnetapi_net_init(struct libnetapi_ctx **context)
103 NET_API_STATUS status;
104 struct libnetapi_ctx *ctx = NULL;
105 char *krb5_cc_env = NULL;
107 frame = talloc_stackframe();
109 ctx = talloc_zero(frame, struct libnetapi_ctx);
110 if (!ctx) {
111 TALLOC_FREE(frame);
112 return W_ERROR_V(WERR_NOMEM);
115 BlockSignals(True, SIGPIPE);
117 krb5_cc_env = getenv(KRB5_ENV_CCNAME);
118 if (!krb5_cc_env || (strlen(krb5_cc_env) == 0)) {
119 ctx->krb5_cc_env = talloc_strdup(frame, "MEMORY:libnetapi");
120 setenv(KRB5_ENV_CCNAME, ctx->krb5_cc_env, 1);
123 if (getenv("USER")) {
124 ctx->username = talloc_strdup(frame, getenv("USER"));
125 } else {
126 ctx->username = talloc_strdup(frame, "");
128 if (!ctx->username) {
129 TALLOC_FREE(frame);
130 fprintf(stderr, "libnetapi_init: out of memory\n");
131 return W_ERROR_V(WERR_NOMEM);
134 status = libnetapi_init_private_context(ctx);
135 if (status != 0) {
136 TALLOC_FREE(frame);
137 return status;
140 libnetapi_initialized = true;
142 *context = stat_ctx = ctx;
144 return NET_API_STATUS_SUCCESS;
147 /****************************************************************
148 ****************************************************************/
150 NET_API_STATUS libnetapi_getctx(struct libnetapi_ctx **ctx)
152 if (stat_ctx) {
153 *ctx = stat_ctx;
154 return NET_API_STATUS_SUCCESS;
157 return libnetapi_init(ctx);
160 /****************************************************************
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_case_tables();
183 gfree_charcnv();
184 gfree_interfaces();
186 secrets_shutdown();
188 TALLOC_FREE(ctx);
189 TALLOC_FREE(frame);
191 gfree_debugsyms();
193 return NET_API_STATUS_SUCCESS;
196 /****************************************************************
197 ****************************************************************/
199 NET_API_STATUS libnetapi_set_debuglevel(struct libnetapi_ctx *ctx,
200 const char *debuglevel)
202 ctx->debuglevel = talloc_strdup(ctx, debuglevel);
203 if (!lp_set_cmdline("log level", debuglevel)) {
204 return W_ERROR_V(WERR_GENERAL_FAILURE);
206 return NET_API_STATUS_SUCCESS;
209 /****************************************************************
210 ****************************************************************/
212 NET_API_STATUS libnetapi_get_debuglevel(struct libnetapi_ctx *ctx,
213 char **debuglevel)
215 *debuglevel = ctx->debuglevel;
216 return NET_API_STATUS_SUCCESS;
219 /****************************************************************
220 ****************************************************************/
222 NET_API_STATUS libnetapi_set_username(struct libnetapi_ctx *ctx,
223 const char *username)
225 TALLOC_FREE(ctx->username);
226 ctx->username = talloc_strdup(ctx, username ? username : "");
228 if (!ctx->username) {
229 return W_ERROR_V(WERR_NOMEM);
231 return NET_API_STATUS_SUCCESS;
234 NET_API_STATUS libnetapi_set_password(struct libnetapi_ctx *ctx,
235 const char *password)
237 TALLOC_FREE(ctx->password);
238 ctx->password = talloc_strdup(ctx, password);
239 if (!ctx->password) {
240 return W_ERROR_V(WERR_NOMEM);
242 return NET_API_STATUS_SUCCESS;
245 NET_API_STATUS libnetapi_set_workgroup(struct libnetapi_ctx *ctx,
246 const char *workgroup)
248 TALLOC_FREE(ctx->workgroup);
249 ctx->workgroup = talloc_strdup(ctx, workgroup);
250 if (!ctx->workgroup) {
251 return W_ERROR_V(WERR_NOMEM);
253 return NET_API_STATUS_SUCCESS;
256 /****************************************************************
257 ****************************************************************/
259 NET_API_STATUS libnetapi_set_use_kerberos(struct libnetapi_ctx *ctx)
261 ctx->use_kerberos = true;
262 return NET_API_STATUS_SUCCESS;
265 NET_API_STATUS libnetapi_set_use_ccache(struct libnetapi_ctx *ctx)
267 ctx->use_ccache = true;
268 return NET_API_STATUS_SUCCESS;
271 /****************************************************************
272 ****************************************************************/
274 const char *libnetapi_errstr(NET_API_STATUS status)
276 if (status & 0xc0000000) {
277 return get_friendly_nt_error_msg(NT_STATUS(status));
280 return get_friendly_werror_msg(W_ERROR(status));
283 /****************************************************************
284 ****************************************************************/
286 NET_API_STATUS libnetapi_set_error_string(struct libnetapi_ctx *ctx,
287 const char *format, ...)
289 va_list args;
291 TALLOC_FREE(ctx->error_string);
293 va_start(args, format);
294 ctx->error_string = talloc_vasprintf(ctx, format, args);
295 va_end(args);
297 if (!ctx->error_string) {
298 return W_ERROR_V(WERR_NOMEM);
300 return NET_API_STATUS_SUCCESS;
303 /****************************************************************
304 ****************************************************************/
306 const char *libnetapi_get_error_string(struct libnetapi_ctx *ctx,
307 NET_API_STATUS status_in)
309 NET_API_STATUS status;
310 struct libnetapi_ctx *tmp_ctx = ctx;
312 if (!tmp_ctx) {
313 status = libnetapi_getctx(&tmp_ctx);
314 if (status != 0) {
315 return NULL;
319 if (tmp_ctx->error_string) {
320 return tmp_ctx->error_string;
323 return libnetapi_errstr(status_in);
326 /****************************************************************
327 ****************************************************************/
329 NET_API_STATUS NetApiBufferAllocate(uint32_t byte_count,
330 void **buffer)
332 void *buf = NULL;
334 if (!buffer) {
335 return W_ERROR_V(WERR_INSUFFICIENT_BUFFER);
338 if (byte_count == 0) {
339 goto done;
342 buf = talloc_size(NULL, byte_count);
343 if (!buf) {
344 return W_ERROR_V(WERR_NOMEM);
347 done:
348 *buffer = buf;
350 return NET_API_STATUS_SUCCESS;
353 /****************************************************************
354 ****************************************************************/
356 NET_API_STATUS NetApiBufferFree(void *buffer)
358 if (!buffer) {
359 return W_ERROR_V(WERR_INSUFFICIENT_BUFFER);
362 talloc_free(buffer);
364 return NET_API_STATUS_SUCCESS;