*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
#include "groupdb/mapping.h"
-#include "lib/ldb/include/includes.h"
+#include "lib/ldb/include/ldb.h"
#include "lib/ldb/include/ldb_errors.h"
static struct ldb_context *ldb;
-static BOOL mapping_upgrade(const char *tdb_path);
+static bool mapping_upgrade(const char *tdb_path);
/*
connect to the group mapping ldb
*/
- BOOL init_group_mapping(void)
+static bool init_group_mapping(void)
{
- BOOL existed;
+ bool existed;
const char *init_ldif[] =
{ "dn: @ATTRIBUTES\n" \
"ntName: CASE_INSENSITIVE\n" \
/* this is needed as Samba3 doesn't have this globally yet */
ldb_global_init();
- db_path = lock_path("group_mapping.ldb");
+ db_path = state_path("group_mapping.ldb");
- ldb = ldb_init(NULL);
+ ldb = ldb_init(NULL, NULL);
if (ldb == NULL) goto failed;
- existed = file_exist(db_path, NULL);
+ /* Ensure this db is created read/write for root only. */
+ ldb_set_create_perms(ldb, 0600);
+
+ existed = file_exist(db_path);
if (lp_parm_bool(-1, "groupmap", "nosync", False)) {
flags |= LDB_FLG_NOSYNC;
}
+ if (!lp_use_mmap()) {
+ flags |= LDB_FLG_NOMMAP;
+ }
+
ret = ldb_connect(ldb, db_path, flags, NULL);
if (ret != LDB_SUCCESS) {
goto failed;
}
-
+
+ /* force the permissions on the ldb to 0600 - this will fix
+ existing databases as well as new ones */
+ if (chmod(db_path, 0600) != 0) {
+ goto failed;
+ }
+
if (!existed) {
/* initialise the ldb with an index */
struct ldb_ldif *ldif;
}
/* possibly upgrade */
- tdb_path = lock_path("group_mapping.tdb");
- if (file_exist(tdb_path, NULL) && !mapping_upgrade(tdb_path)) {
- unlink(lock_path("group_mapping.ldb"));
+ tdb_path = state_path("group_mapping.tdb");
+ if (file_exist(tdb_path) && !mapping_upgrade(tdb_path)) {
+ unlink(state_path("group_mapping.ldb"));
goto failed;
}
if (!sid_split_rid(&domsid, &rid)) {
return NULL;
}
- if (!sid_to_string(string_sid, &domsid)) {
+ if (!sid_to_fstring(string_sid, &domsid)) {
return NULL;
}
/* we split by domain and rid so we can do a subtree search
when we only want one domain */
- return ldb_dn_string_compose(mem_ctx, NULL, "rid=%u,domain=%s",
- rid, string_sid);
+ return ldb_dn_new_fmt(mem_ctx, ldb, "rid=%u,domain=%s",
+ rid, string_sid);
}
/*
add a group mapping entry
*/
- BOOL add_mapping_entry(GROUP_MAP *map, int flag)
+static bool add_mapping_entry(GROUP_MAP *map, int flag)
{
struct ldb_message *msg;
int ret, i;
fstring string_sid;
- if (!init_group_mapping()) {
- return False;
- }
-
msg = ldb_msg_new(ldb);
if (msg == NULL) {
return False;
if (ldb_msg_add_string(msg, "objectClass", "groupMap") != LDB_SUCCESS ||
ldb_msg_add_string(msg, "sid",
- sid_to_string(string_sid, &map->sid)) != LDB_SUCCESS ||
+ sid_to_fstring(string_sid, &map->sid)) != LDB_SUCCESS ||
ldb_msg_add_fmt(msg, "gidNumber", "%u", (unsigned)map->gid) != LDB_SUCCESS ||
ldb_msg_add_fmt(msg, "sidNameUse", "%u", (unsigned)map->sid_name_use) != LDB_SUCCESS ||
ldb_msg_add_string(msg, "comment", map->comment) != LDB_SUCCESS ||
/*
unpack a ldb message into a GROUP_MAP structure
*/
-static BOOL msg_to_group_map(struct ldb_message *msg, GROUP_MAP *map)
+static bool msg_to_group_map(struct ldb_message *msg, GROUP_MAP *map)
{
const char *sidstr;
/*
return a group map entry for a given sid
*/
- BOOL get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map)
+static bool get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map)
{
int ret;
struct ldb_dn *dn;
struct ldb_result *res=NULL;
-
- if (!init_group_mapping()) {
- return False;
- }
+ bool result = false;
- dn = mapping_dn(ldb, &sid);
- if (dn == NULL) goto failed;
+ dn = mapping_dn(talloc_tos(), &sid);
+ if (dn == NULL) {
+ goto failed;
+ }
- ret = ldb_search(ldb, dn, LDB_SCOPE_BASE, NULL, NULL, &res);
- talloc_steal(dn, res);
+ ret = ldb_search(ldb, dn, &res, dn, LDB_SCOPE_BASE, NULL, NULL);
if (ret != LDB_SUCCESS || res->count != 1) {
goto failed;
}
- if (!msg_to_group_map(res->msgs[0], map)) goto failed;
-
- talloc_free(dn);
- return True;
+ if (!msg_to_group_map(res->msgs[0], map)) {
+ goto failed;
+ }
-failed:
+ result = true;
+ failed:
talloc_free(dn);
- return False;
+ return result;
}
/*
return a group map entry for a given gid
*/
- BOOL get_group_map_from_gid(gid_t gid, GROUP_MAP *map)
+static bool get_group_map_from_gid(gid_t gid, GROUP_MAP *map)
{
int ret;
- char *expr;
struct ldb_result *res=NULL;
+ bool result = false;
- if (!init_group_mapping()) {
- return False;
+ ret = ldb_search(ldb, talloc_tos(), &res, NULL, LDB_SCOPE_SUBTREE,
+ NULL, "(&(gidNumber=%u)(objectClass=groupMap))",
+ (unsigned)gid);
+ if (ret != LDB_SUCCESS || res->count != 1) {
+ goto failed;
}
- expr = talloc_asprintf(ldb, "(&(gidNumber=%u)(objectClass=groupMap))",
- (unsigned)gid);
- if (expr == NULL) goto failed;
-
- ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, expr, NULL, &res);
- talloc_steal(expr, res);
- if (ret != LDB_SUCCESS || res->count != 1) goto failed;
-
- if (!msg_to_group_map(res->msgs[0], map)) goto failed;
-
- talloc_free(expr);
- return True;
+ if (!msg_to_group_map(res->msgs[0], map)) {
+ goto failed;
+ }
+ result = true;
failed:
- talloc_free(expr);
- return False;
+ TALLOC_FREE(res);
+ return result;
}
/*
Return the sid and the type of the unix group.
*/
- BOOL get_group_map_from_ntname(const char *name, GROUP_MAP *map)
+static bool get_group_map_from_ntname(const char *name, GROUP_MAP *map)
{
int ret;
- char *expr;
struct ldb_result *res=NULL;
+ bool result = false;
- if (!init_group_mapping()) {
- return False;
+ ret = ldb_search(ldb, talloc_tos(), &res, NULL, LDB_SCOPE_SUBTREE,
+ NULL, "(&(ntName=%s)(objectClass=groupMap))", name);
+ if (ret != LDB_SUCCESS || res->count != 1) {
+ goto failed;
}
- expr = talloc_asprintf(ldb, "(&(ntName=%s)(objectClass=groupMap))", name);
- if (expr == NULL) goto failed;
-
- ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, expr, NULL, &res);
- talloc_steal(expr, res);
- if (ret != LDB_SUCCESS || res->count != 1) goto failed;
-
- if (!msg_to_group_map(res->msgs[0], map)) goto failed;
-
- talloc_free(expr);
- return True;
+ if (!msg_to_group_map(res->msgs[0], map)) {
+ goto failed;
+ }
-failed:
- talloc_free(expr);
- return False;
+ result = true;
+ failed:
+ TALLOC_FREE(res);
+ return result;
}
/*
Remove a group mapping entry.
*/
- BOOL group_map_remove(const DOM_SID *sid)
+static bool group_map_remove(const DOM_SID *sid)
{
struct ldb_dn *dn;
int ret;
- if (!init_group_mapping()) {
- return False;
- }
-
dn = mapping_dn(ldb, sid);
if (dn == NULL) {
return False;
/*
Enumerate the group mappings for a domain
*/
- BOOL enum_group_mapping(const DOM_SID *domsid, enum lsa_SidType sid_name_use,
- GROUP_MAP **pp_rmap,
- size_t *p_num_entries, BOOL unix_only)
+static bool enum_group_mapping(const DOM_SID *domsid, enum lsa_SidType sid_name_use,
+ GROUP_MAP **pp_rmap,
+ size_t *p_num_entries, bool unix_only)
{
int i, ret;
- char *expr;
fstring name;
- struct ldb_result *res;
+ struct ldb_result *res = NULL;
struct ldb_dn *basedn=NULL;
TALLOC_CTX *tmp_ctx;
- if (!init_group_mapping()) {
- return False;
- }
-
tmp_ctx = talloc_new(ldb);
if (tmp_ctx == NULL) goto failed;
- if (sid_name_use == SID_NAME_UNKNOWN) {
- expr = talloc_asprintf(tmp_ctx, "(&(objectClass=groupMap))");
- } else {
- expr = talloc_asprintf(tmp_ctx, "(&(sidNameUse=%u)(objectClass=groupMap))",
- sid_name_use);
- }
- if (expr == NULL) goto failed;
-
/* we do a subtree search on the domain */
if (domsid != NULL) {
- sid_to_string(name, domsid);
- basedn = ldb_dn_string_compose(tmp_ctx, NULL, "domain=%s", name);
+ sid_to_fstring(name, domsid);
+ basedn = ldb_dn_new_fmt(tmp_ctx, ldb, "domain=%s", name);
if (basedn == NULL) goto failed;
}
- ret = ldb_search(ldb, basedn, LDB_SCOPE_SUBTREE, expr, NULL, &res);
+ if (sid_name_use == SID_NAME_UNKNOWN) {
+ ret = ldb_search(ldb, tmp_ctx, &res, basedn, LDB_SCOPE_SUBTREE,
+ NULL, "(&(objectClass=groupMap))");
+ } else {
+ ret = ldb_search(ldb, tmp_ctx, &res, basedn, LDB_SCOPE_SUBTREE,
+ NULL, "(&(sidNameUse=%u)(objectClass=groupMap))",
+ sid_name_use);
+ }
+
if (ret != LDB_SUCCESS) goto failed;
(*pp_rmap) = NULL;
This operation happens on session setup, so it should better be fast. We
store a list of aliases a SID is member of hanging off MEMBEROF/SID.
*/
- NTSTATUS one_alias_membership(const DOM_SID *member,
- DOM_SID **sids, size_t *num)
+static NTSTATUS one_alias_membership(const DOM_SID *member,
+ DOM_SID **sids, size_t *num)
{
const char *attrs[] = {
"sid",
NULL
};
DOM_SID alias;
- char *expr;
int ret, i;
struct ldb_result *res=NULL;
fstring string_sid;
- NTSTATUS status = NT_STATUS_INTERNAL_DB_CORRUPTION;
-
- if (!init_group_mapping()) {
- return NT_STATUS_ACCESS_DENIED;
- }
+ NTSTATUS status;
- if (!sid_to_string(string_sid, member)) {
+ if (!sid_to_fstring(string_sid, member)) {
return NT_STATUS_INVALID_PARAMETER;
}
- expr = talloc_asprintf(ldb, "(&(member=%s)(objectClass=groupMap))",
- string_sid);
- if (expr == NULL) goto failed;
-
- ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, expr, attrs, &res);
- talloc_steal(expr, res);
+ ret = ldb_search(ldb, talloc_tos(), &res, NULL, LDB_SCOPE_SUBTREE,
+ attrs, "(&(member=%s)(objectClass=groupMap))",
+ string_sid);
if (ret != LDB_SUCCESS) {
+ status = NT_STATUS_INTERNAL_DB_CORRUPTION;
goto failed;
}
goto failed;
}
string_to_sid(&alias, (char *)el->values[0].data);
- add_sid_to_array_unique(NULL, &alias, sids, num);
- if (sids == NULL) {
- status = NT_STATUS_NO_MEMORY;
+ status = add_sid_to_array_unique(NULL, &alias, sids, num);
+ if (!NT_STATUS_IS_OK(status)) {
goto failed;
}
}
- talloc_free(expr);
- return NT_STATUS_OK;
-
-failed:
- talloc_free(expr);
+ status = NT_STATUS_OK;
+ failed:
+ TALLOC_FREE(res);
return status;
}
TALLOC_CTX *tmp_ctx;
GROUP_MAP map;
- if (!init_group_mapping()) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
if (!get_group_map_from_sid(*alias, &map)) {
- sid_to_string(string_sid, alias);
+ sid_to_fstring(string_sid, alias);
return NT_STATUS_NO_SUCH_ALIAS;
}
el.name = talloc_strdup(tmp_ctx, "member");
el.num_values = 1;
el.values = &val;
- sid_to_string(string_sid, member);
+ sid_to_fstring(string_sid, member);
val.data = (uint8_t *)string_sid;
val.length = strlen(string_sid);
return (ret == LDB_SUCCESS ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED);
}
- NTSTATUS add_aliasmem(const DOM_SID *alias, const DOM_SID *member)
+static NTSTATUS add_aliasmem(const DOM_SID *alias, const DOM_SID *member)
{
return modify_aliasmem(alias, member, LDB_FLAG_MOD_ADD);
}
- NTSTATUS del_aliasmem(const DOM_SID *alias, const DOM_SID *member)
+static NTSTATUS del_aliasmem(const DOM_SID *alias, const DOM_SID *member)
{
return modify_aliasmem(alias, member, LDB_FLAG_MOD_DELETE);
}
/*
enumerate sids that have the given alias set in member
*/
- NTSTATUS enum_aliasmem(const DOM_SID *alias, DOM_SID **sids, size_t *num)
+static NTSTATUS enum_aliasmem(const DOM_SID *alias, TALLOC_CTX *mem_ctx,
+ DOM_SID **sids, size_t *num)
{
const char *attrs[] = {
"member",
NULL
};
int ret, i;
+ NTSTATUS status = NT_STATUS_OK;
struct ldb_result *res=NULL;
struct ldb_dn *dn;
struct ldb_message_element *el;
- if (!init_group_mapping()) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
*sids = NULL;
*num = 0;
return NT_STATUS_NO_MEMORY;
}
- ret = ldb_search(ldb, dn, LDB_SCOPE_BASE, NULL, attrs, &res);
- talloc_steal(dn, res);
+ ret = ldb_search(ldb, ldb, &res, dn, LDB_SCOPE_BASE, attrs, NULL);
if (ret == LDB_SUCCESS && res->count == 0) {
+ talloc_free(res);
talloc_free(dn);
return NT_STATUS_OK;
}
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
+ talloc_steal(dn, res);
el = ldb_msg_find_element(res->msgs[0], "member");
if (el == NULL) {
talloc_free(dn);
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ return NT_STATUS_OK;
}
for (i=0;i<el->num_values;i++) {
DOM_SID sid;
string_to_sid(&sid, (const char *)el->values[i].data);
- add_sid_to_array_unique(NULL, &sid, sids, num);
- if (sids == NULL) {
- talloc_free(dn);
- return NT_STATUS_NO_MEMORY;
+ status = add_sid_to_array_unique(mem_ctx, &sid, sids, num);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
}
}
- talloc_free(dn);
- return NT_STATUS_OK;
+done:
+ talloc_free(dn);
+ return status;
}
/*
int ret;
GROUP_MAP map;
- if (strncmp(key.dptr, GROUP_PREFIX,
+ if (strncmp((char *)key.dptr, GROUP_PREFIX,
MIN(key.dsize, strlen(GROUP_PREFIX))) != 0) {
return 0;
}
return -1;
}
+ if ((int)map.gid == -1) {
+ /*
+ * Ignore old invalid mappings
+ */
+ return 0;
+ }
+
if (!add_mapping_entry(&map, 0)) {
DEBUG(0,("Failed to add mapping entry during upgrade\n"));
*(int *)state = -1;
static int upgrade_alias_record(TDB_CONTEXT *tdb_ctx, TDB_DATA key,
TDB_DATA data, void *state)
{
- const char *p = data.dptr;
- fstring string_sid;
+ const char *p = (const char *)data.dptr;
+ char *string_sid;
DOM_SID member;
+ TALLOC_CTX *frame;
- if (strncmp(key.dptr, MEMBEROF_PREFIX,
+ if (strncmp((char *)key.dptr, MEMBEROF_PREFIX,
MIN(key.dsize, strlen(MEMBEROF_PREFIX))) != 0) {
return 0;
}
*(int *)state = -1;
}
- while (next_token(&p, string_sid, " ", sizeof(string_sid))) {
+ frame = talloc_stackframe();
+ while (next_token_talloc(frame,&p, &string_sid, " ")) {
DOM_SID alias;
NTSTATUS status;
string_to_sid(&alias, string_sid);
DEBUG(0,("Failed to add alias member during upgrade - %s\n",
nt_errstr(status)));
*(int *)state = -1;
+ TALLOC_FREE(frame);
return -1;
}
}
-
+ TALLOC_FREE(frame);
return 0;
}
/*
upgrade from a old style tdb
*/
-static BOOL mapping_upgrade(const char *tdb_path)
+static bool mapping_upgrade(const char *tdb_path)
{
static TDB_CONTEXT *tdb;
int ret, status=0;
- pstring old_path;
- pstring new_path;
tdb = tdb_open_log(tdb_path, 0, TDB_DEFAULT, O_RDWR, 0600);
if (tdb == NULL) goto failed;
ret = tdb_traverse(tdb, upgrade_alias_record, &status);
if (ret == -1 || status == -1) goto failed;
- if (tdb) tdb_close(tdb);
+ if (tdb) {
+ tdb_close(tdb);
+ tdb = NULL;
+ }
- pstrcpy(old_path, tdb_path);
- pstrcpy(new_path, lock_path("group_mapping.tdb.upgraded"));
+ {
+ const char *old_path = tdb_path;
+ char *new_path = state_path("group_mapping.tdb.upgraded");
- if (rename(old_path, new_path) != 0) {
- DEBUG(0,("Failed to rename old group mapping database\n"));
- goto failed;
+ if (!new_path) {
+ goto failed;
+ }
+ if (rename(old_path, new_path) != 0) {
+ DEBUG(0,("Failed to rename old group mapping database\n"));
+ goto failed;
+ }
}
return True;
if (tdb) tdb_close(tdb);
return False;
}
+
+
+
+static const struct mapping_backend ldb_backend = {
+ .add_mapping_entry = add_mapping_entry,
+ .get_group_map_from_sid = get_group_map_from_sid,
+ .get_group_map_from_gid = get_group_map_from_gid,
+ .get_group_map_from_ntname = get_group_map_from_ntname,
+ .group_map_remove = group_map_remove,
+ .enum_group_mapping = enum_group_mapping,
+ .one_alias_membership = one_alias_membership,
+ .add_aliasmem = add_aliasmem,
+ .del_aliasmem = del_aliasmem,
+ .enum_aliasmem = enum_aliasmem
+};
+
+/*
+ initialise the ldb mapping backend
+ */
+const struct mapping_backend *groupdb_ldb_init(void)
+{
+ if (!init_group_mapping()) {
+ DEBUG(0,("Failed to initialise ldb mapping backend\n"));
+ return NULL;
+ }
+
+ return &ldb_backend;
+}