s3-libnetapi: add libnetapi_set_logfile()
[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 "../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         /* Ignore return code, as we might not have a smb.conf */
133         (void)cli_credentials_guess(ctx->creds, lp_ctx);
134
135         status = libnetapi_init_private_context(ctx);
136         if (status != 0) {
137                 TALLOC_FREE(frame);
138                 return status;
139         }
140
141         libnetapi_initialized = true;
142
143         talloc_steal(NULL, ctx);
144         *context = stat_ctx = ctx;
145         
146         TALLOC_FREE(frame);
147         return NET_API_STATUS_SUCCESS;
148 }
149
150 /****************************************************************
151  Return the static libnetapi context
152 ****************************************************************/
153
154 NET_API_STATUS libnetapi_getctx(struct libnetapi_ctx **ctx)
155 {
156         if (stat_ctx) {
157                 *ctx = stat_ctx;
158                 return NET_API_STATUS_SUCCESS;
159         }
160
161         return libnetapi_init(ctx);
162 }
163
164 /****************************************************************
165  Free the static libnetapi context
166 ****************************************************************/
167
168 NET_API_STATUS libnetapi_free(struct libnetapi_ctx *ctx)
169 {
170         TALLOC_CTX *frame;
171
172         if (!ctx) {
173                 return NET_API_STATUS_SUCCESS;
174         }
175
176         frame = talloc_stackframe();
177         libnetapi_samr_free(ctx);
178
179         libnetapi_shutdown_cm(ctx);
180
181         gfree_loadparm();
182         gfree_charcnv();
183         gfree_interfaces();
184
185         secrets_shutdown();
186
187         netlogon_creds_cli_close_global_db();
188
189         if (ctx == stat_ctx) {
190                 stat_ctx = NULL;
191         }
192         TALLOC_FREE(ctx);
193
194         gfree_debugsyms();
195         talloc_free(frame);
196
197         return NET_API_STATUS_SUCCESS;
198 }
199
200 /****************************************************************
201  Override the current log level for libnetapi
202 ****************************************************************/
203
204 NET_API_STATUS libnetapi_set_debuglevel(struct libnetapi_ctx *ctx,
205                                         const char *debuglevel)
206 {
207         TALLOC_CTX *frame = talloc_stackframe();
208         ctx->debuglevel = talloc_strdup(ctx, debuglevel);
209         
210         if (!lp_set_cmdline("log level", debuglevel)) {
211                 TALLOC_FREE(frame);
212                 return W_ERROR_V(WERR_GEN_FAILURE);
213         }
214         TALLOC_FREE(frame);
215         return NET_API_STATUS_SUCCESS;
216 }
217
218 /****************************************************************
219 ****************************************************************/
220
221 NET_API_STATUS libnetapi_set_logfile(struct libnetapi_ctx *ctx,
222                                      const char *logfile)
223 {
224         TALLOC_CTX *frame = talloc_stackframe();
225         ctx->logfile = talloc_strdup(ctx, logfile);
226
227         if (!lp_set_cmdline("log file", logfile)) {
228                 TALLOC_FREE(frame);
229                 return W_ERROR_V(WERR_GEN_FAILURE);
230         }
231         debug_set_logfile(logfile);
232         setup_logging("libnetapi", DEBUG_FILE);
233         TALLOC_FREE(frame);
234         return NET_API_STATUS_SUCCESS;
235 }
236
237 /****************************************************************
238 ****************************************************************/
239
240 NET_API_STATUS libnetapi_get_debuglevel(struct libnetapi_ctx *ctx,
241                                         char **debuglevel)
242 {
243         *debuglevel = ctx->debuglevel;
244         return NET_API_STATUS_SUCCESS;
245 }
246
247 /****************************************************************
248 ****************************************************************/
249
250 /**
251  * @brief Get the username of the libnet context
252  *
253  * @param[in]  ctx      The netapi context
254  *
255  * @param[in]  username A pointer to hold the username.
256  *
257  * @return 0 on success, an werror code otherwise.
258  */
259 NET_API_STATUS libnetapi_get_username(struct libnetapi_ctx *ctx,
260                                       const char **username)
261 {
262         if (ctx == NULL) {
263                 return W_ERROR_V(WERR_INVALID_PARAMETER);
264         }
265
266         if (username != NULL) {
267                 *username = cli_credentials_get_username(ctx->creds);
268         }
269
270         return NET_API_STATUS_SUCCESS;
271 }
272
273 /**
274  * @brief Get the password of the libnet context
275  *
276  * @param[in]  ctx      The netapi context
277  *
278  * @param[in]  password A pointer to hold the password.
279  *
280  * @return 0 on success, an werror code otherwise.
281  */
282 NET_API_STATUS libnetapi_get_password(struct libnetapi_ctx *ctx,
283                                       const char **password)
284 {
285         if (ctx == NULL) {
286                 return W_ERROR_V(WERR_INVALID_PARAMETER);
287         }
288
289         if (password != NULL) {
290                 *password = cli_credentials_get_password(ctx->creds);
291         }
292
293         return NET_API_STATUS_SUCCESS;
294 }
295
296 NET_API_STATUS libnetapi_set_username(struct libnetapi_ctx *ctx,
297                                       const char *username)
298 {
299         if (ctx == NULL || username == NULL) {
300                 return W_ERROR_V(WERR_INVALID_PARAMETER);
301         }
302
303         cli_credentials_parse_string(ctx->creds, username, CRED_SPECIFIED);
304
305         return NET_API_STATUS_SUCCESS;
306 }
307
308 NET_API_STATUS libnetapi_set_password(struct libnetapi_ctx *ctx,
309                                       const char *password)
310 {
311         bool ok;
312
313         if (ctx == NULL || password == NULL) {
314                 return W_ERROR_V(WERR_INVALID_PARAMETER);
315         }
316
317         ok = cli_credentials_set_password(ctx->creds, password, CRED_SPECIFIED);
318         if (!ok) {
319                 return W_ERROR_V(WERR_INTERNAL_ERROR);
320         }
321
322         return NET_API_STATUS_SUCCESS;
323 }
324
325 NET_API_STATUS libnetapi_set_workgroup(struct libnetapi_ctx *ctx,
326                                        const char *workgroup)
327 {
328         bool ok;
329
330         ok = cli_credentials_set_domain(ctx->creds, workgroup, CRED_SPECIFIED);
331         if (!ok) {
332                 return W_ERROR_V(WERR_INTERNAL_ERROR);
333         }
334
335         return NET_API_STATUS_SUCCESS;
336 }
337
338 /**
339  * @brief Set the cli_credentials to be used in the netapi context
340  *
341  * @param[in]  ctx    The netapi context
342  *
343  * @param[in]  creds  The cli_credentials which should be used by netapi.
344  *
345  * @return 0 on success, an werror code otherwise.
346  */
347 NET_API_STATUS libnetapi_set_creds(struct libnetapi_ctx *ctx,
348                                    struct cli_credentials *creds)
349 {
350         if (ctx == NULL || creds == NULL) {
351                 return W_ERROR_V(WERR_INVALID_PARAMETER);
352         }
353
354         ctx->creds = creds;
355
356         return NET_API_STATUS_SUCCESS;
357 }
358
359 /****************************************************************
360 ****************************************************************/
361
362 NET_API_STATUS libnetapi_set_use_kerberos(struct libnetapi_ctx *ctx)
363 {
364         cli_credentials_set_kerberos_state(ctx->creds,
365                                            CRED_USE_KERBEROS_REQUIRED,
366                                            CRED_SPECIFIED);
367
368         return NET_API_STATUS_SUCCESS;
369 }
370
371 /****************************************************************
372 ****************************************************************/
373
374 NET_API_STATUS libnetapi_get_use_kerberos(struct libnetapi_ctx *ctx,
375                                           int *use_kerberos)
376 {
377         enum credentials_use_kerberos creds_use_kerberos;
378
379         *use_kerberos = 0;
380
381         creds_use_kerberos = cli_credentials_get_kerberos_state(ctx->creds);
382         if (creds_use_kerberos > CRED_USE_KERBEROS_DESIRED) {
383                 *use_kerberos = 1;
384         }
385
386         return NET_API_STATUS_SUCCESS;
387 }
388
389 /****************************************************************
390 ****************************************************************/
391
392 NET_API_STATUS libnetapi_set_use_ccache(struct libnetapi_ctx *ctx)
393 {
394         uint32_t gensec_features;
395
396         gensec_features = cli_credentials_get_gensec_features(ctx->creds);
397         gensec_features |= GENSEC_FEATURE_NTLM_CCACHE;
398         cli_credentials_set_gensec_features(ctx->creds,
399                                             gensec_features,
400                                             CRED_SPECIFIED);
401
402         return NET_API_STATUS_SUCCESS;
403 }
404
405 /****************************************************************
406 Return a libnetapi error as a string, caller must free with NetApiBufferFree
407 ****************************************************************/
408
409 char *libnetapi_errstr(NET_API_STATUS status)
410 {
411         TALLOC_CTX *frame = talloc_stackframe();
412         char *ret;
413         if (status & 0xc0000000) {
414                 ret = talloc_strdup(NULL, 
415                                      get_friendly_nt_error_msg(NT_STATUS(status)));
416         } else {
417                 ret = talloc_strdup(NULL,
418                                     get_friendly_werror_msg(W_ERROR(status)));
419         }
420         TALLOC_FREE(frame);
421         return ret;
422 }
423
424 /****************************************************************
425 ****************************************************************/
426
427 NET_API_STATUS libnetapi_set_error_string(struct libnetapi_ctx *ctx,
428                                           const char *format, ...)
429 {
430         va_list args;
431
432         TALLOC_FREE(ctx->error_string);
433
434         va_start(args, format);
435         ctx->error_string = talloc_vasprintf(ctx, format, args);
436         va_end(args);
437
438         if (!ctx->error_string) {
439                 return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
440         }
441         return NET_API_STATUS_SUCCESS;
442 }
443
444 /****************************************************************
445 Return a libnetapi_errstr(), caller must free with NetApiBufferFree
446 ****************************************************************/
447
448 char *libnetapi_get_error_string(struct libnetapi_ctx *ctx,
449                                        NET_API_STATUS status_in)
450 {
451         NET_API_STATUS status;
452         struct libnetapi_ctx *tmp_ctx = ctx;
453
454         if (!tmp_ctx) {
455                 status = libnetapi_getctx(&tmp_ctx);
456                 if (status != 0) {
457                         return NULL;
458                 }
459         }
460
461         if (tmp_ctx->error_string) {
462                 return talloc_strdup(NULL, tmp_ctx->error_string);
463         }
464
465         return libnetapi_errstr(status_in);
466 }
467
468 /****************************************************************
469 ****************************************************************/
470
471 NET_API_STATUS NetApiBufferAllocate(uint32_t byte_count,
472                                     void **buffer)
473 {
474         void *buf = NULL;
475
476         if (!buffer) {
477                 return W_ERROR_V(WERR_INSUFFICIENT_BUFFER);
478         }
479
480         if (byte_count == 0) {
481                 goto done;
482         }
483
484         buf = talloc_size(NULL, byte_count);
485         if (!buf) {
486                 return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
487         }
488
489  done:
490         *buffer = buf;
491
492         return NET_API_STATUS_SUCCESS;
493 }
494
495 /****************************************************************
496 ****************************************************************/
497
498 NET_API_STATUS NetApiBufferFree(void *buffer)
499 {
500         if (!buffer) {
501                 return W_ERROR_V(WERR_INSUFFICIENT_BUFFER);
502         }
503
504         talloc_free(buffer);
505
506         return NET_API_STATUS_SUCCESS;
507 }