mirror of
https://github.com/samba-team/samba.git
synced 2025-12-17 04:23:50 +03:00
r19456: Add an example application for ldb using the tdb backend
(This used to be commit 778198f279)
This commit is contained in:
committed by
Gerald (Jerry) Carter
parent
002338283f
commit
803a6dbaca
401
source4/lib/ldb/nssldb/ldb-nss.c
Normal file
401
source4/lib/ldb/nssldb/ldb-nss.c
Normal file
@@ -0,0 +1,401 @@
|
||||
/*
|
||||
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_explode(_ldb_nss_ctx, _LDB_NSS_BASEDN);
|
||||
if (_ldb_nss_ctx->base == NULL) {
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user