Winbind client API
Copyright (C) Gerald (Jerry) Carter 2007
+ Copyright (C) Matthew Newton 2015
This library is free software; you can redistribute it and/or
/* Required Headers */
#include "replace.h"
-#include "talloc.h"
-#include "tevent.h"
#include "libwbclient.h"
/* From wb_common.c */
-NSS_STATUS winbindd_request_response(int req_type,
+struct winbindd_context;
+
+NSS_STATUS winbindd_request_response(struct winbindd_context *wbctx,
+ int req_type,
struct winbindd_request *request,
struct winbindd_response *response);
+NSS_STATUS winbindd_priv_request_response(struct winbindd_context *wbctx,
+ int req_type,
+ struct winbindd_request *request,
+ struct winbindd_response *response);
+struct winbindd_context *winbindd_ctx_create(void);
+void winbindd_ctx_free(struct winbindd_context *ctx);
-/** @brief Wrapper around Winbind's send/receive API call
- *
- * @param cmd Winbind command operation to perform
- * @param request Send structure
- * @param response Receive structure
- *
- * @return #wbcErr
- **/
+/* Global context used for non-Ctx functions */
+
+static struct wbcContext wbcGlobalCtx = {
+ .winbindd_ctx = NULL,
+ .pw_cache_size = 0,
+ .pw_cache_idx = 0,
+ .gr_cache_size = 0,
+ .gr_cache_idx = 0
+};
-/**********************************************************************
+/*
result == NSS_STATUS_UNAVAIL: winbind not around
result == NSS_STATUS_NOTFOUND: winbind around, but domain missing
(as far as I have seen) with the callers of is_trusted_domains.
--Volker
-**********************************************************************/
+*/
-wbcErr wbcRequestResponse(int cmd,
- struct winbindd_request *request,
- struct winbindd_response *response)
+static wbcErr wbcRequestResponseInt(
+ struct winbindd_context *wbctx,
+ int cmd,
+ struct winbindd_request *request,
+ struct winbindd_response *response,
+ NSS_STATUS (*fn)(struct winbindd_context *wbctx, int req_type,
+ struct winbindd_request *request,
+ struct winbindd_response *response))
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
NSS_STATUS nss_status;
/* for some calls the request and/or response can be NULL */
- nss_status = winbindd_request_response(cmd, request, response);
+ nss_status = fn(wbctx, cmd, request, response);
switch (nss_status) {
case NSS_STATUS_SUCCESS:
return wbc_status;
}
+/**
+ * @brief Wrapper around Winbind's send/receive API call
+ *
+ * @param ctx Context
+ * @param cmd Winbind command operation to perform
+ * @param request Send structure
+ * @param response Receive structure
+ *
+ * @return #wbcErr
+ */
+wbcErr wbcRequestResponse(struct wbcContext *ctx, int cmd,
+ struct winbindd_request *request,
+ struct winbindd_response *response)
+{
+ struct winbindd_context *wbctx = NULL;
+
+ if (ctx) {
+ wbctx = ctx->winbindd_ctx;
+ }
+
+ return wbcRequestResponseInt(wbctx, cmd, request, response,
+ winbindd_request_response);
+}
+
+wbcErr wbcRequestResponsePriv(struct wbcContext *ctx, int cmd,
+ struct winbindd_request *request,
+ struct winbindd_response *response)
+{
+ struct winbindd_context *wbctx = NULL;
+
+ if (ctx) {
+ wbctx = ctx->winbindd_ctx;
+ }
+
+ return wbcRequestResponseInt(wbctx, cmd, request, response,
+ winbindd_priv_request_response);
+}
+
/** @brief Translate an error value into a string
*
* @param error
return "unknown wbcErr value";
}
+#define WBC_MAGIC (0x7a2b0e1e)
+#define WBC_MAGIC_FREE (0x875634fe)
+
+struct wbcMemPrefix {
+ uint32_t magic;
+ void (*destructor)(void *ptr);
+};
+
+static size_t wbcPrefixLen(void)
+{
+ size_t result = sizeof(struct wbcMemPrefix);
+ return (result + 15) & ~15;
+}
+
+static struct wbcMemPrefix *wbcMemToPrefix(void *ptr)
+{
+ return (struct wbcMemPrefix *)(((char *)ptr) - wbcPrefixLen());
+}
+
+void *wbcAllocateMemory(size_t nelem, size_t elsize,
+ void (*destructor)(void *ptr))
+{
+ struct wbcMemPrefix *result;
+
+ if (nelem >= (2<<24)/elsize) {
+ /* basic protection against integer wrap */
+ return NULL;
+ }
+
+ result = (struct wbcMemPrefix *)calloc(
+ 1, nelem*elsize + wbcPrefixLen());
+ if (result == NULL) {
+ return NULL;
+ }
+ result->magic = WBC_MAGIC;
+ result->destructor = destructor;
+ return ((char *)result) + wbcPrefixLen();
+}
+
/* Free library allocated memory */
void wbcFreeMemory(void *p)
{
- if (p)
- talloc_free(p);
+ struct wbcMemPrefix *wbcMem;
+
+ if (p == NULL) {
+ return;
+ }
+ wbcMem = wbcMemToPrefix(p);
+ if (wbcMem->magic != WBC_MAGIC) {
+ return;
+ }
+ /* paranoid check to ensure we don't double free */
+ wbcMem->magic = WBC_MAGIC_FREE;
+
+ if (wbcMem->destructor != NULL) {
+ wbcMem->destructor(p);
+ }
+ free(wbcMem);
return;
}
+char *wbcStrDup(const char *str)
+{
+ char *result;
+ size_t len;
+
+ len = strlen(str);
+ result = (char *)wbcAllocateMemory(len+1, sizeof(char), NULL);
+ if (result == NULL) {
+ return NULL;
+ }
+ memcpy(result, str, len+1);
+ return result;
+}
+
+static void wbcStringArrayDestructor(void *ptr)
+{
+ char **p = (char **)ptr;
+ while (*p != NULL) {
+ free(*p);
+ p += 1;
+ }
+}
+
+const char **wbcAllocateStringArray(int num_strings)
+{
+ return (const char **)wbcAllocateMemory(
+ num_strings + 1, sizeof(const char *),
+ wbcStringArrayDestructor);
+}
+
wbcErr wbcLibraryDetails(struct wbcLibraryDetails **_details)
{
- wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
struct wbcLibraryDetails *info;
- info = talloc(NULL, struct wbcLibraryDetails);
- BAIL_ON_PTR_ERROR(info, wbc_status);
+ info = (struct wbcLibraryDetails *)wbcAllocateMemory(
+ 1, sizeof(struct wbcLibraryDetails), NULL);
+
+ if (info == NULL) {
+ return WBC_ERR_NO_MEMORY;
+ }
info->major_version = WBCLIENT_MAJOR_VERSION;
info->minor_version = WBCLIENT_MINOR_VERSION;
- info->vendor_version = talloc_strdup(info,
- WBCLIENT_VENDOR_VERSION);
- BAIL_ON_PTR_ERROR(info->vendor_version, wbc_status);
+ info->vendor_version = WBCLIENT_VENDOR_VERSION;
*_details = info;
- info = NULL;
+ return WBC_ERR_SUCCESS;
+}
- wbc_status = WBC_ERR_SUCCESS;
+/* Context handling functions */
-done:
- talloc_free(info);
- return wbc_status;
+static void wbcContextDestructor(void *ptr)
+{
+ struct wbcContext *ctx = (struct wbcContext *)ptr;
+
+ winbindd_ctx_free(ctx->winbindd_ctx);
+}
+
+struct wbcContext *wbcCtxCreate(void)
+{
+ struct wbcContext *ctx;
+ struct winbindd_context *wbctx;
+
+ ctx = (struct wbcContext *)wbcAllocateMemory(
+ 1, sizeof(struct wbcContext), wbcContextDestructor);
+
+ if (!ctx) {
+ return NULL;
+ }
+
+ wbctx = winbindd_ctx_create();
+
+ if (!wbctx) {
+ wbcFreeMemory(ctx);
+ return NULL;
+ }
+
+ ctx->winbindd_ctx = wbctx;
+
+ return ctx;
+}
+
+void wbcCtxFree(struct wbcContext *ctx)
+{
+ wbcFreeMemory(ctx);
+}
+
+struct wbcContext *wbcGetGlobalCtx(void)
+{
+ return &wbcGlobalCtx;
}