Fix ldap_bind compilation for i386
[Samba.git] / nsswitch / libwbclient / wbclient.c
blob5444e823ddfdbfc3b97a3e79811e1fc704aaed10
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind client API
6 Copyright (C) Gerald (Jerry) Carter 2007
7 Copyright (C) Matthew Newton 2015
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 3 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Library General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 /* Required Headers */
26 #include "replace.h"
27 #include "libwbclient.h"
29 /* From wb_common.c */
31 struct winbindd_context;
33 NSS_STATUS winbindd_request_response(struct winbindd_context *wbctx,
34 int req_type,
35 struct winbindd_request *request,
36 struct winbindd_response *response);
37 NSS_STATUS winbindd_priv_request_response(struct winbindd_context *wbctx,
38 int req_type,
39 struct winbindd_request *request,
40 struct winbindd_response *response);
41 struct winbindd_context *winbindd_ctx_create(void);
42 void winbindd_ctx_free(struct winbindd_context *ctx);
44 /* Global context used for non-Ctx functions */
46 static struct wbcContext wbcGlobalCtx = {
47 .winbindd_ctx = NULL,
48 .pw_cache_size = 0,
49 .pw_cache_idx = 0,
50 .gr_cache_size = 0,
51 .gr_cache_idx = 0
55 result == NSS_STATUS_UNAVAIL: winbind not around
56 result == NSS_STATUS_NOTFOUND: winbind around, but domain missing
58 Due to a bad API NSS_STATUS_NOTFOUND is returned both when winbind_off
59 and when winbind return WINBINDD_ERROR. So the semantics of this
60 routine depends on winbind_on. Grepping for winbind_off I just
61 found 3 places where winbind is turned off, and this does not conflict
62 (as far as I have seen) with the callers of is_trusted_domains.
64 --Volker
67 static wbcErr wbcRequestResponseInt(
68 struct winbindd_context *wbctx,
69 int cmd,
70 struct winbindd_request *request,
71 struct winbindd_response *response,
72 NSS_STATUS (*fn)(struct winbindd_context *wbctx, int req_type,
73 struct winbindd_request *request,
74 struct winbindd_response *response))
76 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
77 NSS_STATUS nss_status;
79 /* for some calls the request and/or response can be NULL */
81 nss_status = fn(wbctx, cmd, request, response);
83 switch (nss_status) {
84 case NSS_STATUS_SUCCESS:
85 wbc_status = WBC_ERR_SUCCESS;
86 break;
87 case NSS_STATUS_UNAVAIL:
88 wbc_status = WBC_ERR_WINBIND_NOT_AVAILABLE;
89 break;
90 case NSS_STATUS_NOTFOUND:
91 wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
92 break;
93 default:
94 wbc_status = WBC_ERR_NSS_ERROR;
95 break;
98 return wbc_status;
102 * @brief Wrapper around Winbind's send/receive API call
104 * @param ctx Context
105 * @param cmd Winbind command operation to perform
106 * @param request Send structure
107 * @param response Receive structure
109 * @return #wbcErr
111 wbcErr wbcRequestResponse(struct wbcContext *ctx, int cmd,
112 struct winbindd_request *request,
113 struct winbindd_response *response)
115 struct winbindd_context *wbctx = NULL;
117 if (ctx) {
118 wbctx = ctx->winbindd_ctx;
121 return wbcRequestResponseInt(wbctx, cmd, request, response,
122 winbindd_request_response);
125 wbcErr wbcRequestResponsePriv(struct wbcContext *ctx, int cmd,
126 struct winbindd_request *request,
127 struct winbindd_response *response)
129 struct winbindd_context *wbctx = NULL;
131 if (ctx) {
132 wbctx = ctx->winbindd_ctx;
135 return wbcRequestResponseInt(wbctx, cmd, request, response,
136 winbindd_priv_request_response);
139 /** @brief Translate an error value into a string
141 * @param error
143 * @return a pointer to a static string
145 const char *wbcErrorString(wbcErr error)
147 switch (error) {
148 case WBC_ERR_SUCCESS:
149 return "WBC_ERR_SUCCESS";
150 case WBC_ERR_NOT_IMPLEMENTED:
151 return "WBC_ERR_NOT_IMPLEMENTED";
152 case WBC_ERR_UNKNOWN_FAILURE:
153 return "WBC_ERR_UNKNOWN_FAILURE";
154 case WBC_ERR_NO_MEMORY:
155 return "WBC_ERR_NO_MEMORY";
156 case WBC_ERR_INVALID_SID:
157 return "WBC_ERR_INVALID_SID";
158 case WBC_ERR_INVALID_PARAM:
159 return "WBC_ERR_INVALID_PARAM";
160 case WBC_ERR_WINBIND_NOT_AVAILABLE:
161 return "WBC_ERR_WINBIND_NOT_AVAILABLE";
162 case WBC_ERR_DOMAIN_NOT_FOUND:
163 return "WBC_ERR_DOMAIN_NOT_FOUND";
164 case WBC_ERR_INVALID_RESPONSE:
165 return "WBC_ERR_INVALID_RESPONSE";
166 case WBC_ERR_NSS_ERROR:
167 return "WBC_ERR_NSS_ERROR";
168 case WBC_ERR_UNKNOWN_USER:
169 return "WBC_ERR_UNKNOWN_USER";
170 case WBC_ERR_UNKNOWN_GROUP:
171 return "WBC_ERR_UNKNOWN_GROUP";
172 case WBC_ERR_AUTH_ERROR:
173 return "WBC_ERR_AUTH_ERROR";
174 case WBC_ERR_PWD_CHANGE_FAILED:
175 return "WBC_ERR_PWD_CHANGE_FAILED";
178 return "unknown wbcErr value";
181 #define WBC_MAGIC (0x7a2b0e1e)
182 #define WBC_MAGIC_FREE (0x875634fe)
184 struct wbcMemPrefix {
185 uint32_t magic;
186 void (*destructor)(void *ptr);
189 static size_t wbcPrefixLen(void)
191 size_t result = sizeof(struct wbcMemPrefix);
192 return (result + 15) & ~15;
195 static struct wbcMemPrefix *wbcMemToPrefix(void *ptr)
197 return (struct wbcMemPrefix *)(((char *)ptr) - wbcPrefixLen());
200 void *wbcAllocateMemory(size_t nelem, size_t elsize,
201 void (*destructor)(void *ptr))
203 struct wbcMemPrefix *result;
205 if (nelem >= (2<<24)/elsize) {
206 /* basic protection against integer wrap */
207 return NULL;
210 result = (struct wbcMemPrefix *)calloc(
211 1, nelem*elsize + wbcPrefixLen());
212 if (result == NULL) {
213 return NULL;
215 result->magic = WBC_MAGIC;
216 result->destructor = destructor;
217 return ((char *)result) + wbcPrefixLen();
220 /* Free library allocated memory */
221 void wbcFreeMemory(void *p)
223 struct wbcMemPrefix *wbcMem;
225 if (p == NULL) {
226 return;
228 wbcMem = wbcMemToPrefix(p);
229 if (wbcMem->magic != WBC_MAGIC) {
230 return;
233 /* paranoid check to ensure we don't double free */
234 wbcMem->magic = WBC_MAGIC_FREE;
236 if (wbcMem->destructor != NULL) {
237 wbcMem->destructor(p);
239 free(wbcMem);
240 return;
243 char *wbcStrDup(const char *str)
245 char *result;
246 size_t len;
248 len = strlen(str);
249 result = (char *)wbcAllocateMemory(len+1, sizeof(char), NULL);
250 if (result == NULL) {
251 return NULL;
253 memcpy(result, str, len+1);
254 return result;
257 static void wbcStringArrayDestructor(void *ptr)
259 char **p = (char **)ptr;
260 while (*p != NULL) {
261 free(*p);
262 p += 1;
266 const char **wbcAllocateStringArray(int num_strings)
268 return (const char **)wbcAllocateMemory(
269 num_strings + 1, sizeof(const char *),
270 wbcStringArrayDestructor);
273 wbcErr wbcLibraryDetails(struct wbcLibraryDetails **_details)
275 struct wbcLibraryDetails *info;
277 info = (struct wbcLibraryDetails *)wbcAllocateMemory(
278 1, sizeof(struct wbcLibraryDetails), NULL);
280 if (info == NULL) {
281 return WBC_ERR_NO_MEMORY;
284 info->major_version = WBCLIENT_MAJOR_VERSION;
285 info->minor_version = WBCLIENT_MINOR_VERSION;
286 info->vendor_version = WBCLIENT_VENDOR_VERSION;
288 *_details = info;
289 return WBC_ERR_SUCCESS;
292 /* Context handling functions */
294 static void wbcContextDestructor(void *ptr)
296 struct wbcContext *ctx = (struct wbcContext *)ptr;
298 winbindd_ctx_free(ctx->winbindd_ctx);
301 struct wbcContext *wbcCtxCreate(void)
303 struct wbcContext *ctx;
304 struct winbindd_context *wbctx;
306 ctx = (struct wbcContext *)wbcAllocateMemory(
307 1, sizeof(struct wbcContext), wbcContextDestructor);
309 if (!ctx) {
310 return NULL;
313 wbctx = winbindd_ctx_create();
315 if (!wbctx) {
316 wbcFreeMemory(ctx);
317 return NULL;
320 ctx->winbindd_ctx = wbctx;
322 return ctx;
325 void wbcCtxFree(struct wbcContext *ctx)
327 wbcFreeMemory(ctx);
330 struct wbcContext *wbcGetGlobalCtx(void)
332 return &wbcGlobalCtx;