s3-debug Remove 'AllowDebugChange' and use lp_set_cmdline() instead
[abartlet/samba.git/.git] / source3 / lib / netapi / netapi.c
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 "lib/netapi/netapi.h"
22 #include "lib/netapi/netapi_private.h"
23 #include "secrets.h"
24 #include "krb5_env.h"
25
26 struct libnetapi_ctx *stat_ctx = NULL;
27 TALLOC_CTX *frame = NULL;
28 static bool libnetapi_initialized = false;
29
30 /****************************************************************
31 ****************************************************************/
32
33 static NET_API_STATUS libnetapi_init_private_context(struct libnetapi_ctx *ctx)
34 {
35         struct libnetapi_private_ctx *priv;
36
37         if (!ctx) {
38                 return W_ERROR_V(WERR_INVALID_PARAM);
39         }
40
41         priv = TALLOC_ZERO_P(ctx, struct libnetapi_private_ctx);
42         if (!priv) {
43                 return W_ERROR_V(WERR_NOMEM);
44         }
45
46         ctx->private_data = priv;
47
48         return NET_API_STATUS_SUCCESS;
49 }
50
51 /****************************************************************
52 ****************************************************************/
53
54 NET_API_STATUS libnetapi_init(struct libnetapi_ctx **context)
55 {
56         NET_API_STATUS status;
57         struct libnetapi_ctx *ctx = NULL;
58         char *krb5_cc_env = NULL;
59
60         if (stat_ctx && libnetapi_initialized) {
61                 *context = stat_ctx;
62                 return NET_API_STATUS_SUCCESS;
63         }
64
65 #if 0
66         talloc_enable_leak_report();
67 #endif
68         frame = talloc_stackframe();
69
70         ctx = talloc_zero(frame, struct libnetapi_ctx);
71         if (!ctx) {
72                 TALLOC_FREE(frame);
73                 return W_ERROR_V(WERR_NOMEM);
74         }
75
76         lp_set_cmdline("log level", "0");
77
78         /* prevent setup_logging() from closing x_stderr... */
79         setup_logging("libnetapi", DEBUG_STDERR);
80
81         load_case_tables();
82
83         if (!lp_load(get_dyn_CONFIGFILE(), true, false, false, false)) {
84                 TALLOC_FREE(frame);
85                 fprintf(stderr, "error loading %s\n", get_dyn_CONFIGFILE() );
86                 return W_ERROR_V(WERR_GENERAL_FAILURE);
87         }
88
89         init_names();
90         load_interfaces();
91         reopen_logs();
92
93         BlockSignals(True, SIGPIPE);
94
95         krb5_cc_env = getenv(KRB5_ENV_CCNAME);
96         if (!krb5_cc_env || (strlen(krb5_cc_env) == 0)) {
97                 ctx->krb5_cc_env = talloc_strdup(frame, "MEMORY:libnetapi");
98                 setenv(KRB5_ENV_CCNAME, ctx->krb5_cc_env, 1);
99         }
100
101         if (getenv("USER")) {
102                 ctx->username = talloc_strdup(frame, getenv("USER"));
103         } else {
104                 ctx->username = talloc_strdup(frame, "");
105         }
106         if (!ctx->username) {
107                 TALLOC_FREE(frame);
108                 fprintf(stderr, "libnetapi_init: out of memory\n");
109                 return W_ERROR_V(WERR_NOMEM);
110         }
111
112         status = libnetapi_init_private_context(ctx);
113         if (status != 0) {
114                 TALLOC_FREE(frame);
115                 return status;
116         }
117
118         libnetapi_initialized = true;
119
120         *context = stat_ctx = ctx;
121
122         return NET_API_STATUS_SUCCESS;
123 }
124
125 /****************************************************************
126 ****************************************************************/
127
128 NET_API_STATUS libnetapi_getctx(struct libnetapi_ctx **ctx)
129 {
130         if (stat_ctx) {
131                 *ctx = stat_ctx;
132                 return NET_API_STATUS_SUCCESS;
133         }
134
135         return libnetapi_init(ctx);
136 }
137
138 /****************************************************************
139 ****************************************************************/
140
141 NET_API_STATUS libnetapi_free(struct libnetapi_ctx *ctx)
142 {
143         if (!ctx) {
144                 return NET_API_STATUS_SUCCESS;
145         }
146
147         libnetapi_samr_free(ctx);
148
149         libnetapi_shutdown_cm(ctx);
150
151         if (ctx->krb5_cc_env) {
152                 char *env = getenv(KRB5_ENV_CCNAME);
153                 if (env && (strequal(ctx->krb5_cc_env, env))) {
154                         unsetenv(KRB5_ENV_CCNAME);
155                 }
156         }
157
158         gfree_names();
159         gfree_loadparm();
160         gfree_case_tables();
161         gfree_charcnv();
162         gfree_interfaces();
163
164         secrets_shutdown();
165
166         TALLOC_FREE(ctx);
167         TALLOC_FREE(frame);
168
169         gfree_debugsyms();
170
171         return NET_API_STATUS_SUCCESS;
172 }
173
174 /****************************************************************
175 ****************************************************************/
176
177 NET_API_STATUS libnetapi_set_debuglevel(struct libnetapi_ctx *ctx,
178                                         const char *debuglevel)
179 {
180         ctx->debuglevel = talloc_strdup(ctx, debuglevel);
181         if (!lp_set_cmdline("log level", debuglevel)) {
182                 return W_ERROR_V(WERR_GENERAL_FAILURE);
183         }
184         return NET_API_STATUS_SUCCESS;
185 }
186
187 /****************************************************************
188 ****************************************************************/
189
190 NET_API_STATUS libnetapi_get_debuglevel(struct libnetapi_ctx *ctx,
191                                         char **debuglevel)
192 {
193         *debuglevel = ctx->debuglevel;
194         return NET_API_STATUS_SUCCESS;
195 }
196
197 /****************************************************************
198 ****************************************************************/
199
200 NET_API_STATUS libnetapi_set_username(struct libnetapi_ctx *ctx,
201                                       const char *username)
202 {
203         TALLOC_FREE(ctx->username);
204         ctx->username = talloc_strdup(ctx, username ? username : "");
205
206         if (!ctx->username) {
207                 return W_ERROR_V(WERR_NOMEM);
208         }
209         return NET_API_STATUS_SUCCESS;
210 }
211
212 NET_API_STATUS libnetapi_set_password(struct libnetapi_ctx *ctx,
213                                       const char *password)
214 {
215         TALLOC_FREE(ctx->password);
216         ctx->password = talloc_strdup(ctx, password);
217         if (!ctx->password) {
218                 return W_ERROR_V(WERR_NOMEM);
219         }
220         return NET_API_STATUS_SUCCESS;
221 }
222
223 NET_API_STATUS libnetapi_set_workgroup(struct libnetapi_ctx *ctx,
224                                        const char *workgroup)
225 {
226         TALLOC_FREE(ctx->workgroup);
227         ctx->workgroup = talloc_strdup(ctx, workgroup);
228         if (!ctx->workgroup) {
229                 return W_ERROR_V(WERR_NOMEM);
230         }
231         return NET_API_STATUS_SUCCESS;
232 }
233
234 /****************************************************************
235 ****************************************************************/
236
237 NET_API_STATUS libnetapi_set_use_kerberos(struct libnetapi_ctx *ctx)
238 {
239         ctx->use_kerberos = true;
240         return NET_API_STATUS_SUCCESS;
241 }
242
243 NET_API_STATUS libnetapi_set_use_ccache(struct libnetapi_ctx *ctx)
244 {
245         ctx->use_ccache = true;
246         return NET_API_STATUS_SUCCESS;
247 }
248
249 /****************************************************************
250 ****************************************************************/
251
252 const char *libnetapi_errstr(NET_API_STATUS status)
253 {
254         if (status & 0xc0000000) {
255                 return get_friendly_nt_error_msg(NT_STATUS(status));
256         }
257
258         return get_friendly_werror_msg(W_ERROR(status));
259 }
260
261 /****************************************************************
262 ****************************************************************/
263
264 NET_API_STATUS libnetapi_set_error_string(struct libnetapi_ctx *ctx,
265                                           const char *format, ...)
266 {
267         va_list args;
268
269         TALLOC_FREE(ctx->error_string);
270
271         va_start(args, format);
272         ctx->error_string = talloc_vasprintf(ctx, format, args);
273         va_end(args);
274
275         if (!ctx->error_string) {
276                 return W_ERROR_V(WERR_NOMEM);
277         }
278         return NET_API_STATUS_SUCCESS;
279 }
280
281 /****************************************************************
282 ****************************************************************/
283
284 const char *libnetapi_get_error_string(struct libnetapi_ctx *ctx,
285                                        NET_API_STATUS status_in)
286 {
287         NET_API_STATUS status;
288         struct libnetapi_ctx *tmp_ctx = ctx;
289
290         if (!tmp_ctx) {
291                 status = libnetapi_getctx(&tmp_ctx);
292                 if (status != 0) {
293                         return NULL;
294                 }
295         }
296
297         if (tmp_ctx->error_string) {
298                 return tmp_ctx->error_string;
299         }
300
301         return libnetapi_errstr(status_in);
302 }
303
304 /****************************************************************
305 ****************************************************************/
306
307 NET_API_STATUS NetApiBufferAllocate(uint32_t byte_count,
308                                     void **buffer)
309 {
310         void *buf = NULL;
311
312         if (!buffer) {
313                 return W_ERROR_V(WERR_INSUFFICIENT_BUFFER);
314         }
315
316         if (byte_count == 0) {
317                 goto done;
318         }
319
320         buf = talloc_size(NULL, byte_count);
321         if (!buf) {
322                 return W_ERROR_V(WERR_NOMEM);
323         }
324
325  done:
326         *buffer = buf;
327
328         return NET_API_STATUS_SUCCESS;
329 }
330
331 /****************************************************************
332 ****************************************************************/
333
334 NET_API_STATUS NetApiBufferFree(void *buffer)
335 {
336         if (!buffer) {
337                 return W_ERROR_V(WERR_INSUFFICIENT_BUFFER);
338         }
339
340         talloc_free(buffer);
341
342         return NET_API_STATUS_SUCCESS;
343 }