s3:netapi: Remove use_ccache from 'struct libnetapi_ctx'
[metze/samba-autobuild/.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 "../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 static NET_API_STATUS libnetapi_init_private_context(struct libnetapi_ctx *ctx)
37 {
38         struct libnetapi_private_ctx *priv;
39
40         if (!ctx) {
41                 return W_ERROR_V(WERR_INVALID_PARAMETER);
42         }
43
44         priv = talloc_zero(ctx, struct libnetapi_private_ctx);
45         if (!priv) {
46                 return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
47         }
48
49         ctx->private_data = priv;
50
51         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 NET_API_STATUS libnetapi_init(struct libnetapi_ctx **context)
62 {
63         NET_API_STATUS ret;
64         TALLOC_CTX *frame;
65         if (stat_ctx && libnetapi_initialized) {
66                 *context = stat_ctx;
67                 return NET_API_STATUS_SUCCESS;
68         }
69
70 #if 0
71         talloc_enable_leak_report();
72 #endif
73         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         lp_set_cmdline("log level", "0");
79         setup_logging("libnetapi", DEBUG_STDERR);
80
81         if (!lp_load_global(get_dyn_CONFIGFILE())) {
82                 TALLOC_FREE(frame);
83                 fprintf(stderr, "error loading %s\n", get_dyn_CONFIGFILE() );
84                 return W_ERROR_V(WERR_GEN_FAILURE);
85         }
86
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         struct loadparm_context *lp_ctx = NULL;
111
112         ctx = talloc_zero(frame, struct libnetapi_ctx);
113         if (!ctx) {
114                 TALLOC_FREE(frame);
115                 return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
116         }
117
118         ctx->creds = cli_credentials_init(ctx);
119         if (ctx->creds == NULL) {
120                 TALLOC_FREE(frame);
121                 return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
122         }
123
124         lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
125         if (lp_ctx == NULL) {
126                 TALLOC_FREE(frame);
127                 return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
128         }
129
130         BlockSignals(True, SIGPIPE);
131
132         cli_credentials_guess(ctx->creds, lp_ctx);
133
134         status = libnetapi_init_private_context(ctx);
135         if (status != 0) {
136                 TALLOC_FREE(frame);
137                 return status;
138         }
139
140         libnetapi_initialized = true;
141
142         talloc_steal(NULL, ctx);
143         *context = stat_ctx = ctx;
144         
145         TALLOC_FREE(frame);
146         return NET_API_STATUS_SUCCESS;
147 }
148
149 /****************************************************************
150  Return the static libnetapi context
151 ****************************************************************/
152
153 NET_API_STATUS libnetapi_getctx(struct libnetapi_ctx **ctx)
154 {
155         if (stat_ctx) {
156                 *ctx = stat_ctx;
157                 return NET_API_STATUS_SUCCESS;
158         }
159
160         return libnetapi_init(ctx);
161 }
162
163 /****************************************************************
164  Free the static libnetapi context
165 ****************************************************************/
166
167 NET_API_STATUS libnetapi_free(struct libnetapi_ctx *ctx)
168 {
169         TALLOC_CTX *frame;
170
171         if (!ctx) {
172                 return NET_API_STATUS_SUCCESS;
173         }
174
175         frame = talloc_stackframe();
176         libnetapi_samr_free(ctx);
177
178         libnetapi_shutdown_cm(ctx);
179
180         gfree_loadparm();
181         gfree_charcnv();
182         gfree_interfaces();
183
184         secrets_shutdown();
185
186         netlogon_creds_cli_close_global_db();
187
188         if (ctx == stat_ctx) {
189                 stat_ctx = NULL;
190         }
191         TALLOC_FREE(ctx);
192
193         gfree_debugsyms();
194         talloc_free(frame);
195
196         return NET_API_STATUS_SUCCESS;
197 }
198
199 /****************************************************************
200  Override the current log level for libnetapi
201 ****************************************************************/
202
203 NET_API_STATUS libnetapi_set_debuglevel(struct libnetapi_ctx *ctx,
204                                         const char *debuglevel)
205 {
206         TALLOC_CTX *frame = talloc_stackframe();
207         ctx->debuglevel = talloc_strdup(ctx, debuglevel);
208         
209         if (!lp_set_cmdline("log level", debuglevel)) {
210                 TALLOC_FREE(frame);
211                 return W_ERROR_V(WERR_GEN_FAILURE);
212         }
213         TALLOC_FREE(frame);
214         return NET_API_STATUS_SUCCESS;
215 }
216
217 /****************************************************************
218 ****************************************************************/
219
220 NET_API_STATUS libnetapi_get_debuglevel(struct libnetapi_ctx *ctx,
221                                         char **debuglevel)
222 {
223         *debuglevel = ctx->debuglevel;
224         return NET_API_STATUS_SUCCESS;
225 }
226
227 /****************************************************************
228 ****************************************************************/
229
230 /**
231  * @brief Get the username of the libnet context
232  *
233  * @param[in]  ctx      The netapi context
234  *
235  * @param[in]  username A pointer to hold the username.
236  *
237  * @return 0 on success, an werror code otherwise.
238  */
239 NET_API_STATUS libnetapi_get_username(struct libnetapi_ctx *ctx,
240                                       const char **username)
241 {
242         if (ctx == NULL) {
243                 return W_ERROR_V(WERR_INVALID_PARAMETER);
244         }
245
246         if (username != NULL) {
247                 *username = cli_credentials_get_username(ctx->creds);
248         }
249
250         return NET_API_STATUS_SUCCESS;
251 }
252
253 /**
254  * @brief Get the password of the libnet context
255  *
256  * @param[in]  ctx      The netapi context
257  *
258  * @param[in]  password A pointer to hold the password.
259  *
260  * @return 0 on success, an werror code otherwise.
261  */
262 NET_API_STATUS libnetapi_get_password(struct libnetapi_ctx *ctx,
263                                       const char **password)
264 {
265         if (ctx == NULL) {
266                 return W_ERROR_V(WERR_INVALID_PARAMETER);
267         }
268
269         if (password != NULL) {
270                 *password = cli_credentials_get_password(ctx->creds);
271         }
272
273         return NET_API_STATUS_SUCCESS;
274 }
275
276 NET_API_STATUS libnetapi_set_username(struct libnetapi_ctx *ctx,
277                                       const char *username)
278 {
279         if (ctx == NULL || username == NULL) {
280                 return W_ERROR_V(WERR_INVALID_PARAMETER);
281         }
282
283         cli_credentials_parse_string(ctx->creds, username, CRED_SPECIFIED);
284
285         return NET_API_STATUS_SUCCESS;
286 }
287
288 NET_API_STATUS libnetapi_set_password(struct libnetapi_ctx *ctx,
289                                       const char *password)
290 {
291         bool ok;
292
293         if (ctx == NULL || password == NULL) {
294                 return W_ERROR_V(WERR_INVALID_PARAMETER);
295         }
296
297         ok = cli_credentials_set_password(ctx->creds, password, CRED_SPECIFIED);
298         if (!ok) {
299                 return W_ERROR_V(WERR_INTERNAL_ERROR);
300         }
301
302         return NET_API_STATUS_SUCCESS;
303 }
304
305 NET_API_STATUS libnetapi_set_workgroup(struct libnetapi_ctx *ctx,
306                                        const char *workgroup)
307 {
308         bool ok;
309
310         ok = cli_credentials_set_domain(ctx->creds, workgroup, CRED_SPECIFIED);
311         if (!ok) {
312                 return W_ERROR_V(WERR_INTERNAL_ERROR);
313         }
314
315         return NET_API_STATUS_SUCCESS;
316 }
317
318 /****************************************************************
319 ****************************************************************/
320
321 NET_API_STATUS libnetapi_set_use_kerberos(struct libnetapi_ctx *ctx)
322 {
323         cli_credentials_set_kerberos_state(ctx->creds,
324                                            CRED_USE_KERBEROS_REQUIRED);
325
326         return NET_API_STATUS_SUCCESS;
327 }
328
329 /****************************************************************
330 ****************************************************************/
331
332 NET_API_STATUS libnetapi_set_use_ccache(struct libnetapi_ctx *ctx)
333 {
334         uint32_t gensec_features;
335
336         gensec_features = cli_credentials_get_gensec_features(ctx->creds);
337         gensec_features |= GENSEC_FEATURE_NTLM_CCACHE;
338         cli_credentials_set_gensec_features(ctx->creds, gensec_features);
339
340         return NET_API_STATUS_SUCCESS;
341 }
342
343 /****************************************************************
344 Return a libnetapi error as a string, caller must free with NetApiBufferFree
345 ****************************************************************/
346
347 char *libnetapi_errstr(NET_API_STATUS status)
348 {
349         TALLOC_CTX *frame = talloc_stackframe();
350         char *ret;
351         if (status & 0xc0000000) {
352                 ret = talloc_strdup(NULL, 
353                                      get_friendly_nt_error_msg(NT_STATUS(status)));
354         } else {
355                 ret = talloc_strdup(NULL,
356                                     get_friendly_werror_msg(W_ERROR(status)));
357         }
358         TALLOC_FREE(frame);
359         return ret;
360 }
361
362 /****************************************************************
363 ****************************************************************/
364
365 NET_API_STATUS libnetapi_set_error_string(struct libnetapi_ctx *ctx,
366                                           const char *format, ...)
367 {
368         va_list args;
369
370         TALLOC_FREE(ctx->error_string);
371
372         va_start(args, format);
373         ctx->error_string = talloc_vasprintf(ctx, format, args);
374         va_end(args);
375
376         if (!ctx->error_string) {
377                 return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
378         }
379         return NET_API_STATUS_SUCCESS;
380 }
381
382 /****************************************************************
383 Return a libnetapi_errstr(), caller must free with NetApiBufferFree
384 ****************************************************************/
385
386 char *libnetapi_get_error_string(struct libnetapi_ctx *ctx,
387                                        NET_API_STATUS status_in)
388 {
389         NET_API_STATUS status;
390         struct libnetapi_ctx *tmp_ctx = ctx;
391
392         if (!tmp_ctx) {
393                 status = libnetapi_getctx(&tmp_ctx);
394                 if (status != 0) {
395                         return NULL;
396                 }
397         }
398
399         if (tmp_ctx->error_string) {
400                 return talloc_strdup(NULL, tmp_ctx->error_string);
401         }
402
403         return libnetapi_errstr(status_in);
404 }
405
406 /****************************************************************
407 ****************************************************************/
408
409 NET_API_STATUS NetApiBufferAllocate(uint32_t byte_count,
410                                     void **buffer)
411 {
412         void *buf = NULL;
413
414         if (!buffer) {
415                 return W_ERROR_V(WERR_INSUFFICIENT_BUFFER);
416         }
417
418         if (byte_count == 0) {
419                 goto done;
420         }
421
422         buf = talloc_size(NULL, byte_count);
423         if (!buf) {
424                 return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
425         }
426
427  done:
428         *buffer = buf;
429
430         return NET_API_STATUS_SUCCESS;
431 }
432
433 /****************************************************************
434 ****************************************************************/
435
436 NET_API_STATUS NetApiBufferFree(void *buffer)
437 {
438         if (!buffer) {
439                 return W_ERROR_V(WERR_INSUFFICIENT_BUFFER);
440         }
441
442         talloc_free(buffer);
443
444         return NET_API_STATUS_SUCCESS;
445 }