s3-lib Move isvalid83_w to mangle_hash.c
[ira/wip.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 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 ****************************************************************/
57
58 NET_API_STATUS libnetapi_init(struct libnetapi_ctx **context)
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         /* Case tables must be loaded before any string comparisons occour */
71         load_case_tables_library();
72
73         /* When libnetapi is invoked from an application, it does not
74          * want to be swamped with level 10 debug messages, even if
75          * this has been set for the server in smb.conf */
76         lp_set_cmdline("log level", "0");
77         setup_logging("libnetapi", DEBUG_STDERR);
78
79         if (!lp_load(get_dyn_CONFIGFILE(), true, false, false, false)) {
80                 TALLOC_FREE(frame);
81                 fprintf(stderr, "error loading %s\n", get_dyn_CONFIGFILE() );
82                 return W_ERROR_V(WERR_GENERAL_FAILURE);
83         }
84
85         init_names();
86         load_interfaces();
87         reopen_logs();
88
89         BlockSignals(True, SIGPIPE);
90
91         return libnetapi_net_init(context);
92 }
93
94 /****************************************************************
95 Create a libnetapi context, for use inside the 'net' binary.
96
97 As we know net has already loaded the smb.conf file, and set the debug
98 level etc, this avoids doing so again (which causes trouble with -d on
99 the command line).
100 ****************************************************************/
101
102 NET_API_STATUS libnetapi_net_init(struct libnetapi_ctx **context)
103 {
104         NET_API_STATUS status;
105         struct libnetapi_ctx *ctx = NULL;
106         char *krb5_cc_env = NULL;
107
108         frame = talloc_stackframe();
109
110         ctx = talloc_zero(frame, struct libnetapi_ctx);
111         if (!ctx) {
112                 TALLOC_FREE(frame);
113                 return W_ERROR_V(WERR_NOMEM);
114         }
115
116         BlockSignals(True, SIGPIPE);
117
118         krb5_cc_env = getenv(KRB5_ENV_CCNAME);
119         if (!krb5_cc_env || (strlen(krb5_cc_env) == 0)) {
120                 ctx->krb5_cc_env = talloc_strdup(frame, "MEMORY:libnetapi");
121                 setenv(KRB5_ENV_CCNAME, ctx->krb5_cc_env, 1);
122         }
123
124         if (getenv("USER")) {
125                 ctx->username = talloc_strdup(frame, getenv("USER"));
126         } else {
127                 ctx->username = talloc_strdup(frame, "");
128         }
129         if (!ctx->username) {
130                 TALLOC_FREE(frame);
131                 fprintf(stderr, "libnetapi_init: out of memory\n");
132                 return W_ERROR_V(WERR_NOMEM);
133         }
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         *context = stat_ctx = ctx;
144
145         return NET_API_STATUS_SUCCESS;
146 }
147
148 /****************************************************************
149  Return the static libnetapi context
150 ****************************************************************/
151
152 NET_API_STATUS libnetapi_getctx(struct libnetapi_ctx **ctx)
153 {
154         if (stat_ctx) {
155                 *ctx = stat_ctx;
156                 return NET_API_STATUS_SUCCESS;
157         }
158
159         return libnetapi_init(ctx);
160 }
161
162 /****************************************************************
163  Free the static libnetapi context
164 ****************************************************************/
165
166 NET_API_STATUS libnetapi_free(struct libnetapi_ctx *ctx)
167 {
168         if (!ctx) {
169                 return NET_API_STATUS_SUCCESS;
170         }
171
172         libnetapi_samr_free(ctx);
173
174         libnetapi_shutdown_cm(ctx);
175
176         if (ctx->krb5_cc_env) {
177                 char *env = getenv(KRB5_ENV_CCNAME);
178                 if (env && (strequal(ctx->krb5_cc_env, env))) {
179                         unsetenv(KRB5_ENV_CCNAME);
180                 }
181         }
182
183         gfree_names();
184         gfree_loadparm();
185         gfree_charcnv();
186         gfree_interfaces();
187
188         secrets_shutdown();
189
190         TALLOC_FREE(ctx);
191         TALLOC_FREE(frame);
192
193         gfree_debugsyms();
194
195         return NET_API_STATUS_SUCCESS;
196 }
197
198 /****************************************************************
199  Override the current log level for libnetapi
200 ****************************************************************/
201
202 NET_API_STATUS libnetapi_set_debuglevel(struct libnetapi_ctx *ctx,
203                                         const char *debuglevel)
204 {
205         ctx->debuglevel = talloc_strdup(ctx, debuglevel);
206         if (!lp_set_cmdline("log level", debuglevel)) {
207                 return W_ERROR_V(WERR_GENERAL_FAILURE);
208         }
209         return NET_API_STATUS_SUCCESS;
210 }
211
212 /****************************************************************
213 ****************************************************************/
214
215 NET_API_STATUS libnetapi_get_debuglevel(struct libnetapi_ctx *ctx,
216                                         char **debuglevel)
217 {
218         *debuglevel = ctx->debuglevel;
219         return NET_API_STATUS_SUCCESS;
220 }
221
222 /****************************************************************
223 ****************************************************************/
224
225 NET_API_STATUS libnetapi_set_username(struct libnetapi_ctx *ctx,
226                                       const char *username)
227 {
228         TALLOC_FREE(ctx->username);
229         ctx->username = talloc_strdup(ctx, username ? username : "");
230
231         if (!ctx->username) {
232                 return W_ERROR_V(WERR_NOMEM);
233         }
234         return NET_API_STATUS_SUCCESS;
235 }
236
237 NET_API_STATUS libnetapi_set_password(struct libnetapi_ctx *ctx,
238                                       const char *password)
239 {
240         TALLOC_FREE(ctx->password);
241         ctx->password = talloc_strdup(ctx, password);
242         if (!ctx->password) {
243                 return W_ERROR_V(WERR_NOMEM);
244         }
245         return NET_API_STATUS_SUCCESS;
246 }
247
248 NET_API_STATUS libnetapi_set_workgroup(struct libnetapi_ctx *ctx,
249                                        const char *workgroup)
250 {
251         TALLOC_FREE(ctx->workgroup);
252         ctx->workgroup = talloc_strdup(ctx, workgroup);
253         if (!ctx->workgroup) {
254                 return W_ERROR_V(WERR_NOMEM);
255         }
256         return NET_API_STATUS_SUCCESS;
257 }
258
259 /****************************************************************
260 ****************************************************************/
261
262 NET_API_STATUS libnetapi_set_use_kerberos(struct libnetapi_ctx *ctx)
263 {
264         ctx->use_kerberos = true;
265         return NET_API_STATUS_SUCCESS;
266 }
267
268 NET_API_STATUS libnetapi_set_use_ccache(struct libnetapi_ctx *ctx)
269 {
270         ctx->use_ccache = true;
271         return NET_API_STATUS_SUCCESS;
272 }
273
274 /****************************************************************
275 ****************************************************************/
276
277 const char *libnetapi_errstr(NET_API_STATUS status)
278 {
279         if (status & 0xc0000000) {
280                 return get_friendly_nt_error_msg(NT_STATUS(status));
281         }
282
283         return get_friendly_werror_msg(W_ERROR(status));
284 }
285
286 /****************************************************************
287 ****************************************************************/
288
289 NET_API_STATUS libnetapi_set_error_string(struct libnetapi_ctx *ctx,
290                                           const char *format, ...)
291 {
292         va_list args;
293
294         TALLOC_FREE(ctx->error_string);
295
296         va_start(args, format);
297         ctx->error_string = talloc_vasprintf(ctx, format, args);
298         va_end(args);
299
300         if (!ctx->error_string) {
301                 return W_ERROR_V(WERR_NOMEM);
302         }
303         return NET_API_STATUS_SUCCESS;
304 }
305
306 /****************************************************************
307 ****************************************************************/
308
309 const char *libnetapi_get_error_string(struct libnetapi_ctx *ctx,
310                                        NET_API_STATUS status_in)
311 {
312         NET_API_STATUS status;
313         struct libnetapi_ctx *tmp_ctx = ctx;
314
315         if (!tmp_ctx) {
316                 status = libnetapi_getctx(&tmp_ctx);
317                 if (status != 0) {
318                         return NULL;
319                 }
320         }
321
322         if (tmp_ctx->error_string) {
323                 return tmp_ctx->error_string;
324         }
325
326         return libnetapi_errstr(status_in);
327 }
328
329 /****************************************************************
330 ****************************************************************/
331
332 NET_API_STATUS NetApiBufferAllocate(uint32_t byte_count,
333                                     void **buffer)
334 {
335         void *buf = NULL;
336
337         if (!buffer) {
338                 return W_ERROR_V(WERR_INSUFFICIENT_BUFFER);
339         }
340
341         if (byte_count == 0) {
342                 goto done;
343         }
344
345         buf = talloc_size(NULL, byte_count);
346         if (!buf) {
347                 return W_ERROR_V(WERR_NOMEM);
348         }
349
350  done:
351         *buffer = buf;
352
353         return NET_API_STATUS_SUCCESS;
354 }
355
356 /****************************************************************
357 ****************************************************************/
358
359 NET_API_STATUS NetApiBufferFree(void *buffer)
360 {
361         if (!buffer) {
362                 return W_ERROR_V(WERR_INSUFFICIENT_BUFFER);
363         }
364
365         talloc_free(buffer);
366
367         return NET_API_STATUS_SUCCESS;
368 }