summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nsswitch/libwbclient/wbc_idmap_sssd.c138
-rw-r--r--nsswitch/libwbclient/wbc_pwd_sssd.c575
-rw-r--r--nsswitch/libwbclient/wbc_sid_sssd.c171
-rw-r--r--nsswitch/libwbclient/wbc_util_sssd.c63
-rw-r--r--nsswitch/libwbclient/wbclient_sssd.c2
5 files changed, 927 insertions, 22 deletions
diff --git a/nsswitch/libwbclient/wbc_idmap_sssd.c b/nsswitch/libwbclient/wbc_idmap_sssd.c
index d1ef7f59ca1..25fb88eb18b 100644
--- a/nsswitch/libwbclient/wbc_idmap_sssd.c
+++ b/nsswitch/libwbclient/wbc_idmap_sssd.c
@@ -20,6 +20,7 @@
*/
/* Required Headers */
+#include <sss_nss_idmap.h>
#include "replace.h"
#include "libwbclient.h"
@@ -29,13 +30,57 @@
/* Convert a Windows SID to a Unix uid, allocating an uid if needed */
wbcErr wbcSidToUid(const struct wbcDomainSid *sid, uid_t *puid)
{
- WBC_SSSD_NOT_IMPLEMENTED;
+ int ret;
+ char *sid_str;
+ uint32_t id;
+ enum sss_id_type type;
+ wbcErr wbc_status;
+
+ wbc_status = wbcSidToString(sid, &sid_str);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ return wbc_status;
+ }
+
+ ret = sss_nss_getidbysid(sid_str, &id, &type);
+ wbcFreeMemory(sid_str);
+ if (ret != 0) {
+ return WBC_ERR_UNKNOWN_FAILURE;
+ }
+
+ if (type != SSS_ID_TYPE_UID && type != SSS_ID_TYPE_BOTH) {
+ return WBC_ERR_UNKNOWN_GROUP;
+ }
+
+ *puid = (uid_t) id;
+
+ return WBC_ERR_SUCCESS;
}
/* Convert a Unix uid to a Windows SID, allocating a SID if needed */
wbcErr wbcUidToSid(uid_t uid, struct wbcDomainSid *sid)
{
- WBC_SSSD_NOT_IMPLEMENTED;
+ int ret;
+ char *str_sid;
+ enum sss_id_type type;
+ wbcErr wbc_status;
+
+ ret = sss_nss_getsidbyid(uid, &str_sid, &type);
+ if (ret != 0) {
+ return WBC_ERR_UNKNOWN_FAILURE;
+ }
+
+ if (type != SSS_ID_TYPE_UID && type != SSS_ID_TYPE_BOTH) {
+ free(str_sid);
+ return WBC_ERR_UNKNOWN_USER;
+ }
+
+ wbc_status = wbcStringToSid(str_sid, sid);
+ free(str_sid);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ return wbc_status;
+ }
+
+ return WBC_ERR_SUCCESS;
}
/** @brief Convert a Windows SID to a Unix gid, allocating a gid if needed
@@ -49,24 +94,70 @@ wbcErr wbcUidToSid(uid_t uid, struct wbcDomainSid *sid)
wbcErr wbcSidToGid(const struct wbcDomainSid *sid, gid_t *pgid)
{
- WBC_SSSD_NOT_IMPLEMENTED;
+ int ret;
+ char *sid_str;
+ uint32_t id;
+ enum sss_id_type type;
+ wbcErr wbc_status;
+
+ wbc_status = wbcSidToString(sid, &sid_str);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ return wbc_status;
+ }
+
+ ret = sss_nss_getidbysid(sid_str, &id, &type);
+ wbcFreeMemory(sid_str);
+ if (ret != 0) {
+ return WBC_ERR_UNKNOWN_FAILURE;
+ }
+
+ if (type != SSS_ID_TYPE_GID && type != SSS_ID_TYPE_BOTH) {
+ return WBC_ERR_UNKNOWN_GROUP;
+ }
+
+ *pgid = (gid_t) id;
+
+ return WBC_ERR_SUCCESS;
}
/* Convert a Unix gid to a Windows SID, allocating a SID if needed */
wbcErr wbcGidToSid(gid_t gid, struct wbcDomainSid *sid)
{
- WBC_SSSD_NOT_IMPLEMENTED;
+ int ret;
+ char *str_sid;
+ enum sss_id_type type;
+ wbcErr wbc_status;
+
+ ret = sss_nss_getsidbyid(gid, &str_sid, &type);
+ if (ret != 0) {
+ return WBC_ERR_UNKNOWN_FAILURE;
+ }
+
+ if (type != SSS_ID_TYPE_GID && type != SSS_ID_TYPE_BOTH) {
+ free(str_sid);
+ return WBC_ERR_UNKNOWN_USER;
+ }
+
+ wbc_status = wbcStringToSid(str_sid, sid);
+ free(str_sid);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ return wbc_status;
+ }
+
+ return WBC_ERR_SUCCESS;
}
/* Obtain a new uid from Winbind */
wbcErr wbcAllocateUid(uid_t *puid)
{
+ /* Not supported by SSSD */
WBC_SSSD_NOT_IMPLEMENTED;
}
/* Obtain a new gid from Winbind */
wbcErr wbcAllocateGid(gid_t *pgid)
{
+ /* Not supported by SSSD */
WBC_SSSD_NOT_IMPLEMENTED;
}
@@ -74,5 +165,42 @@ wbcErr wbcAllocateGid(gid_t *pgid)
wbcErr wbcSidsToUnixIds(const struct wbcDomainSid *sids, uint32_t num_sids,
struct wbcUnixId *ids)
{
- WBC_SSSD_NOT_IMPLEMENTED;
+ int ret;
+ char *sid_str;
+ uint32_t id;
+ enum sss_id_type type;
+ size_t c;
+ wbcErr wbc_status;
+
+ for (c = 0; c < num_sids; c++) {
+ wbc_status = wbcSidToString(&sids[c], &sid_str);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ return wbc_status;
+ }
+
+ ret = sss_nss_getidbysid(sid_str, &id, &type);
+ wbcFreeMemory(sid_str);
+ if (ret != 0) {
+ return WBC_ERR_UNKNOWN_FAILURE;
+ }
+
+ switch (type) {
+ case SSS_ID_TYPE_UID:
+ ids[c].type = WBC_ID_TYPE_UID;
+ ids[c].id.uid = (uid_t) id;
+ break;
+ case SSS_ID_TYPE_GID:
+ ids[c].type = WBC_ID_TYPE_GID;
+ ids[c].id.gid = (gid_t) id;
+ break;
+ case SSS_ID_TYPE_BOTH:
+ ids[c].type = WBC_ID_TYPE_BOTH;
+ ids[c].id.uid = (uid_t) id;
+ break;
+ default:
+ ids[c].type = WBC_ID_TYPE_NOT_SPECIFIED;
+ }
+ }
+
+ return WBC_ERR_SUCCESS;
}
diff --git a/nsswitch/libwbclient/wbc_pwd_sssd.c b/nsswitch/libwbclient/wbc_pwd_sssd.c
index 164166090e1..b44c8c3eb95 100644
--- a/nsswitch/libwbclient/wbc_pwd_sssd.c
+++ b/nsswitch/libwbclient/wbc_pwd_sssd.c
@@ -25,75 +25,586 @@
#include "../winbind_client.h"
#include "wbc_sssd_internal.h"
+#define DEFAULT_BUFSIZE 4096
+#define MAX_BUFSIZE (1024*1204)
+
+struct nss_ops_ctx {
+ void *dl_handle;
+
+ enum nss_status (*getpwnam_r)(const char *name, struct passwd *result,
+ char *buffer, size_t buflen, int *errnop);
+ enum nss_status (*getpwuid_r)(uid_t uid, struct passwd *result,
+ char *buffer, size_t buflen, int *errnop);
+ enum nss_status (*setpwent)(void);
+ enum nss_status (*getpwent_r)(struct passwd *result,
+ char *buffer, size_t buflen, int *errnop);
+ enum nss_status (*endpwent)(void);
+
+ enum nss_status (*getgrnam_r)(const char *name, struct group *result,
+ char *buffer, size_t buflen, int *errnop);
+ enum nss_status (*getgrgid_r)(gid_t gid, struct group *result,
+ char *buffer, size_t buflen, int *errnop);
+ enum nss_status (*setgrent)(void);
+ enum nss_status (*getgrent_r)(struct group *result,
+ char *buffer, size_t buflen, int *errnop);
+ enum nss_status (*endgrent)(void);
+
+ enum nss_status (*initgroups_dyn)(const char *user, gid_t group,
+ long int *start, long int *size,
+ gid_t **groups, long int limit,
+ int *errnop);
+};
+
+struct nss_ops_ctx *ctx = NULL;
+
+static bool open_libnss_sss(void)
+{
+ ctx = calloc(1, sizeof(struct nss_ops_ctx));
+ if (ctx == NULL) {
+ return false;
+ }
+
+ ctx->dl_handle = dlopen("libnss_sss.so.2", RTLD_NOW);
+ if (ctx->dl_handle == NULL) {
+ goto fail;
+ }
+
+ ctx->getpwnam_r = dlsym(ctx->dl_handle, "_nss_sss_getpwnam_r");
+ if (ctx->getpwnam_r == NULL) {
+ goto fail;
+ }
+
+ ctx->getpwuid_r = dlsym(ctx->dl_handle, "_nss_sss_getpwuid_r");
+ if (ctx->getpwuid_r == NULL) {
+ goto fail;
+ }
+
+ ctx->setpwent = dlsym(ctx->dl_handle, "_nss_sss_setpwent");
+ if (ctx->setpwent == NULL) {
+ goto fail;
+ }
+
+ ctx->getpwent_r = dlsym(ctx->dl_handle, "_nss_sss_getpwent_r");
+ if (ctx->getpwent_r == NULL) {
+ goto fail;
+ }
+
+ ctx->endpwent = dlsym(ctx->dl_handle, "_nss_sss_endpwent");
+ if (ctx->endpwent == NULL) {
+ goto fail;
+ }
+
+ ctx->getgrnam_r = dlsym(ctx->dl_handle, "_nss_sss_getgrnam_r");
+ if (ctx->getgrnam_r == NULL) {
+ goto fail;
+ }
+
+ ctx->getgrgid_r = dlsym(ctx->dl_handle, "_nss_sss_getgrgid_r");
+ if (ctx->getgrgid_r == NULL) {
+ goto fail;
+ }
+
+ ctx->setgrent = dlsym(ctx->dl_handle, "_nss_sss_setgrent");
+ if (ctx->setgrent == NULL) {
+ goto fail;
+ }
+
+ ctx->getgrent_r = dlsym(ctx->dl_handle, "_nss_sss_getgrent_r");
+ if (ctx->getgrent_r == NULL) {
+ goto fail;
+ }
+
+ ctx->endgrent = dlsym(ctx->dl_handle, "_nss_sss_endgrent");
+ if (ctx->endgrent == NULL) {
+ goto fail;
+ }
+
+ ctx->initgroups_dyn = dlsym(ctx->dl_handle, "_nss_sss_initgroups_dyn");
+ if (ctx->initgroups_dyn == NULL) {
+ goto fail;
+ }
+
+ return true;
+
+fail:
+ if (ctx->dl_handle != NULL) {
+ dlclose(ctx->dl_handle);
+ }
+
+ free(ctx);
+ ctx = NULL;
+
+ return false;
+}
+
+static void wbcPasswdDestructor(void *ptr)
+{
+ struct passwd *pw = (struct passwd *)ptr;
+ free(pw->pw_name);
+ free(pw->pw_passwd);
+ free(pw->pw_gecos);
+ free(pw->pw_shell);
+ free(pw->pw_dir);
+}
+
+static wbcErr copy_pwd(struct passwd *in, struct passwd **out)
+{
+ struct passwd *pw;
+
+ pw = (struct passwd *)wbcAllocateMemory(1, sizeof(struct passwd),
+ wbcPasswdDestructor);
+ if (pw == NULL) {
+ return WBC_ERR_NO_MEMORY;
+ }
+
+ pw->pw_name = strdup(in->pw_name);
+ if (pw->pw_name == NULL) {
+ goto fail;
+ }
+
+ pw->pw_passwd = strdup(in->pw_passwd);
+ if (pw->pw_passwd == NULL) {
+ goto fail;
+ }
+
+ pw->pw_uid = in->pw_uid;
+ pw->pw_gid = in->pw_gid;
+
+ pw->pw_gecos = strdup(in->pw_gecos);
+ if (pw->pw_gecos == NULL) {
+ goto fail;
+ }
+
+ pw->pw_shell = strdup(in->pw_shell);
+ if (pw->pw_shell == NULL) {
+ goto fail;
+ }
+
+ pw->pw_dir = strdup(in->pw_dir);
+ if (pw->pw_dir == NULL) {
+ goto fail;
+ }
+
+ *out = pw;
+ return WBC_ERR_SUCCESS;
+fail:
+ wbcFreeMemory(pw);
+
+ return WBC_ERR_NO_MEMORY;
+}
+
+static wbcErr nss_to_wbc(enum nss_status status)
+{
+ wbcErr wbc_status;
+
+ switch (status) {
+ case NSS_STATUS_SUCCESS:
+ wbc_status = WBC_ERR_SUCCESS;
+ break;
+ case NSS_STATUS_NOTFOUND:
+ wbc_status = WBC_ERR_UNKNOWN_USER;
+ break;
+ default:
+ wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ }
+
+ return wbc_status;
+}
+
/* Fill in a struct passwd* for a domain user based on username */
wbcErr wbcGetpwnam(const char *name, struct passwd **pwd)
{
- WBC_SSSD_NOT_IMPLEMENTED;
+ struct passwd lpwd = {0};
+ enum nss_status status;
+ char *buffer = NULL;
+ size_t buflen;
+ wbcErr wbc_status;
+ int nss_errno;
+
+ if (ctx == NULL && !open_libnss_sss()) {
+ return WBC_ERR_NSS_ERROR;
+ }
+
+ if (name == NULL || pwd == NULL) {
+ return WBC_ERR_INVALID_PARAM;
+ }
+
+ buflen = DEFAULT_BUFSIZE;
+ buffer = malloc(buflen);
+ if (buffer == NULL) {
+ return WBC_ERR_NO_MEMORY;
+ }
+
+ status = ctx->getpwnam_r(name, &lpwd, buffer, buflen, &nss_errno);
+ wbc_status = nss_to_wbc(status);
+ if (WBC_ERROR_IS_OK(wbc_status)) {
+ wbc_status = copy_pwd(&lpwd, pwd);
+ }
+
+ free(buffer);
+
+ return wbc_status;
}
/* Fill in a struct passwd* for a domain user based on uid */
wbcErr wbcGetpwuid(uid_t uid, struct passwd **pwd)
{
- WBC_SSSD_NOT_IMPLEMENTED;
+ struct passwd lpwd = {0};
+ enum nss_status status;
+ char *buffer = NULL;
+ size_t buflen;
+ wbcErr wbc_status;
+ int nss_errno;
+
+ if (ctx == NULL && !open_libnss_sss()) {
+ return WBC_ERR_NSS_ERROR;
+ }
+
+ if (pwd == NULL) {
+ return WBC_ERR_INVALID_PARAM;
+ }
+
+ buflen = DEFAULT_BUFSIZE;
+ buffer = malloc(buflen);
+ if (buffer == NULL) {
+ return WBC_ERR_NO_MEMORY;
+ }
+
+ status = ctx->getpwuid_r(uid, &lpwd, buffer, buflen, &nss_errno);
+ wbc_status = nss_to_wbc(status);
+ if (WBC_ERROR_IS_OK(wbc_status)) {
+ wbc_status = copy_pwd(&lpwd, pwd);
+ }
+
+ free(buffer);
+
+ return wbc_status;
}
/* Fill in a struct passwd* for a domain user based on sid */
wbcErr wbcGetpwsid(struct wbcDomainSid *sid, struct passwd **pwd)
{
- WBC_SSSD_NOT_IMPLEMENTED;
+ wbcErr wbc_status;
+ uid_t uid;
+
+ wbc_status = wbcSidToUid(sid, &uid);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ return wbc_status;
+ }
+
+ wbc_status = wbcGetpwuid(uid, pwd);
+
+ return wbc_status;
+
+}
+
+static void wbcGroupDestructor(void *ptr)
+{
+ struct group *gr = (struct group *)ptr;
+ size_t c;
+
+ free(gr->gr_name);
+ free(gr->gr_passwd);
+
+ /* if the array was partly created this can be NULL */
+ if (gr->gr_mem == NULL) {
+ return;
+ }
+
+ for (c=0; gr->gr_mem[c] != NULL; c++) {
+ free(gr->gr_mem[c]);
+ }
+ free(gr->gr_mem);
}
+static wbcErr copy_grp(struct group *in, struct group **out)
+{
+ struct group *gr;
+ size_t members;
+ size_t c;
+
+ gr = (struct group *)wbcAllocateMemory(1, sizeof(struct group),
+ wbcGroupDestructor);
+ if (gr == NULL) {
+ return WBC_ERR_NO_MEMORY;
+ }
+
+ gr->gr_name = strdup(in->gr_name);
+ if (gr->gr_name == NULL) {
+ goto fail;
+ }
+
+ gr->gr_passwd = strdup(in->gr_passwd);
+ if (gr->gr_passwd == NULL) {
+ goto fail;
+ }
+
+ gr->gr_gid = in->gr_gid;
+
+ for (members = 0; in->gr_mem[members] != NULL; members++);
+
+ if (members > 0) {
+ gr->gr_mem = (char **)calloc(members+1, sizeof(char *));
+ if (gr->gr_mem == NULL) {
+ goto fail;
+ }
+
+ for (c = 0; c < members; c++) {
+ gr->gr_mem[c] = strdup(in->gr_mem[c]);
+ if (gr->gr_mem[c] == NULL) {
+ goto fail;
+ }
+ }
+ }
+
+ *out = gr;
+ return WBC_ERR_SUCCESS;
+fail:
+ wbcFreeMemory(gr);
+
+ return WBC_ERR_NO_MEMORY;
+}
/* Fill in a struct passwd* for a domain user based on username */
wbcErr wbcGetgrnam(const char *name, struct group **grp)
{
- WBC_SSSD_NOT_IMPLEMENTED;
+ struct group lgrp;
+ enum nss_status status;
+ char *newbuffer = NULL;
+ char *buffer = NULL;
+ size_t buflen = 0;
+ wbcErr wbc_status;
+ int nss_errno;
+
+ if (ctx == NULL && !open_libnss_sss()) {
+ return WBC_ERR_NSS_ERROR;
+ }
+
+ if (name == NULL || grp == NULL) {
+ return WBC_ERR_INVALID_PARAM;
+ }
+
+ do {
+ if (buflen == 0) {
+ buflen = DEFAULT_BUFSIZE;
+ } else {
+ buflen *= 2;
+ }
+ newbuffer = realloc(buffer, buflen);
+ if (newbuffer == NULL) {
+ free(buffer);
+ return WBC_ERR_NO_MEMORY;
+ }
+ buffer = newbuffer;
+
+ memset(grp, 0, sizeof(struct group));
+ status = ctx->getgrnam_r(name, &lgrp, buffer, buflen, &nss_errno);
+ wbc_status = nss_to_wbc(status);
+ if (WBC_ERROR_IS_OK(wbc_status)) {
+ wbc_status = copy_grp(&lgrp, grp);
+ }
+ } while (status == NSS_STATUS_TRYAGAIN && nss_errno == ERANGE \
+ && buflen < MAX_BUFSIZE);
+
+ free(buffer);
+
+ return wbc_status;
}
/* Fill in a struct passwd* for a domain user based on uid */
wbcErr wbcGetgrgid(gid_t gid, struct group **grp)
{
- WBC_SSSD_NOT_IMPLEMENTED;
+ struct group lgrp;
+ enum nss_status status;
+ char *newbuffer = NULL;
+ char *buffer = NULL;
+ size_t buflen = 0;
+ wbcErr wbc_status;
+ int nss_errno;
+
+ if (ctx == NULL && !open_libnss_sss()) {
+ return WBC_ERR_NSS_ERROR;
+ }
+
+ if (grp == NULL) {
+ return WBC_ERR_INVALID_PARAM;
+ }
+
+ do {
+ if (buflen == 0) {
+ buflen = DEFAULT_BUFSIZE;
+ } else {
+ buflen *= 2;
+ }
+ newbuffer = realloc(buffer, buflen);
+ if (newbuffer == NULL) {
+ free(buffer);
+ return WBC_ERR_NO_MEMORY;
+ }
+ buffer = newbuffer;
+
+ memset(grp, 0, sizeof(struct group));
+ status = ctx->getgrgid_r(gid, &lgrp, buffer, buflen, &nss_errno);
+ wbc_status = nss_to_wbc(status);
+ if (WBC_ERROR_IS_OK(wbc_status)) {
+ wbc_status = copy_grp(&lgrp, grp);
+ }
+ } while (status == NSS_STATUS_TRYAGAIN && nss_errno == ERANGE \
+ && buflen < MAX_BUFSIZE);
+
+ free(buffer);
+
+ return wbc_status;
}
/* Reset the passwd iterator */
wbcErr wbcSetpwent(void)
{
- WBC_SSSD_NOT_IMPLEMENTED;
+ enum nss_status status;
+ wbcErr wbc_status;
+
+ if (ctx == NULL && !open_libnss_sss()) {
+ return WBC_ERR_NSS_ERROR;
+ }
+
+ status = ctx->setpwent();
+ wbc_status = nss_to_wbc(status);
+
+ return wbc_status;
}
/* Close the passwd iterator */
wbcErr wbcEndpwent(void)
{
- WBC_SSSD_NOT_IMPLEMENTED;
+ enum nss_status status;
+ wbcErr wbc_status;
+
+ if (ctx == NULL && !open_libnss_sss()) {
+ return WBC_ERR_NSS_ERROR;
+ }
+
+ status = ctx->endpwent();
+ wbc_status = nss_to_wbc(status);
+
+ return wbc_status;
}
/* Return the next struct passwd* entry from the pwent iterator */
wbcErr wbcGetpwent(struct passwd **pwd)
{
- WBC_SSSD_NOT_IMPLEMENTED;
+ struct passwd lpwd = {0};
+ enum nss_status status;
+ char *buffer = NULL;
+ size_t buflen;
+ wbcErr wbc_status;
+ int nss_errno;
+
+ if (ctx == NULL && !open_libnss_sss()) {
+ return WBC_ERR_NSS_ERROR;
+ }
+
+ if (pwd == NULL) {
+ return WBC_ERR_INVALID_PARAM;
+ }
+
+ buflen = DEFAULT_BUFSIZE;
+ buffer = malloc(buflen);
+ if (buffer == NULL) {
+ return WBC_ERR_NO_MEMORY;
+ }
+
+ status = ctx->getpwent_r(&lpwd, buffer, buflen, &nss_errno);
+ wbc_status = nss_to_wbc(status);
+ if (WBC_ERROR_IS_OK(wbc_status)) {
+ wbc_status = copy_pwd(&lpwd, pwd);
+ }
+
+ free(buffer);
+
+ return wbc_status;
}
/* Reset the group iterator */
wbcErr wbcSetgrent(void)
{
- WBC_SSSD_NOT_IMPLEMENTED;
+ enum nss_status status;
+ wbcErr wbc_status;
+
+ if (ctx == NULL && !open_libnss_sss()) {
+ return WBC_ERR_NSS_ERROR;
+ }
+
+ status = ctx->setgrent();
+ wbc_status = nss_to_wbc(status);
+
+ return wbc_status;
}
/* Close the group iterator */
wbcErr wbcEndgrent(void)
{
- WBC_SSSD_NOT_IMPLEMENTED;
+ enum nss_status status;
+ wbcErr wbc_status;
+
+ if (ctx == NULL && !open_libnss_sss()) {
+ return WBC_ERR_NSS_ERROR;
+ }
+
+ status = ctx->endgrent();
+ wbc_status = nss_to_wbc(status);
+
+ return wbc_status;
}
/* Return the next struct group* entry from the pwent iterator */
wbcErr wbcGetgrent(struct group **grp)
{
- WBC_SSSD_NOT_IMPLEMENTED;
+ struct group lgrp;
+ enum nss_status status;
+ char *newbuffer = NULL;
+ char *buffer = NULL;
+ size_t buflen = 0;
+ wbcErr wbc_status;
+ int nss_errno;
+
+ if (ctx == NULL && !open_libnss_sss()) {
+ return WBC_ERR_NSS_ERROR;
+ }
+
+ if (grp == NULL) {
+ return WBC_ERR_INVALID_PARAM;
+ }
+
+ do {
+ if (buflen == 0) {
+ buflen = DEFAULT_BUFSIZE;
+ } else {
+ buflen *= 2;
+ }
+ newbuffer = realloc(buffer, buflen);
+ if (newbuffer == NULL) {
+ free(buffer);
+ return WBC_ERR_NO_MEMORY;
+ }
+ buffer = newbuffer;
+
+ memset(grp, 0, sizeof(struct group));
+ status = ctx->getgrent_r(&lgrp, buffer, buflen, &nss_errno);
+ wbc_status = nss_to_wbc(status);
+ if (WBC_ERROR_IS_OK(wbc_status)) {
+ wbc_status = copy_grp(&lgrp, grp);
+ }
+ } while (status == NSS_STATUS_TRYAGAIN && nss_errno == ERANGE \
+ && buflen < MAX_BUFSIZE);
+
+ free(buffer);
+
+ return wbc_status;
}
/* Return the next struct group* entry from the pwent iterator */
wbcErr wbcGetgrlist(struct group **grp)
{
+ /* Not used anywhere */
WBC_SSSD_NOT_IMPLEMENTED;
}
@@ -102,5 +613,45 @@ wbcErr wbcGetGroups(const char *account,
uint32_t *num_groups,
gid_t **_groups)
{
- WBC_SSSD_NOT_IMPLEMENTED;
+ wbcErr wbc_status;
+ enum nss_status status;
+ struct passwd *pwd;
+ long int gr_size = 0;
+ long int start = 0;
+ gid_t *gids = NULL;
+ int nss_errno;
+
+ wbc_status = wbcGetpwnam(account, &pwd);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ return wbc_status;
+ }
+
+ gr_size = DEFAULT_BUFSIZE;
+ gids = calloc(gr_size, sizeof(gid_t));
+ if (gids == NULL) {
+ wbc_status = WBC_ERR_NO_MEMORY;
+ goto done;
+ }
+
+ /* nss modules may skip the primary group when we pass it in so always
+ * add it in advance */
+ gids[0] = pwd->pw_gid;
+ start++;
+
+ status = ctx->initgroups_dyn(pwd->pw_name, pwd->pw_gid, &start,
+ &gr_size, &gids, -1, &nss_errno);
+ wbc_status = nss_to_wbc(status);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ goto done;
+ }
+
+ *_groups = gids;
+ *num_groups = start;
+
+ wbc_status = WBC_ERR_SUCCESS;
+
+done:
+ wbcFreeMemory(pwd);
+
+ return wbc_status;
}
diff --git a/nsswitch/libwbclient/wbc_sid_sssd.c b/nsswitch/libwbclient/wbc_sid_sssd.c
index 4826f295fb7..28d181c5664 100644
--- a/nsswitch/libwbclient/wbc_sid_sssd.c
+++ b/nsswitch/libwbclient/wbc_sid_sssd.c
@@ -21,18 +21,69 @@
/* Required Headers */
+#include <sss_nss_idmap.h>
+
#include "replace.h"
#include "libwbclient.h"
#include "../winbind_client.h"
#include "wbc_sssd_internal.h"
+static int sss_id_type_to_wbcSidType(enum sss_id_type sss_type,
+ enum wbcSidType *name_type)
+{
+ switch (sss_type) {
+ case SSS_ID_TYPE_NOT_SPECIFIED:
+ *name_type = WBC_SID_NAME_USE_NONE;
+ break;
+ case SSS_ID_TYPE_UID:
+ case SSS_ID_TYPE_BOTH:
+ *name_type = WBC_SID_NAME_USER;
+ break;
+ case SSS_ID_TYPE_GID:
+ *name_type = WBC_SID_NAME_DOM_GRP;
+ break;
+ default:
+ return EINVAL;
+ }
+
+ return 0;
+};
+
/* Convert a domain and name to SID */
wbcErr wbcLookupName(const char *domain,
const char *name,
struct wbcDomainSid *sid,
enum wbcSidType *name_type)
{
- WBC_SSSD_NOT_IMPLEMENTED;
+ char *fq_name = NULL;
+ char *str_sid;
+ enum sss_id_type type;
+ int ret;
+ wbcErr wbc_status;
+
+ ret = asprintf(&fq_name, "%s@%s", name, domain);
+ if (ret == -1) {
+ return WBC_ERR_NO_MEMORY;
+ }
+
+ ret = sss_nss_getsidbyname(fq_name, &str_sid, &type);
+ free(fq_name);
+ if (ret != 0) {
+ return WBC_ERR_UNKNOWN_FAILURE;
+ }
+
+ ret = sss_id_type_to_wbcSidType(type, name_type);
+ if (ret != 0) {
+ return WBC_ERR_UNKNOWN_FAILURE;
+ }
+
+ wbc_status = wbcStringToSid(str_sid, sid);
+ free(str_sid);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ return wbc_status;
+ }
+
+ return WBC_ERR_SUCCESS;
}
@@ -42,7 +93,55 @@ wbcErr wbcLookupSid(const struct wbcDomainSid *sid,
char **pname,
enum wbcSidType *pname_type)
{
- WBC_SSSD_NOT_IMPLEMENTED;
+ char *str_sid;
+ char *fq_name = NULL;
+ enum sss_id_type type;
+ int ret;
+ char *p;
+ wbcErr wbc_status;
+
+ wbc_status = wbcSidToString(sid, &str_sid);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ return wbc_status;
+ }
+
+ ret = sss_nss_getnamebysid(str_sid, &fq_name, &type);
+ wbcFreeMemory(str_sid);
+ if (ret != 0) {
+ return WBC_ERR_UNKNOWN_FAILURE;
+ }
+
+ ret = sss_id_type_to_wbcSidType(type, pname_type);
+ if (ret != 0) {
+ wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ goto done;
+ }
+
+ /* FIXME: it would be nice to have a sss_nss_getnamebysid() call which
+ * return name and domain separately. */
+ p = strchr(fq_name, '@');
+ if (p == NULL) {
+ wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ goto done;
+ }
+
+ *p = '\0';
+ *pname = wbcStrDup(fq_name);
+ if (*pname == NULL) {
+ wbc_status = WBC_ERR_NO_MEMORY;
+ goto done;
+ }
+
+ *pdomain = wbcStrDup(p + 1);
+ if (*pdomain == NULL) {
+ wbc_status = WBC_ERR_NO_MEMORY;
+ goto done;
+ }
+
+ wbc_status = WBC_ERR_SUCCESS;
+done:
+ free(fq_name);
+ return wbc_status;
}
wbcErr wbcLookupSids(const struct wbcDomainSid *sids, int num_sids,
@@ -61,7 +160,73 @@ wbcErr wbcLookupRids(struct wbcDomainSid *dom_sid,
const char ***pnames,
enum wbcSidType **ptypes)
{
- WBC_SSSD_NOT_IMPLEMENTED;
+ struct wbcDomainSid obj_sid;
+ size_t c;
+ wbcErr err;
+ char *domain;
+ char *name;
+ enum wbcSidType type;
+ const char **names = NULL;
+ enum wbcSidType *types = NULL;
+
+ memset(&obj_sid, 0, sizeof(obj_sid));
+
+ obj_sid.sid_rev_num = dom_sid->sid_rev_num;
+ obj_sid.num_auths = dom_sid->num_auths + 1;
+ for (c = 0; c < 6; c++) {
+ obj_sid.id_auth[c] = dom_sid->id_auth[c];
+ }
+ for (c = 0; c < WBC_MAXSUBAUTHS; c++) {
+ obj_sid.sub_auths[c] = dom_sid->sub_auths[c];
+ }
+
+ names = wbcAllocateStringArray(num_rids + 1);
+ if (names == NULL) {
+ err = WBC_ERR_NO_MEMORY;
+ goto done;
+ }
+
+ types = wbcAllocateMemory(num_rids + 1, sizeof(enum wbcSidType), NULL);
+ if (types == NULL) {
+ err = WBC_ERR_NO_MEMORY;
+ goto done;
+ }
+
+ for (c = 0; c < num_rids; c++) {
+ obj_sid.sub_auths[obj_sid.num_auths - 1] = rids[c];
+
+ err = wbcLookupSid(&obj_sid, &domain, &name, &type);
+ if (err != WBC_ERR_SUCCESS) {
+ goto done;
+ }
+
+ names[c] = strdup(name);
+ wbcFreeMemory(name);
+ if (names[c] == NULL) {
+ err = WBC_ERR_NO_MEMORY;
+ goto done;
+ }
+ types[c] = type;
+
+ if (c == 0) {
+ *pp_domain_name = domain;
+ } else {
+ wbcFreeMemory(domain);
+ }
+ }
+
+ *pnames = names;
+ *ptypes = types;
+
+ err = WBC_ERR_SUCCESS;
+
+done:
+ if (err != WBC_ERR_SUCCESS) {
+ wbcFreeMemory(types);
+ wbcFreeMemory(names);
+ }
+
+ return err;
}
/* Get the groups a user belongs to */
diff --git a/nsswitch/libwbclient/wbc_util_sssd.c b/nsswitch/libwbclient/wbc_util_sssd.c
index d1049e239b3..50edc072bc3 100644
--- a/nsswitch/libwbclient/wbc_util_sssd.c
+++ b/nsswitch/libwbclient/wbc_util_sssd.c
@@ -25,13 +25,26 @@
#include "../winbind_client.h"
#include "wbc_sssd_internal.h"
+/* For WINBIND_INTERFACE_VERSION */
+#include "../winbind_struct_protocol.h"
+
/** @brief Ping winbindd to see if the daemon is running
*
* @return #wbcErr
**/
wbcErr wbcPing(void)
{
- WBC_SSSD_NOT_IMPLEMENTED;
+ /* TODO: add real check */
+ return WBC_ERR_SUCCESS;
+}
+
+static void wbcInterfaceDetailsDestructor(void *ptr)
+{
+ struct wbcInterfaceDetails *i = (struct wbcInterfaceDetails *)ptr;
+ free(i->winbind_version);
+ free(i->netbios_name);
+ free(i->netbios_domain);
+ free(i->dns_domain);
}
/**
@@ -44,7 +57,51 @@ wbcErr wbcPing(void)
wbcErr wbcInterfaceDetails(struct wbcInterfaceDetails **_details)
{
- WBC_SSSD_NOT_IMPLEMENTED;
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ struct wbcInterfaceDetails *info;
+ info = (struct wbcInterfaceDetails *)wbcAllocateMemory(
+ 1, sizeof(struct wbcInterfaceDetails),
+ wbcInterfaceDetailsDestructor);
+ if (info == NULL) {
+ return WBC_ERR_NO_MEMORY;
+ }
+
+ /* TODO: currently this call just returns a suitable winbind_separator
+ * for wbinfo. */
+
+ info->interface_version = WINBIND_INTERFACE_VERSION;
+ info->winbind_version = strdup("libwbclient for SSSD");
+ if (info->winbind_version == NULL) {
+ wbc_status = WBC_ERR_NO_MEMORY;
+ goto done;
+ }
+
+ info->winbind_separator = '\\';
+
+ info->netbios_name = strdup("-not available-");
+ if (info->netbios_name == NULL) {
+ wbc_status = WBC_ERR_NO_MEMORY;
+ goto done;
+ }
+
+ info->netbios_domain = strdup("-not available-");
+ if (info->netbios_domain == NULL) {
+ wbc_status = WBC_ERR_NO_MEMORY;
+ goto done;
+ }
+
+ info->dns_domain = strdup("-not available-");
+ if (info->dns_domain == NULL) {
+ wbc_status = WBC_ERR_NO_MEMORY;
+ goto done;
+ }
+
+ *_details = info;
+ info = NULL;
+ wbc_status = WBC_ERR_SUCCESS;
+done:
+ wbcFreeMemory(info);
+ return wbc_status;
}
/** @brief Lookup the current status of a trusted domain, sync wrapper
@@ -70,12 +127,14 @@ wbcErr wbcDcInfo(const char *domain, size_t *num_dcs,
/* Resolve a NetbiosName via WINS */
wbcErr wbcResolveWinsByName(const char *name, char **ip)
{
+ /* SSSD does not support WINS */
WBC_SSSD_NOT_IMPLEMENTED;
}
/* Resolve an IP address via WINS into a NetbiosName */
wbcErr wbcResolveWinsByIP(const char *ip, char **name)
{
+ /* SSSD does not support WINS */
WBC_SSSD_NOT_IMPLEMENTED;
}
diff --git a/nsswitch/libwbclient/wbclient_sssd.c b/nsswitch/libwbclient/wbclient_sssd.c
index 2c975f5bcfe..256eac8ad7c 100644
--- a/nsswitch/libwbclient/wbclient_sssd.c
+++ b/nsswitch/libwbclient/wbclient_sssd.c
@@ -28,6 +28,7 @@ wbcErr wbcRequestResponse(int cmd,
struct winbindd_request *request,
struct winbindd_response *response)
{
+ /* Helper to make API check happy */
WBC_SSSD_NOT_IMPLEMENTED;
}
@@ -35,5 +36,6 @@ wbcErr wbcRequestResponsePriv(int cmd,
struct winbindd_request *request,
struct winbindd_response *response)
{
+ /* Helper to make API check happy */
WBC_SSSD_NOT_IMPLEMENTED;
}