wmi-1.3.16 from opsview.com
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
|
||||
This test code requires a tdb that is configured for to use the asq module.
|
||||
You can do that adding the following record to a tdb:
|
||||
|
||||
dn: @MODULES
|
||||
@LIST: asq
|
||||
|
||||
Other modules can be used as well (like rdn_name for example)
|
||||
|
||||
The uidNumber 0 and the gidNumber 0 are considered invalid.
|
||||
|
||||
The user records should contain the followin attributes:
|
||||
uid (required) the user name
|
||||
userPassword (optional) the user password (if not present "LDB" is
|
||||
returned in the password field)
|
||||
uidNumber (required) the user uid
|
||||
gidNumber (required) the user primary gid
|
||||
gecos (optional) the GECOS
|
||||
homeDirectory (required) the home directory
|
||||
loginShell (required) the login shell
|
||||
memberOf (required) all the groups the user is member of should
|
||||
be reported here using their DNs. The
|
||||
primary group as well.
|
||||
|
||||
The group accounts should contain the following attributes:
|
||||
cn (required) the group name
|
||||
uesrPassword (optional) the group password (if not present "LDB" is
|
||||
returned in the password field)
|
||||
gidNumber (required) the group gid
|
||||
member (optional) the DNs of the member users, also the ones
|
||||
that have this group as primary
|
||||
|
||||
|
||||
SSS
|
||||
@@ -0,0 +1,427 @@
|
||||
/*
|
||||
LDB nsswitch module
|
||||
|
||||
Copyright (C) Simo Sorce 2006
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "ldb-nss.h"
|
||||
|
||||
extern struct _ldb_nss_context *_ldb_nss_ctx;
|
||||
|
||||
const char *_ldb_nss_gr_attrs[] = {
|
||||
"cn",
|
||||
"userPassword",
|
||||
"gidNumber",
|
||||
NULL
|
||||
};
|
||||
|
||||
const char *_ldb_nss_mem_attrs[] = {
|
||||
"uid",
|
||||
NULL
|
||||
};
|
||||
|
||||
#define _NSS_LDB_ENOMEM(amem) \
|
||||
do { \
|
||||
if ( ! amem) { \
|
||||
errno = ENOMEM; \
|
||||
talloc_free(memctx); \
|
||||
return NSS_STATUS_UNAVAIL; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/* This setgrent, getgrent, endgrent is not very efficient */
|
||||
|
||||
NSS_STATUS _nss_ldb_setgrent(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = _ldb_nss_init();
|
||||
if (ret != NSS_STATUS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
_ldb_nss_ctx->gr_cur = 0;
|
||||
if (_ldb_nss_ctx->gr_res != NULL) {
|
||||
talloc_free(_ldb_nss_ctx->gr_res);
|
||||
_ldb_nss_ctx->gr_res = NULL;
|
||||
}
|
||||
|
||||
ret = ldb_search(_ldb_nss_ctx->ldb,
|
||||
_ldb_nss_ctx->base,
|
||||
LDB_SCOPE_SUBTREE,
|
||||
_LDB_NSS_GRENT_FILTER,
|
||||
_ldb_nss_gr_attrs,
|
||||
&_ldb_nss_ctx->gr_res);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
return NSS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NSS_STATUS _nss_ldb_endgrent(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = _ldb_nss_init();
|
||||
if (ret != NSS_STATUS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
_ldb_nss_ctx->gr_cur = 0;
|
||||
if (_ldb_nss_ctx->gr_res) {
|
||||
talloc_free(_ldb_nss_ctx->gr_res);
|
||||
_ldb_nss_ctx->gr_res = NULL;
|
||||
}
|
||||
|
||||
return NSS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NSS_STATUS _nss_ldb_getgrent_r(struct group *result_buf, char *buffer, size_t buflen, int *errnop)
|
||||
{
|
||||
int ret;
|
||||
struct ldb_result *res;
|
||||
|
||||
ret = _ldb_nss_init();
|
||||
if (ret != NSS_STATUS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
*errnop = 0;
|
||||
|
||||
if (_ldb_nss_ctx->gr_cur >= _ldb_nss_ctx->gr_res->count) {
|
||||
/* already returned all entries */
|
||||
return NSS_STATUS_NOTFOUND;
|
||||
}
|
||||
|
||||
res = talloc_zero(_ldb_nss_ctx->gr_res, struct ldb_result);
|
||||
if ( ! res) {
|
||||
errno = *errnop = ENOMEM;
|
||||
_ldb_nss_ctx->gr_cur++; /* skip this entry */
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
ret = _ldb_nss_group_request(&res,
|
||||
_ldb_nss_ctx->gr_res->msgs[_ldb_nss_ctx->gr_cur]->dn,
|
||||
_ldb_nss_mem_attrs,
|
||||
"member");
|
||||
|
||||
if (ret != NSS_STATUS_SUCCESS) {
|
||||
*errnop = errno;
|
||||
talloc_free(res);
|
||||
_ldb_nss_ctx->gr_cur++; /* skip this entry */
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = _ldb_nss_fill_group(result_buf,
|
||||
buffer,
|
||||
buflen,
|
||||
errnop,
|
||||
_ldb_nss_ctx->gr_res->msgs[_ldb_nss_ctx->gr_cur],
|
||||
res);
|
||||
|
||||
talloc_free(res);
|
||||
|
||||
if (ret != NSS_STATUS_SUCCESS) {
|
||||
if (ret != NSS_STATUS_TRYAGAIN) {
|
||||
_ldb_nss_ctx->gr_cur++; /* skip this entry */
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* this entry is ok, increment counter to nex entry */
|
||||
_ldb_nss_ctx->gr_cur++;
|
||||
|
||||
return NSS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NSS_STATUS _nss_ldb_getgrnam_r(const char *name, struct group *result_buf, char *buffer, size_t buflen, int *errnop)
|
||||
{
|
||||
int ret;
|
||||
char *filter;
|
||||
TALLOC_CTX *ctx;
|
||||
struct ldb_result *gr_res;
|
||||
struct ldb_result *mem_res;
|
||||
|
||||
ret = _ldb_nss_init();
|
||||
if (ret != NSS_STATUS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx = talloc_new(_ldb_nss_ctx->ldb);
|
||||
if ( ! ctx) {
|
||||
*errnop = errno = ENOMEM;
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
/* build the filter for this uid */
|
||||
filter = talloc_asprintf(ctx, _LDB_NSS_GRNAM_FILTER, name);
|
||||
if (filter == NULL) {
|
||||
/* this is a fatal error */
|
||||
*errnop = errno = ENOMEM;
|
||||
ret = NSS_STATUS_UNAVAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* search the entry */
|
||||
ret = ldb_search(_ldb_nss_ctx->ldb,
|
||||
_ldb_nss_ctx->base,
|
||||
LDB_SCOPE_SUBTREE,
|
||||
filter,
|
||||
_ldb_nss_gr_attrs,
|
||||
&gr_res);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
/* this is a fatal error */
|
||||
*errnop = errno = ENOENT;
|
||||
ret = NSS_STATUS_UNAVAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
talloc_steal(ctx, gr_res);
|
||||
|
||||
/* if none found return */
|
||||
if (gr_res->count == 0) {
|
||||
*errnop = errno = ENOENT;
|
||||
ret = NSS_STATUS_NOTFOUND;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (gr_res->count != 1) {
|
||||
/* this is a fatal error */
|
||||
*errnop = errno = ENOENT;
|
||||
ret = NSS_STATUS_UNAVAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
mem_res = talloc_zero(ctx, struct ldb_result);
|
||||
if ( ! mem_res) {
|
||||
errno = *errnop = ENOMEM;
|
||||
ret = NSS_STATUS_UNAVAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = _ldb_nss_group_request(&mem_res,
|
||||
gr_res->msgs[0]->dn,
|
||||
_ldb_nss_mem_attrs,
|
||||
"member");
|
||||
|
||||
if (ret != NSS_STATUS_SUCCESS) {
|
||||
*errnop = errno;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = _ldb_nss_fill_group(result_buf,
|
||||
buffer,
|
||||
buflen,
|
||||
errnop,
|
||||
gr_res->msgs[0],
|
||||
mem_res);
|
||||
|
||||
if (ret != NSS_STATUS_SUCCESS) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = NSS_STATUS_SUCCESS;
|
||||
done:
|
||||
talloc_free(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
NSS_STATUS _nss_ldb_getgrgid_r(gid_t gid, struct group *result_buf, char *buffer, size_t buflen, int *errnop)
|
||||
{
|
||||
int ret;
|
||||
char *filter;
|
||||
TALLOC_CTX *ctx;
|
||||
struct ldb_result *gr_res;
|
||||
struct ldb_result *mem_res;
|
||||
|
||||
if (gid == 0) { /* we don't serve root gid by policy */
|
||||
*errnop = errno = ENOENT;
|
||||
return NSS_STATUS_NOTFOUND;
|
||||
}
|
||||
|
||||
ret = _ldb_nss_init();
|
||||
if (ret != NSS_STATUS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx = talloc_new(_ldb_nss_ctx->ldb);
|
||||
if ( ! ctx) {
|
||||
*errnop = errno = ENOMEM;
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
/* build the filter for this uid */
|
||||
filter = talloc_asprintf(ctx, _LDB_NSS_GRGID_FILTER, gid);
|
||||
if (filter == NULL) {
|
||||
/* this is a fatal error */
|
||||
*errnop = errno = ENOMEM;
|
||||
ret = NSS_STATUS_UNAVAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* search the entry */
|
||||
ret = ldb_search(_ldb_nss_ctx->ldb,
|
||||
_ldb_nss_ctx->base,
|
||||
LDB_SCOPE_SUBTREE,
|
||||
filter,
|
||||
_ldb_nss_gr_attrs,
|
||||
&gr_res);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
/* this is a fatal error */
|
||||
*errnop = errno = ENOENT;
|
||||
ret = NSS_STATUS_UNAVAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
talloc_steal(ctx, gr_res);
|
||||
|
||||
/* if none found return */
|
||||
if (gr_res->count == 0) {
|
||||
*errnop = errno = ENOENT;
|
||||
ret = NSS_STATUS_NOTFOUND;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (gr_res->count != 1) {
|
||||
/* this is a fatal error */
|
||||
*errnop = errno = ENOENT;
|
||||
ret = NSS_STATUS_UNAVAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
mem_res = talloc_zero(ctx, struct ldb_result);
|
||||
if ( ! mem_res) {
|
||||
errno = *errnop = ENOMEM;
|
||||
ret = NSS_STATUS_UNAVAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = _ldb_nss_group_request(&mem_res,
|
||||
gr_res->msgs[0]->dn,
|
||||
_ldb_nss_mem_attrs,
|
||||
"member");
|
||||
|
||||
if (ret != NSS_STATUS_SUCCESS) {
|
||||
*errnop = errno;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = _ldb_nss_fill_group(result_buf,
|
||||
buffer,
|
||||
buflen,
|
||||
errnop,
|
||||
gr_res->msgs[0],
|
||||
mem_res);
|
||||
|
||||
if (ret != NSS_STATUS_SUCCESS) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = NSS_STATUS_SUCCESS;
|
||||
done:
|
||||
talloc_free(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
NSS_STATUS _nss_ldb_initgroups_dyn(const char *user, gid_t group, long int *start, long int *size, gid_t **groups, long int limit, int *errnop)
|
||||
{
|
||||
int ret;
|
||||
char *filter;
|
||||
const char * attrs[] = { "uidNumber", "gidNumber", NULL };
|
||||
struct ldb_result *uid_res;
|
||||
struct ldb_result *mem_res;
|
||||
|
||||
ret = _ldb_nss_init();
|
||||
if (ret != NSS_STATUS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
mem_res = talloc_zero(_ldb_nss_ctx, struct ldb_result);
|
||||
if ( ! mem_res) {
|
||||
errno = *errnop = ENOMEM;
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
/* build the filter for this name */
|
||||
filter = talloc_asprintf(mem_res, _LDB_NSS_PWNAM_FILTER, user);
|
||||
if (filter == NULL) {
|
||||
/* this is a fatal error */
|
||||
*errnop = errno = ENOENT;
|
||||
ret = NSS_STATUS_UNAVAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* search the entry */
|
||||
ret = ldb_search(_ldb_nss_ctx->ldb,
|
||||
_ldb_nss_ctx->base,
|
||||
LDB_SCOPE_SUBTREE,
|
||||
filter,
|
||||
attrs,
|
||||
&uid_res);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
/* this is a fatal error */
|
||||
*errnop = errno = ENOENT;
|
||||
ret = NSS_STATUS_UNAVAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
talloc_steal(mem_res, uid_res);
|
||||
|
||||
/* if none found return */
|
||||
if (uid_res->count == 0) {
|
||||
*errnop = errno = ENOENT;
|
||||
ret = NSS_STATUS_NOTFOUND;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (uid_res->count != 1) {
|
||||
/* this is a fatal error */
|
||||
*errnop = errno = ENOENT;
|
||||
ret = NSS_STATUS_UNAVAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = _ldb_nss_group_request(&mem_res,
|
||||
uid_res->msgs[0]->dn,
|
||||
attrs,
|
||||
"memberOf");
|
||||
|
||||
if (ret != NSS_STATUS_SUCCESS) {
|
||||
*errnop = errno;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = _ldb_nss_fill_initgr(group,
|
||||
limit,
|
||||
start,
|
||||
size,
|
||||
groups,
|
||||
errnop,
|
||||
mem_res);
|
||||
|
||||
if (ret != NSS_STATUS_SUCCESS) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = NSS_STATUS_SUCCESS;
|
||||
|
||||
done:
|
||||
talloc_free(mem_res);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,402 @@
|
||||
/*
|
||||
LDB nsswitch module
|
||||
|
||||
Copyright (C) Simo Sorce 2006
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "ldb-nss.h"
|
||||
|
||||
struct _ldb_nss_context *_ldb_nss_ctx = NULL;
|
||||
|
||||
NSS_STATUS _ldb_nss_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
pid_t mypid = getpid();
|
||||
|
||||
if (_ldb_nss_ctx != NULL) {
|
||||
if (_ldb_nss_ctx->pid == mypid) {
|
||||
/* already initialized */
|
||||
return NSS_STATUS_SUCCESS;
|
||||
} else {
|
||||
/* we are in a forked child now, reinitialize */
|
||||
talloc_free(_ldb_nss_ctx);
|
||||
_ldb_nss_ctx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
_ldb_nss_ctx = talloc_named(NULL, 0, "_ldb_nss_ctx(%u)", mypid);
|
||||
if (_ldb_nss_ctx == NULL) {
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
_ldb_nss_ctx->pid = mypid;
|
||||
|
||||
ret = ldb_global_init();
|
||||
if (ret != 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
_ldb_nss_ctx->ldb = ldb_init(_ldb_nss_ctx);
|
||||
if (_ldb_nss_ctx->ldb == NULL) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
ret = ldb_connect(_ldb_nss_ctx->ldb, _LDB_NSS_URL, LDB_FLG_RDONLY, NULL);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
_ldb_nss_ctx->base = ldb_dn_new(_ldb_nss_ctx, _ldb_nss_ctx->ldb, _LDB_NSS_BASEDN);
|
||||
if ( ! ldb_dn_validate(_ldb_nss_ctx->base)) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
_ldb_nss_ctx->pw_cur = 0;
|
||||
_ldb_nss_ctx->pw_res = NULL;
|
||||
_ldb_nss_ctx->gr_cur = 0;
|
||||
_ldb_nss_ctx->gr_res = NULL;
|
||||
|
||||
return NSS_STATUS_SUCCESS;
|
||||
|
||||
failed:
|
||||
/* talloc_free(_ldb_nss_ctx); */
|
||||
_ldb_nss_ctx = NULL;
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
NSS_STATUS _ldb_nss_fill_passwd(struct passwd *result,
|
||||
char *buffer,
|
||||
int buflen,
|
||||
int *errnop,
|
||||
struct ldb_message *msg)
|
||||
{
|
||||
int len;
|
||||
int bufpos;
|
||||
const char *tmp;
|
||||
|
||||
bufpos = 0;
|
||||
|
||||
/* get username */
|
||||
tmp = ldb_msg_find_attr_as_string(msg, "uid", NULL);
|
||||
if (tmp == NULL) {
|
||||
/* this is a fatal error */
|
||||
*errnop = errno = ENOENT;
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
len = strlen(tmp)+1;
|
||||
if (bufpos + len > buflen) {
|
||||
/* buffer too small */
|
||||
*errnop = errno = EAGAIN;
|
||||
return NSS_STATUS_TRYAGAIN;
|
||||
}
|
||||
memcpy(&buffer[bufpos], tmp, len);
|
||||
result->pw_name = &buffer[bufpos];
|
||||
bufpos += len;
|
||||
|
||||
/* get userPassword */
|
||||
tmp = ldb_msg_find_attr_as_string(msg, "userPassword", NULL);
|
||||
if (tmp == NULL) {
|
||||
tmp = "LDB";
|
||||
}
|
||||
len = strlen(tmp)+1;
|
||||
if (bufpos + len > buflen) {
|
||||
/* buffer too small */
|
||||
*errnop = errno = EAGAIN;
|
||||
return NSS_STATUS_TRYAGAIN;
|
||||
}
|
||||
memcpy(&buffer[bufpos], tmp, len);
|
||||
result->pw_passwd = &buffer[bufpos];
|
||||
bufpos += len;
|
||||
|
||||
/* this backend never serves an uid 0 user */
|
||||
result->pw_uid = ldb_msg_find_attr_as_int(msg, "uidNumber", 0);
|
||||
if (result->pw_uid == 0) {
|
||||
/* this is a fatal error */
|
||||
*errnop = errno = ENOENT;
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
result->pw_gid = ldb_msg_find_attr_as_int(msg, "gidNumber", 0);
|
||||
if (result->pw_gid == 0) {
|
||||
/* this is a fatal error */
|
||||
*errnop = errno = ENOENT;
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
/* get gecos */
|
||||
tmp = ldb_msg_find_attr_as_string(msg, "gecos", NULL);
|
||||
if (tmp == NULL) {
|
||||
tmp = "";
|
||||
}
|
||||
len = strlen(tmp)+1;
|
||||
if (bufpos + len > buflen) {
|
||||
/* buffer too small */
|
||||
*errnop = errno = EAGAIN;
|
||||
return NSS_STATUS_TRYAGAIN;
|
||||
}
|
||||
memcpy(&buffer[bufpos], tmp, len);
|
||||
result->pw_gecos = &buffer[bufpos];
|
||||
bufpos += len;
|
||||
|
||||
/* get homeDirectory */
|
||||
tmp = ldb_msg_find_attr_as_string(msg, "homeDirectory", NULL);
|
||||
if (tmp == NULL) {
|
||||
tmp = "";
|
||||
}
|
||||
len = strlen(tmp)+1;
|
||||
if (bufpos + len > buflen) {
|
||||
/* buffer too small */
|
||||
*errnop = errno = EAGAIN;
|
||||
return NSS_STATUS_TRYAGAIN;
|
||||
}
|
||||
memcpy(&buffer[bufpos], tmp, len);
|
||||
result->pw_dir = &buffer[bufpos];
|
||||
bufpos += len;
|
||||
|
||||
/* get shell */
|
||||
tmp = ldb_msg_find_attr_as_string(msg, "loginShell", NULL);
|
||||
if (tmp == NULL) {
|
||||
tmp = "";
|
||||
}
|
||||
len = strlen(tmp)+1;
|
||||
if (bufpos + len > buflen) {
|
||||
/* buffer too small */
|
||||
*errnop = errno = EAGAIN;
|
||||
return NSS_STATUS_TRYAGAIN;
|
||||
}
|
||||
memcpy(&buffer[bufpos], tmp, len);
|
||||
result->pw_shell = &buffer[bufpos];
|
||||
bufpos += len;
|
||||
|
||||
return NSS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NSS_STATUS _ldb_nss_fill_group(struct group *result,
|
||||
char *buffer,
|
||||
int buflen,
|
||||
int *errnop,
|
||||
struct ldb_message *group,
|
||||
struct ldb_result *members)
|
||||
{
|
||||
const char *tmp;
|
||||
size_t len;
|
||||
size_t bufpos;
|
||||
size_t lsize;
|
||||
int i;
|
||||
|
||||
bufpos = 0;
|
||||
|
||||
/* get group name */
|
||||
tmp = ldb_msg_find_attr_as_string(group, "cn", NULL);
|
||||
if (tmp == NULL) {
|
||||
/* this is a fatal error */
|
||||
*errnop = errno = ENOENT;
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
len = strlen(tmp)+1;
|
||||
if (bufpos + len > buflen) {
|
||||
/* buffer too small */
|
||||
*errnop = errno = EAGAIN;
|
||||
return NSS_STATUS_TRYAGAIN;
|
||||
}
|
||||
memcpy(&buffer[bufpos], tmp, len);
|
||||
result->gr_name = &buffer[bufpos];
|
||||
bufpos += len;
|
||||
|
||||
/* get userPassword */
|
||||
tmp = ldb_msg_find_attr_as_string(group, "userPassword", NULL);
|
||||
if (tmp == NULL) {
|
||||
tmp = "LDB";
|
||||
}
|
||||
len = strlen(tmp)+1;
|
||||
if (bufpos + len > buflen) {
|
||||
/* buffer too small */
|
||||
*errnop = errno = EAGAIN;
|
||||
return NSS_STATUS_TRYAGAIN;
|
||||
}
|
||||
memcpy(&buffer[bufpos], tmp, len);
|
||||
result->gr_passwd = &buffer[bufpos];
|
||||
bufpos += len;
|
||||
|
||||
result->gr_gid = ldb_msg_find_attr_as_int(group, "gidNumber", 0);
|
||||
if (result->gr_gid == 0) {
|
||||
/* this is a fatal error */
|
||||
*errnop = errno = ENOENT;
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
/* check if there is enough memory for the list of pointers */
|
||||
lsize = (members->count + 1) * sizeof(char *);
|
||||
|
||||
/* align buffer on pointer boundary */
|
||||
bufpos += (sizeof(char*) - ((unsigned long)(buffer) % sizeof(char*)));
|
||||
if ((buflen - bufpos) < lsize) {
|
||||
/* buffer too small */
|
||||
*errnop = errno = EAGAIN;
|
||||
return NSS_STATUS_TRYAGAIN;
|
||||
}
|
||||
|
||||
result->gr_mem = (char **)&buffer[bufpos];
|
||||
bufpos += lsize;
|
||||
|
||||
for (i = 0; i < members->count; i++) {
|
||||
tmp = ldb_msg_find_attr_as_string(members->msgs[i], "uid", NULL);
|
||||
if (tmp == NULL) {
|
||||
/* this is a fatal error */
|
||||
*errnop = errno = ENOENT;
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
len = strlen(tmp)+1;
|
||||
if (bufpos + len > buflen) {
|
||||
/* buffer too small */
|
||||
*errnop = errno = EAGAIN;
|
||||
return NSS_STATUS_TRYAGAIN;
|
||||
}
|
||||
memcpy(&buffer[bufpos], tmp, len);
|
||||
result->gr_mem[i] = &buffer[bufpos];
|
||||
bufpos += len;
|
||||
}
|
||||
|
||||
result->gr_mem[i] = NULL;
|
||||
|
||||
return NSS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NSS_STATUS _ldb_nss_fill_initgr(gid_t group,
|
||||
long int limit,
|
||||
long int *start,
|
||||
long int *size,
|
||||
gid_t **groups,
|
||||
int *errnop,
|
||||
struct ldb_result *grlist)
|
||||
{
|
||||
NSS_STATUS ret;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < grlist->count; i++) {
|
||||
|
||||
if (limit && (*start > limit)) {
|
||||
/* TODO: warn no all groups were reported */
|
||||
*errnop = 0;
|
||||
ret = NSS_STATUS_SUCCESS;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (*start == *size) {
|
||||
/* buffer full, enlarge it */
|
||||
long int gs;
|
||||
gid_t *gm;
|
||||
|
||||
gs = (*size) + 32;
|
||||
if (limit && (gs > limit)) {
|
||||
gs = limit;
|
||||
}
|
||||
|
||||
gm = (gid_t *)realloc((*groups), gs * sizeof(gid_t));
|
||||
if ( ! gm) {
|
||||
*errnop = ENOMEM;
|
||||
ret = NSS_STATUS_UNAVAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
*groups = gm;
|
||||
*size = gs;
|
||||
}
|
||||
|
||||
(*groups)[*start] = ldb_msg_find_attr_as_int(grlist->msgs[i], "gidNumber", 0);
|
||||
if ((*groups)[*start] == 0 || (*groups)[*start] == group) {
|
||||
/* skip root group or primary group */
|
||||
continue;
|
||||
}
|
||||
(*start)++;
|
||||
|
||||
}
|
||||
|
||||
*errnop = 0;
|
||||
ret = NSS_STATUS_SUCCESS;
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define _LDB_NSS_ALLOC_CHECK(mem) do { if (!mem) { errno = ENOMEM; return NSS_STATUS_UNAVAIL; } } while(0)
|
||||
|
||||
NSS_STATUS _ldb_nss_group_request(struct ldb_result **_res,
|
||||
struct ldb_dn *group_dn,
|
||||
const char * const *attrs,
|
||||
const char *mattr)
|
||||
{
|
||||
struct ldb_control **ctrls;
|
||||
struct ldb_control *ctrl;
|
||||
struct ldb_asq_control *asqc;
|
||||
struct ldb_request *req;
|
||||
int ret;
|
||||
struct ldb_result *res = *_res;
|
||||
|
||||
ctrls = talloc_array(res, struct ldb_control *, 2);
|
||||
_LDB_NSS_ALLOC_CHECK(ctrls);
|
||||
|
||||
ctrl = talloc(ctrls, struct ldb_control);
|
||||
_LDB_NSS_ALLOC_CHECK(ctrl);
|
||||
|
||||
asqc = talloc(ctrl, struct ldb_asq_control);
|
||||
_LDB_NSS_ALLOC_CHECK(asqc);
|
||||
|
||||
asqc->source_attribute = talloc_strdup(asqc, mattr);
|
||||
_LDB_NSS_ALLOC_CHECK(asqc->source_attribute);
|
||||
|
||||
asqc->request = 1;
|
||||
asqc->src_attr_len = strlen(asqc->source_attribute);
|
||||
ctrl->oid = LDB_CONTROL_ASQ_OID;
|
||||
ctrl->critical = 1;
|
||||
ctrl->data = asqc;
|
||||
ctrls[0] = ctrl;
|
||||
ctrls[1] = NULL;
|
||||
|
||||
ret = ldb_build_search_req(
|
||||
&req,
|
||||
_ldb_nss_ctx->ldb,
|
||||
res,
|
||||
group_dn,
|
||||
LDB_SCOPE_BASE,
|
||||
"(objectClass=*)",
|
||||
attrs,
|
||||
ctrls,
|
||||
res,
|
||||
ldb_search_default_callback);
|
||||
|
||||
if (ret != LDB_SUCCESS) {
|
||||
errno = ENOENT;
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
ldb_set_timeout(_ldb_nss_ctx->ldb, req, 0);
|
||||
|
||||
ret = ldb_request(_ldb_nss_ctx->ldb, req);
|
||||
|
||||
if (ret == LDB_SUCCESS) {
|
||||
ret = ldb_wait(req->handle, LDB_WAIT_ALL);
|
||||
} else {
|
||||
talloc_free(req);
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
talloc_free(req);
|
||||
return NSS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
LDB nsswitch module
|
||||
|
||||
Copyright (C) Simo Sorce 2006
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _LDB_NSS
|
||||
#define _LDB_NSS
|
||||
|
||||
#include "includes.h"
|
||||
#include "ldb/include/includes.h"
|
||||
|
||||
#include <nss.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
#define _LDB_NSS_URL "etc/users.ldb"
|
||||
#define _LDB_NSS_BASEDN "CN=Users,CN=System"
|
||||
#define _LDB_NSS_PWENT_FILTER "(&(objectClass=posixAccount)(!(uidNumber=0))(!(gidNumber=0)))"
|
||||
#define _LDB_NSS_PWUID_FILTER "(&(objectClass=posixAccount)(uidNumber=%d)(!(gidNumber=0)))"
|
||||
#define _LDB_NSS_PWNAM_FILTER "(&(objectClass=posixAccount)(uid=%s)(!(uidNumber=0))(!(gidNumber=0)))"
|
||||
|
||||
#define _LDB_NSS_GRENT_FILTER "(&(objectClass=posixGroup)(!(gidNumber=0)))"
|
||||
#define _LDB_NSS_GRGID_FILTER "(&(objectClass=posixGroup)(gidNumber=%d)))"
|
||||
#define _LDB_NSS_GRNAM_FILTER "(&(objectClass=posixGroup)(cn=%s)(!(gidNumber=0)))"
|
||||
|
||||
typedef enum nss_status NSS_STATUS;
|
||||
|
||||
struct _ldb_nss_context {
|
||||
|
||||
pid_t pid;
|
||||
|
||||
struct ldb_context *ldb;
|
||||
struct ldb_dn *base;
|
||||
|
||||
int pw_cur;
|
||||
struct ldb_result *pw_res;
|
||||
|
||||
int gr_cur;
|
||||
struct ldb_result *gr_res;
|
||||
};
|
||||
|
||||
NSS_STATUS _ldb_nss_init(void);
|
||||
|
||||
NSS_STATUS _ldb_nss_fill_passwd(struct passwd *result,
|
||||
char *buffer,
|
||||
int buflen,
|
||||
int *errnop,
|
||||
struct ldb_message *msg);
|
||||
|
||||
NSS_STATUS _ldb_nss_fill_group(struct group *result,
|
||||
char *buffer,
|
||||
int buflen,
|
||||
int *errnop,
|
||||
struct ldb_message *group,
|
||||
struct ldb_result *members);
|
||||
|
||||
NSS_STATUS _ldb_nss_fill_initgr(gid_t group,
|
||||
long int limit,
|
||||
long int *start,
|
||||
long int *size,
|
||||
gid_t **groups,
|
||||
int *errnop,
|
||||
struct ldb_result *grlist);
|
||||
|
||||
NSS_STATUS _ldb_nss_group_request(struct ldb_result **res,
|
||||
struct ldb_dn *group_dn,
|
||||
const char * const *attrs,
|
||||
const char *mattr);
|
||||
|
||||
#endif /* _LDB_NSS */
|
||||
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
LDB nsswitch module
|
||||
|
||||
Copyright (C) Simo Sorce 2006
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "ldb-nss.h"
|
||||
|
||||
extern struct _ldb_nss_context *_ldb_nss_ctx;
|
||||
|
||||
const char *_ldb_nss_pw_attrs[] = {
|
||||
"uid",
|
||||
"userPassword",
|
||||
"uidNumber",
|
||||
"gidNumber",
|
||||
"gecos",
|
||||
"homeDirectory",
|
||||
"loginShell",
|
||||
NULL
|
||||
};
|
||||
|
||||
NSS_STATUS _nss_ldb_setpwent(void)
|
||||
{
|
||||
int ret;
|
||||
ret = _ldb_nss_init();
|
||||
if (ret != NSS_STATUS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
_ldb_nss_ctx->pw_cur = 0;
|
||||
if (_ldb_nss_ctx->pw_res != NULL) {
|
||||
talloc_free(_ldb_nss_ctx->pw_res);
|
||||
_ldb_nss_ctx->pw_res = NULL;
|
||||
}
|
||||
|
||||
ret = ldb_search(_ldb_nss_ctx->ldb,
|
||||
_ldb_nss_ctx->base,
|
||||
LDB_SCOPE_SUBTREE,
|
||||
_LDB_NSS_PWENT_FILTER,
|
||||
_ldb_nss_pw_attrs,
|
||||
&_ldb_nss_ctx->pw_res);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
return NSS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NSS_STATUS _nss_ldb_endpwent(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = _ldb_nss_init();
|
||||
if (ret != NSS_STATUS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
_ldb_nss_ctx->pw_cur = 0;
|
||||
if (_ldb_nss_ctx->pw_res) {
|
||||
talloc_free(_ldb_nss_ctx->pw_res);
|
||||
_ldb_nss_ctx->pw_res = NULL;
|
||||
}
|
||||
|
||||
return NSS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NSS_STATUS _nss_ldb_getpwent_r(struct passwd *result_buf,
|
||||
char *buffer,
|
||||
int buflen,
|
||||
int *errnop)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = _ldb_nss_init();
|
||||
if (ret != NSS_STATUS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
*errnop = 0;
|
||||
|
||||
if (_ldb_nss_ctx->pw_cur >= _ldb_nss_ctx->pw_res->count) {
|
||||
/* already returned all entries */
|
||||
return NSS_STATUS_NOTFOUND;
|
||||
}
|
||||
|
||||
ret = _ldb_nss_fill_passwd(result_buf,
|
||||
buffer,
|
||||
buflen,
|
||||
errnop,
|
||||
_ldb_nss_ctx->pw_res->msgs[_ldb_nss_ctx->pw_cur]);
|
||||
if (ret != NSS_STATUS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
_ldb_nss_ctx->pw_cur++;
|
||||
|
||||
return NSS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NSS_STATUS _nss_ldb_getpwuid_r(uid_t uid, struct passwd *result_buf, char *buffer, size_t buflen, int *errnop)
|
||||
{
|
||||
int ret;
|
||||
char *filter;
|
||||
struct ldb_result *res;
|
||||
|
||||
if (uid == 0) { /* we don't serve root uid by policy */
|
||||
*errnop = errno = ENOENT;
|
||||
return NSS_STATUS_NOTFOUND;
|
||||
}
|
||||
|
||||
ret = _ldb_nss_init();
|
||||
if (ret != NSS_STATUS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* build the filter for this uid */
|
||||
filter = talloc_asprintf(_ldb_nss_ctx, _LDB_NSS_PWUID_FILTER, uid);
|
||||
if (filter == NULL) {
|
||||
/* this is a fatal error */
|
||||
*errnop = errno = ENOMEM;
|
||||
ret = NSS_STATUS_UNAVAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* search the entry */
|
||||
ret = ldb_search(_ldb_nss_ctx->ldb,
|
||||
_ldb_nss_ctx->base,
|
||||
LDB_SCOPE_SUBTREE,
|
||||
filter,
|
||||
_ldb_nss_pw_attrs,
|
||||
&res);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
/* this is a fatal error */
|
||||
*errnop = errno = ENOENT;
|
||||
ret = NSS_STATUS_UNAVAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* if none found return */
|
||||
if (res->count == 0) {
|
||||
*errnop = errno = ENOENT;
|
||||
ret = NSS_STATUS_NOTFOUND;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (res->count != 1) {
|
||||
/* this is a fatal error */
|
||||
*errnop = errno = ENOENT;
|
||||
ret = NSS_STATUS_UNAVAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* fill in the passwd struct */
|
||||
ret = _ldb_nss_fill_passwd(result_buf,
|
||||
buffer,
|
||||
buflen,
|
||||
errnop,
|
||||
res->msgs[0]);
|
||||
|
||||
done:
|
||||
talloc_free(filter);
|
||||
talloc_free(res);
|
||||
return ret;
|
||||
}
|
||||
|
||||
NSS_STATUS _nss_ldb_getpwnam_r(const char *name, struct passwd *result_buf, char *buffer, size_t buflen, int *errnop)
|
||||
{
|
||||
int ret;
|
||||
char *filter;
|
||||
struct ldb_result *res;
|
||||
|
||||
ret = _ldb_nss_init();
|
||||
if (ret != NSS_STATUS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* build the filter for this name */
|
||||
filter = talloc_asprintf(_ldb_nss_ctx, _LDB_NSS_PWNAM_FILTER, name);
|
||||
if (filter == NULL) {
|
||||
/* this is a fatal error */
|
||||
*errnop = errno = ENOENT;
|
||||
ret = NSS_STATUS_UNAVAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* search the entry */
|
||||
ret = ldb_search(_ldb_nss_ctx->ldb,
|
||||
_ldb_nss_ctx->base,
|
||||
LDB_SCOPE_SUBTREE,
|
||||
filter,
|
||||
_ldb_nss_pw_attrs,
|
||||
&res);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
/* this is a fatal error */
|
||||
*errnop = errno = ENOENT;
|
||||
ret = NSS_STATUS_UNAVAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* if none found return */
|
||||
if (res->count == 0) {
|
||||
*errnop = errno = ENOENT;
|
||||
ret = NSS_STATUS_NOTFOUND;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (res->count != 1) {
|
||||
/* this is a fatal error */
|
||||
*errnop = errno = ENOENT;
|
||||
ret = NSS_STATUS_UNAVAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* fill in the passwd struct */
|
||||
ret = _ldb_nss_fill_passwd(result_buf,
|
||||
buffer,
|
||||
buflen,
|
||||
errnop,
|
||||
res->msgs[0]);
|
||||
|
||||
done:
|
||||
talloc_free(filter);
|
||||
talloc_free(res);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user