s3-netapi: remove pointless use_memory_krb5_ccache.
[mat/samba.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 static bool libnetapi_initialized = false;
28
29 /****************************************************************
30 ****************************************************************/
31
32 static NET_API_STATUS libnetapi_init_private_context(struct libnetapi_ctx *ctx)
33 {
34         struct libnetapi_private_ctx *priv;
35
36         if (!ctx) {
37                 return W_ERROR_V(WERR_INVALID_PARAM);
38         }
39
40         priv = talloc_zero(ctx, struct libnetapi_private_ctx);
41         if (!priv) {
42                 return W_ERROR_V(WERR_NOMEM);
43         }
44
45         ctx->private_data = priv;
46
47         return NET_API_STATUS_SUCCESS;
48 }
49
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 ****************************************************************/
56
57 NET_API_STATUS libnetapi_init(struct libnetapi_ctx **context)
58 {
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;
64         }
65
66 #if 0
67         talloc_enable_leak_report();
68 #endif
69         frame = talloc_stackframe();
70
71         /* Case tables must be loaded before any string comparisons occour */
72         load_case_tables_library();
73
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);
79
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);
84         }
85
86         init_names();
87         load_interfaces();
88         reopen_logs();
89
90         BlockSignals(True, SIGPIPE);
91
92         ret = libnetapi_net_init(context);
93         TALLOC_FREE(frame);
94         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 NET_API_STATUS libnetapi_net_init(struct libnetapi_ctx **context)
106 {
107         NET_API_STATUS status;
108         struct libnetapi_ctx *ctx = NULL;
109         TALLOC_CTX *frame = talloc_stackframe();
110
111         ctx = talloc_zero(frame, struct libnetapi_ctx);
112         if (!ctx) {
113                 TALLOC_FREE(frame);
114                 return W_ERROR_V(WERR_NOMEM);
115         }
116
117         BlockSignals(True, SIGPIPE);
118
119         if (getenv("USER")) {
120                 ctx->username = talloc_strdup(ctx, getenv("USER"));
121         } else {
122                 ctx->username = talloc_strdup(ctx, "");
123         }
124         if (!ctx->username) {
125                 TALLOC_FREE(frame);
126                 fprintf(stderr, "libnetapi_init: out of memory\n");
127                 return W_ERROR_V(WERR_NOMEM);
128         }
129
130         status = libnetapi_init_private_context(ctx);
131         if (status != 0) {
132                 TALLOC_FREE(frame);
133                 return status;
134         }
135
136         libnetapi_initialized = true;
137
138         talloc_steal(NULL, ctx);
139         *context = stat_ctx = ctx;
140         
141         TALLOC_FREE(frame);
142         return NET_API_STATUS_SUCCESS;
143 }
144
145 /****************************************************************
146  Return the static libnetapi context
147 ****************************************************************/
148
149 NET_API_STATUS libnetapi_getctx(struct libnetapi_ctx **ctx)
150 {
151         if (stat_ctx) {
152                 *ctx = stat_ctx;
153                 return NET_API_STATUS_SUCCESS;
154         }
155
156         return libnetapi_init(ctx);
157 }
158
159 /****************************************************************
160  Free the static libnetapi context
161 ****************************************************************/
162
163 NET_API_STATUS libnetapi_free(struct libnetapi_ctx *ctx)
164 {
165         if (!ctx) {
166                 return NET_API_STATUS_SUCCESS;
167         }
168
169         libnetapi_samr_free(ctx);
170
171         libnetapi_shutdown_cm(ctx);
172
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);
177                 }
178         }
179
180         gfree_names();
181         gfree_loadparm();
182         gfree_charcnv();
183         gfree_interfaces();
184
185         secrets_shutdown();
186
187         if (ctx == stat_ctx) {
188                 stat_ctx = NULL;
189         }
190         TALLOC_FREE(ctx);
191
192         gfree_debugsyms();
193
194         return NET_API_STATUS_SUCCESS;
195 }
196
197 /****************************************************************
198  Override the current log level for libnetapi
199 ****************************************************************/
200
201 NET_API_STATUS libnetapi_set_debuglevel(struct libnetapi_ctx *ctx,
202                                         const char *debuglevel)
203 {
204         TALLOC_CTX *frame = talloc_stackframe();
205         ctx->debuglevel = talloc_strdup(ctx, debuglevel);
206         
207         if (!lp_set_cmdline("log level", debuglevel)) {
208                 TALLOC_FREE(frame);
209                 return W_ERROR_V(WERR_GENERAL_FAILURE);
210         }
211         TALLOC_FREE(frame);
212         return NET_API_STATUS_SUCCESS;
213 }
214
215 /****************************************************************
216 ****************************************************************/
217
218 NET_API_STATUS libnetapi_get_debuglevel(struct libnetapi_ctx *ctx,
219                                         char **debuglevel)
220 {
221         *debuglevel = ctx->debuglevel;
222         return NET_API_STATUS_SUCCESS;
223 }
224
225 /****************************************************************
226 ****************************************************************/
227
228 NET_API_STATUS libnetapi_set_username(struct libnetapi_ctx *ctx,
229                                       const char *username)
230 {
231         TALLOC_FREE(ctx->username);
232         ctx->username = talloc_strdup(ctx, username ? username : "");
233
234         if (!ctx->username) {
235                 return W_ERROR_V(WERR_NOMEM);
236         }
237         return NET_API_STATUS_SUCCESS;
238 }
239
240 NET_API_STATUS libnetapi_set_password(struct libnetapi_ctx *ctx,
241                                       const char *password)
242 {
243         TALLOC_FREE(ctx->password);
244         ctx->password = talloc_strdup(ctx, password);
245         if (!ctx->password) {
246                 return W_ERROR_V(WERR_NOMEM);
247         }
248         return NET_API_STATUS_SUCCESS;
249 }
250
251 NET_API_STATUS libnetapi_set_workgroup(struct libnetapi_ctx *ctx,
252                                        const char *workgroup)
253 {
254         TALLOC_FREE(ctx->workgroup);
255         ctx->workgroup = talloc_strdup(ctx, workgroup);
256         if (!ctx->workgroup) {
257                 return W_ERROR_V(WERR_NOMEM);
258         }
259         return NET_API_STATUS_SUCCESS;
260 }
261
262 /****************************************************************
263 ****************************************************************/
264
265 NET_API_STATUS libnetapi_set_use_kerberos(struct libnetapi_ctx *ctx)
266 {
267         ctx->use_kerberos = true;
268         return NET_API_STATUS_SUCCESS;
269 }
270
271 /****************************************************************
272 ****************************************************************/
273
274 NET_API_STATUS libnetapi_set_use_ccache(struct libnetapi_ctx *ctx)
275 {
276         ctx->use_ccache = true;
277         return NET_API_STATUS_SUCCESS;
278 }
279
280 /****************************************************************
281 Return a libnetapi error as a string, caller must free with NetApiBufferFree
282 ****************************************************************/
283
284 char *libnetapi_errstr(NET_API_STATUS status)
285 {
286         TALLOC_CTX *frame = talloc_stackframe();
287         char *ret;
288         if (status & 0xc0000000) {
289                 ret = talloc_strdup(NULL, 
290                                      get_friendly_nt_error_msg(NT_STATUS(status)));
291         } else {
292                 ret = talloc_strdup(NULL,
293                                     get_friendly_werror_msg(W_ERROR(status)));
294         }
295         TALLOC_FREE(frame);
296         return ret;
297 }
298
299 /****************************************************************
300 ****************************************************************/
301
302 NET_API_STATUS libnetapi_set_error_string(struct libnetapi_ctx *ctx,
303                                           const char *format, ...)
304 {
305         va_list args;
306
307         TALLOC_FREE(ctx->error_string);
308
309         va_start(args, format);
310         ctx->error_string = talloc_vasprintf(ctx, format, args);
311         va_end(args);
312
313         if (!ctx->error_string) {
314                 return W_ERROR_V(WERR_NOMEM);
315         }
316         return NET_API_STATUS_SUCCESS;
317 }
318
319 /****************************************************************
320 Return a libnetapi_errstr(), caller must free with NetApiBufferFree
321 ****************************************************************/
322
323 char *libnetapi_get_error_string(struct libnetapi_ctx *ctx,
324                                        NET_API_STATUS status_in)
325 {
326         NET_API_STATUS status;
327         struct libnetapi_ctx *tmp_ctx = ctx;
328
329         if (!tmp_ctx) {
330                 status = libnetapi_getctx(&tmp_ctx);
331                 if (status != 0) {
332                         return NULL;
333                 }
334         }
335
336         if (tmp_ctx->error_string) {
337                 return talloc_strdup(NULL, tmp_ctx->error_string);
338         }
339
340         return libnetapi_errstr(status_in);
341 }
342
343 /****************************************************************
344 ****************************************************************/
345
346 NET_API_STATUS NetApiBufferAllocate(uint32_t byte_count,
347                                     void **buffer)
348 {
349         void *buf = NULL;
350
351         if (!buffer) {
352                 return W_ERROR_V(WERR_INSUFFICIENT_BUFFER);
353         }
354
355         if (byte_count == 0) {
356                 goto done;
357         }
358
359         buf = talloc_size(NULL, byte_count);
360         if (!buf) {
361                 return W_ERROR_V(WERR_NOMEM);
362         }
363
364  done:
365         *buffer = buf;
366
367         return NET_API_STATUS_SUCCESS;
368 }
369
370 /****************************************************************
371 ****************************************************************/
372
373 NET_API_STATUS NetApiBufferFree(void *buffer)
374 {
375         if (!buffer) {
376                 return W_ERROR_V(WERR_INSUFFICIENT_BUFFER);
377         }
378
379         talloc_free(buffer);
380
381         return NET_API_STATUS_SUCCESS;
382 }