diff options
Diffstat (limited to 'source3/passdb')
-rw-r--r-- | source3/passdb/pdb_interface.c | 35 | ||||
-rw-r--r-- | source3/passdb/pdb_ldap.c | 108 |
2 files changed, 143 insertions, 0 deletions
diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c index 082e57ecc0..f18ef616f0 100644 --- a/source3/passdb/pdb_interface.c +++ b/source3/passdb/pdb_interface.c @@ -452,6 +452,24 @@ static NTSTATUS context_enum_group_mapping(struct pdb_context *context, num_entries, unix_only); } +static NTSTATUS context_enum_group_memberships(struct pdb_context *context, + const char *username, + gid_t primary_gid, + DOM_SID **sids, gid_t **gids, + int *num_groups) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + if ((!context) || (!context->pdb_methods)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return ret; + } + + return context->pdb_methods-> + enum_group_memberships(context->pdb_methods, username, + primary_gid, sids, gids, num_groups); +} + static NTSTATUS context_find_alias(struct pdb_context *context, const char *name, DOM_SID *sid) { @@ -718,6 +736,7 @@ static NTSTATUS make_pdb_context(struct pdb_context **context) (*context)->pdb_update_group_mapping_entry = context_update_group_mapping_entry; (*context)->pdb_delete_group_mapping_entry = context_delete_group_mapping_entry; (*context)->pdb_enum_group_mapping = context_enum_group_mapping; + (*context)->pdb_enum_group_memberships = context_enum_group_memberships; (*context)->pdb_find_alias = context_find_alias; (*context)->pdb_create_alias = context_create_alias; @@ -1038,6 +1057,21 @@ BOOL pdb_enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap, rmap, num_entries, unix_only)); } +NTSTATUS pdb_enum_group_memberships(const char *username, gid_t primary_gid, + DOM_SID **sids, gid_t **gids, + int *num_groups) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return NT_STATUS_UNSUCCESSFUL; + } + + return pdb_context->pdb_enum_group_memberships(pdb_context, username, + primary_gid, sids, gids, + num_groups); +} + BOOL pdb_find_alias(const char *name, DOM_SID *sid) { struct pdb_context *pdb_context = pdb_get_static_context(False); @@ -1250,6 +1284,7 @@ NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods) (*methods)->update_group_mapping_entry = pdb_default_update_group_mapping_entry; (*methods)->delete_group_mapping_entry = pdb_default_delete_group_mapping_entry; (*methods)->enum_group_mapping = pdb_default_enum_group_mapping; + (*methods)->enum_group_memberships = pdb_default_enum_group_memberships; (*methods)->find_alias = pdb_default_find_alias; (*methods)->create_alias = pdb_default_create_alias; (*methods)->delete_alias = pdb_default_delete_alias; diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index 41d650fad5..685d393eb9 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -2199,6 +2199,113 @@ static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map, return ldapsam_getgroup(methods, filter, map); } +static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods, + const char *username, + gid_t primary_gid, + DOM_SID **sids, gid_t **gids, + int *num_groups) +{ + struct ldapsam_privates *ldap_state = + (struct ldapsam_privates *)methods->private_data; + struct smbldap_state *conn = ldap_state->smbldap_state; + pstring filter; + char *attrs[] = { "gidNumber", "sambaSID", NULL }; + char *escape_name = escape_ldap_string_alloc(username); + int rc; + LDAPMessage *msg = NULL; + LDAPMessage *entry; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + int num_sids, num_gids; + extern DOM_SID global_sid_NULL; + + if (!lp_parm_bool(-1, "ldapsam", "trusted", False)) + return pdb_default_enum_group_memberships(methods, username, + primary_gid, sids, + gids, num_groups); + + *sids = NULL; + num_sids = 0; + + if (escape_name == NULL) + return NT_STATUS_UNSUCCESSFUL; + + pstr_sprintf(filter, "(&(objectClass=posixGroup)" + "(|(memberUid=%s)(gidNumber=%d)))", + username, primary_gid); + + rc = smbldap_search(conn, lp_ldap_group_suffix(), + LDAP_SCOPE_SUBTREE, filter, attrs, 0, &msg); + + if (rc != LDAP_SUCCESS) + goto done; + + num_gids = 0; + *gids = NULL; + + num_sids = 0; + *sids = NULL; + + /* We need to add the primary group as the first gid/sid */ + + add_gid_to_array_unique(primary_gid, gids, &num_gids); + + /* This sid will be replaced later */ + + add_sid_to_array_unique(&global_sid_NULL, sids, &num_sids); + + for (entry = ldap_first_entry(conn->ldap_struct, msg); + entry != NULL; + entry = ldap_next_entry(conn->ldap_struct, entry)) + { + fstring str; + DOM_SID sid; + gid_t gid; + char *end; + + if (!smbldap_get_single_attribute(conn->ldap_struct, + entry, "sambaSID", + str, sizeof(str)-1)) + goto done; + + if (!string_to_sid(&sid, str)) + goto done; + + if (!smbldap_get_single_attribute(conn->ldap_struct, + entry, "gidNumber", + str, sizeof(str)-1)) + goto done; + + gid = strtoul(str, &end, 10); + + if (PTR_DIFF(end, str) != strlen(str)) + goto done; + + if (gid == primary_gid) { + sid_copy(&(*sids)[0], &sid); + } else { + add_gid_to_array_unique(gid, gids, &num_gids); + add_sid_to_array_unique(&sid, sids, &num_sids); + } + } + + if (sid_compare(&global_sid_NULL, &(*sids)[0]) == 0) { + DEBUG(3, ("primary group not found\n")); + goto done; + } + + *num_groups = num_sids; + + result = NT_STATUS_OK; + + done: + + SAFE_FREE(escape_name); + if (msg != NULL) + ldap_msgfree(msg); + + return result; +} + /********************************************************************** *********************************************************************/ @@ -2858,6 +2965,7 @@ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS ** (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry; (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry; (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping; + (*pdb_method)->enum_group_memberships = ldapsam_enum_group_memberships; /* TODO: Setup private data and free */ |