libnetapi: do not overwrite status in libnetapi_get_error_string().
[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
24 extern bool AllowDebugChange;
25
26 struct libnetapi_ctx *stat_ctx = NULL;
27 TALLOC_CTX *frame = NULL;
28 static bool libnetapi_initialized = false;
29
30 /****************************************************************
31 ****************************************************************/
32
33 NET_API_STATUS libnetapi_init(struct libnetapi_ctx **context)
34 {
35         struct libnetapi_ctx *ctx = NULL;
36         char *krb5_cc_env = NULL;
37
38         if (stat_ctx && libnetapi_initialized) {
39                 *context = stat_ctx;
40                 return NET_API_STATUS_SUCCESS;
41         }
42
43 #ifdef DEVELOPER
44         talloc_enable_leak_report();
45 #endif
46         frame = talloc_stackframe();
47
48         ctx = talloc_zero(frame, struct libnetapi_ctx);
49         if (!ctx) {
50                 TALLOC_FREE(frame);
51                 return W_ERROR_V(WERR_NOMEM);
52         }
53
54         if (!DEBUGLEVEL) {
55                 DEBUGLEVEL = 0;
56         }
57
58         /* prevent setup_logging() from closing x_stderr... */
59         dbf = 0;
60         setup_logging("libnetapi", true);
61
62         dbf = x_stderr;
63         x_setbuf(x_stderr, NULL);
64         AllowDebugChange = false;
65
66         load_case_tables();
67
68         if (!lp_load(get_dyn_CONFIGFILE(), true, false, false, false)) {
69                 TALLOC_FREE(frame);
70                 fprintf(stderr, "lp_load failed\n");
71                 return W_ERROR_V(WERR_GENERAL_FAILURE);
72         }
73
74         AllowDebugChange = true;
75
76         init_names();
77         load_interfaces();
78         reopen_logs();
79
80         BlockSignals(True, SIGPIPE);
81
82         krb5_cc_env = getenv(KRB5_ENV_CCNAME);
83         if (!krb5_cc_env || (strlen(krb5_cc_env) == 0)) {
84                 ctx->krb5_cc_env = talloc_strdup(frame, "MEMORY:libnetapi");
85                 setenv(KRB5_ENV_CCNAME, ctx->krb5_cc_env, 1);
86         }
87
88         ctx->username = talloc_strdup(frame, getenv("USER"));
89         if (!ctx->username) {
90                 TALLOC_FREE(frame);
91                 fprintf(stderr, "out of memory\n");
92                 return W_ERROR_V(WERR_NOMEM);
93         }
94
95         libnetapi_initialized = true;
96
97         *context = stat_ctx = ctx;
98
99         return NET_API_STATUS_SUCCESS;
100 }
101
102 /****************************************************************
103 ****************************************************************/
104
105 NET_API_STATUS libnetapi_getctx(struct libnetapi_ctx **ctx)
106 {
107         if (stat_ctx) {
108                 *ctx = stat_ctx;
109                 return NET_API_STATUS_SUCCESS;
110         }
111
112         return libnetapi_init(ctx);
113 }
114
115 /****************************************************************
116 ****************************************************************/
117
118 NET_API_STATUS libnetapi_free(struct libnetapi_ctx *ctx)
119 {
120         if (!ctx) {
121                 return NET_API_STATUS_SUCCESS;
122         }
123
124         libnetapi_shutdown_cm(ctx);
125
126         if (ctx->krb5_cc_env) {
127                 char *env = getenv(KRB5_ENV_CCNAME);
128                 if (env && (strequal(ctx->krb5_cc_env, env))) {
129                         unsetenv(KRB5_ENV_CCNAME);
130                 }
131         }
132
133         gfree_names();
134         gfree_loadparm();
135         gfree_case_tables();
136         gfree_charcnv();
137         gfree_interfaces();
138
139         gencache_shutdown();
140         secrets_shutdown();
141
142         TALLOC_FREE(ctx);
143         TALLOC_FREE(frame);
144
145         gfree_debugsyms();
146
147         return NET_API_STATUS_SUCCESS;
148 }
149
150 /****************************************************************
151 ****************************************************************/
152
153 NET_API_STATUS libnetapi_set_debuglevel(struct libnetapi_ctx *ctx,
154                                         const char *debuglevel)
155 {
156         AllowDebugChange = true;
157         ctx->debuglevel = talloc_strdup(ctx, debuglevel);
158         if (!debug_parse_levels(debuglevel)) {
159                 return W_ERROR_V(WERR_GENERAL_FAILURE);
160         }
161         return NET_API_STATUS_SUCCESS;
162 }
163
164 /****************************************************************
165 ****************************************************************/
166
167 NET_API_STATUS libnetapi_get_debuglevel(struct libnetapi_ctx *ctx,
168                                         char **debuglevel)
169 {
170         *debuglevel = ctx->debuglevel;
171         return NET_API_STATUS_SUCCESS;
172 }
173
174 /****************************************************************
175 ****************************************************************/
176
177 NET_API_STATUS libnetapi_set_username(struct libnetapi_ctx *ctx,
178                                       const char *username)
179 {
180         TALLOC_FREE(ctx->username);
181         ctx->username = talloc_strdup(ctx, username ? username : "");
182
183         if (!ctx->username) {
184                 return W_ERROR_V(WERR_NOMEM);
185         }
186         return NET_API_STATUS_SUCCESS;
187 }
188
189 NET_API_STATUS libnetapi_set_password(struct libnetapi_ctx *ctx,
190                                       const char *password)
191 {
192         TALLOC_FREE(ctx->password);
193         ctx->password = talloc_strdup(ctx, password);
194         if (!ctx->password) {
195                 return W_ERROR_V(WERR_NOMEM);
196         }
197         return NET_API_STATUS_SUCCESS;
198 }
199
200 NET_API_STATUS libnetapi_set_workgroup(struct libnetapi_ctx *ctx,
201                                        const char *workgroup)
202 {
203         TALLOC_FREE(ctx->workgroup);
204         ctx->workgroup = talloc_strdup(ctx, workgroup);
205         if (!ctx->workgroup) {
206                 return W_ERROR_V(WERR_NOMEM);
207         }
208         return NET_API_STATUS_SUCCESS;
209 }
210
211 /****************************************************************
212 ****************************************************************/
213
214 NET_API_STATUS libnetapi_set_use_kerberos(struct libnetapi_ctx *ctx)
215 {
216         ctx->use_kerberos = true;
217         return NET_API_STATUS_SUCCESS;
218 }
219
220 /****************************************************************
221 ****************************************************************/
222
223 const char *libnetapi_errstr(NET_API_STATUS status)
224 {
225         if (status & 0xc0000000) {
226                 return get_friendly_nt_error_msg(NT_STATUS(status));
227         }
228
229         return get_friendly_werror_msg(W_ERROR(status));
230 }
231
232 /****************************************************************
233 ****************************************************************/
234
235 NET_API_STATUS libnetapi_set_error_string(struct libnetapi_ctx *ctx,
236                                           const char *format, ...)
237 {
238         va_list args;
239
240         TALLOC_FREE(ctx->error_string);
241
242         va_start(args, format);
243         ctx->error_string = talloc_vasprintf(ctx, format, args);
244         va_end(args);
245
246         if (!ctx->error_string) {
247                 return W_ERROR_V(WERR_NOMEM);
248         }
249         return NET_API_STATUS_SUCCESS;
250 }
251
252 /****************************************************************
253 ****************************************************************/
254
255 const char *libnetapi_get_error_string(struct libnetapi_ctx *ctx,
256                                        NET_API_STATUS status_in)
257 {
258         NET_API_STATUS status;
259         struct libnetapi_ctx *tmp_ctx = ctx;
260
261         if (!tmp_ctx) {
262                 status = libnetapi_getctx(&tmp_ctx);
263                 if (status != 0) {
264                         return NULL;
265                 }
266         }
267
268         if (tmp_ctx->error_string) {
269                 return tmp_ctx->error_string;
270         }
271
272         return libnetapi_errstr(status_in);
273 }
274
275 /****************************************************************
276 ****************************************************************/
277
278 NET_API_STATUS NetApiBufferFree(void *buffer)
279 {
280         if (!buffer) {
281                 return W_ERROR_V(WERR_INSUFFICIENT_BUFFER);
282         }
283
284         talloc_free(buffer);
285
286         return NET_API_STATUS_SUCCESS;
287 }