1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-27 03:21:53 +03:00
samba-mirror/source3/libads/ldap_schema.c
Günther Deschner 34d091f1c6 r23839: Try to get the attribute name from schema GUIDs or the display name from
extended rights GUID from ad while dumping the security descriptors's aces.

This would perform much better with a guid cache, but for the rare cases where
it is used

	net ads search cn=mymachine ntSecurityDescriptor -U user%pass

it should be ok for now.

Guenther
(This used to be commit b36913433e)
2007-10-10 12:28:33 -05:00

385 lines
10 KiB
C

/*
Unix SMB/CIFS implementation.
ads (active directory) utility library
Copyright (C) Guenther Deschner 2005-2007
Copyright (C) Gerald (Jerry) Carter 2006
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 3 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
#ifdef HAVE_LDAP
ADS_STATUS ads_get_attrnames_by_oids(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
const char *schema_path,
const char **OIDs, size_t num_OIDs,
char ***OIDs_out, char ***names, size_t *count)
{
ADS_STATUS status;
LDAPMessage *res = NULL;
LDAPMessage *msg;
char *expr = NULL;
const char *attrs[] = { "lDAPDisplayName", "attributeId", NULL };
int i = 0, p = 0;
if (!ads || !mem_ctx || !names || !count || !OIDs || !OIDs_out) {
return ADS_ERROR(LDAP_PARAM_ERROR);
}
if (num_OIDs == 0 || OIDs[0] == NULL) {
return ADS_ERROR_NT(NT_STATUS_NONE_MAPPED);
}
if ((expr = talloc_asprintf(mem_ctx, "(|")) == NULL) {
return ADS_ERROR(LDAP_NO_MEMORY);
}
for (i=0; i<num_OIDs; i++) {
if ((expr = talloc_asprintf_append(expr, "(attributeId=%s)",
OIDs[i])) == NULL) {
return ADS_ERROR(LDAP_NO_MEMORY);
}
}
if ((expr = talloc_asprintf_append(expr, ")")) == NULL) {
return ADS_ERROR(LDAP_NO_MEMORY);
}
status = ads_do_search_retry(ads, schema_path,
LDAP_SCOPE_SUBTREE, expr, attrs, &res);
if (!ADS_ERR_OK(status)) {
return status;
}
*count = ads_count_replies(ads, res);
if (*count == 0 || !res) {
status = ADS_ERROR_NT(NT_STATUS_NONE_MAPPED);
goto out;
}
if (((*names) = TALLOC_ARRAY(mem_ctx, char *, *count)) == NULL) {
status = ADS_ERROR(LDAP_NO_MEMORY);
goto out;
}
if (((*OIDs_out) = TALLOC_ARRAY(mem_ctx, char *, *count)) == NULL) {
status = ADS_ERROR(LDAP_NO_MEMORY);
goto out;
}
for (msg = ads_first_entry(ads, res); msg != NULL;
msg = ads_next_entry(ads, msg)) {
(*names)[p] = ads_pull_string(ads, mem_ctx, msg,
"lDAPDisplayName");
(*OIDs_out)[p] = ads_pull_string(ads, mem_ctx, msg,
"attributeId");
if (((*names)[p] == NULL) || ((*OIDs_out)[p] == NULL)) {
status = ADS_ERROR(LDAP_NO_MEMORY);
goto out;
}
p++;
}
if (*count < num_OIDs) {
status = ADS_ERROR_NT(STATUS_SOME_UNMAPPED);
goto out;
}
status = ADS_ERROR(LDAP_SUCCESS);
out:
ads_msgfree(ads, res);
return status;
}
const char *ads_get_attrname_by_guid(ADS_STRUCT *ads,
const char *schema_path,
TALLOC_CTX *mem_ctx,
const struct GUID *schema_guid)
{
ADS_STATUS rc;
LDAPMessage *res = NULL;
char *expr = NULL;
const char *attrs[] = { "lDAPDisplayName", NULL };
const char *result = NULL;
char *guid_bin = NULL;
if (!ads || !mem_ctx || !schema_guid) {
goto done;
}
guid_bin = guid_binstring(schema_guid);
if (!guid_bin) {
goto done;
}
expr = talloc_asprintf(mem_ctx, "(schemaIDGUID=%s)", guid_bin);
if (!expr) {
goto done;
}
rc = ads_do_search_retry(ads, schema_path, LDAP_SCOPE_SUBTREE,
expr, attrs, &res);
if (!ADS_ERR_OK(rc)) {
goto done;
}
if (ads_count_replies(ads, res) != 1) {
goto done;
}
result = ads_pull_string(ads, mem_ctx, res, "lDAPDisplayName");
done:
SAFE_FREE(guid_bin);
ads_msgfree(ads, res);
return result;
}
const char *ads_get_attrname_by_oid(ADS_STRUCT *ads, const char *schema_path, TALLOC_CTX *mem_ctx, const char * OID)
{
ADS_STATUS rc;
int count = 0;
LDAPMessage *res = NULL;
char *expr = NULL;
const char *attrs[] = { "lDAPDisplayName", NULL };
char *result;
if (ads == NULL || mem_ctx == NULL || OID == NULL) {
goto failed;
}
expr = talloc_asprintf(mem_ctx, "(attributeId=%s)", OID);
if (expr == NULL) {
goto failed;
}
rc = ads_do_search_retry(ads, schema_path, LDAP_SCOPE_SUBTREE,
expr, attrs, &res);
if (!ADS_ERR_OK(rc)) {
goto failed;
}
count = ads_count_replies(ads, res);
if (count == 0 || !res) {
goto failed;
}
result = ads_pull_string(ads, mem_ctx, res, "lDAPDisplayName");
ads_msgfree(ads, res);
return result;
failed:
DEBUG(0,("ads_get_attrname_by_oid: failed to retrieve name for oid: %s\n",
OID));
ads_msgfree(ads, res);
return NULL;
}
/*********************************************************************
*********************************************************************/
ADS_STATUS ads_schema_path(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **schema_path)
{
ADS_STATUS status;
LDAPMessage *res;
const char *schema;
const char *attrs[] = { "schemaNamingContext", NULL };
status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
if (!ADS_ERR_OK(status)) {
return status;
}
if ( (schema = ads_pull_string(ads, mem_ctx, res, "schemaNamingContext")) == NULL ) {
ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
}
if ( (*schema_path = talloc_strdup(mem_ctx, schema)) == NULL ) {
ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
ads_msgfree(ads, res);
return status;
}
/**
* Check for "Services for Unix" or rfc2307 Schema and load some attributes into the ADS_STRUCT
* @param ads connection to ads server
* @param enum mapping type
* @return ADS_STATUS status of search (False if one or more attributes couldn't be
* found in Active Directory)
**/
ADS_STATUS ads_check_posix_schema_mapping(TALLOC_CTX *mem_ctx,
ADS_STRUCT *ads,
enum wb_posix_mapping map_type,
struct posix_schema **s )
{
TALLOC_CTX *ctx = NULL;
ADS_STATUS status;
char **oids_out, **names_out;
size_t num_names;
char *schema_path = NULL;
int i;
struct posix_schema *schema = NULL;
const char *oids_sfu[] = { ADS_ATTR_SFU_UIDNUMBER_OID,
ADS_ATTR_SFU_GIDNUMBER_OID,
ADS_ATTR_SFU_HOMEDIR_OID,
ADS_ATTR_SFU_SHELL_OID,
ADS_ATTR_SFU_GECOS_OID};
const char *oids_sfu20[] = { ADS_ATTR_SFU20_UIDNUMBER_OID,
ADS_ATTR_SFU20_GIDNUMBER_OID,
ADS_ATTR_SFU20_HOMEDIR_OID,
ADS_ATTR_SFU20_SHELL_OID,
ADS_ATTR_SFU20_GECOS_OID};
const char *oids_rfc2307[] = { ADS_ATTR_RFC2307_UIDNUMBER_OID,
ADS_ATTR_RFC2307_GIDNUMBER_OID,
ADS_ATTR_RFC2307_HOMEDIR_OID,
ADS_ATTR_RFC2307_SHELL_OID,
ADS_ATTR_RFC2307_GECOS_OID };
DEBUG(10,("ads_check_posix_schema_mapping for schema mode: %d\n", map_type));
switch (map_type) {
case WB_POSIX_MAP_TEMPLATE:
case WB_POSIX_MAP_UNIXINFO:
DEBUG(10,("ads_check_posix_schema_mapping: nothing to do\n"));
return ADS_ERROR(LDAP_SUCCESS);
case WB_POSIX_MAP_SFU:
case WB_POSIX_MAP_SFU20:
case WB_POSIX_MAP_RFC2307:
break;
default:
DEBUG(0,("ads_check_posix_schema_mapping: "
"unknown enum %d\n", map_type));
return ADS_ERROR(LDAP_PARAM_ERROR);
}
if ( (ctx = talloc_init("ads_check_posix_schema_mapping")) == NULL ) {
return ADS_ERROR(LDAP_NO_MEMORY);
}
if ( (schema = TALLOC_P(mem_ctx, struct posix_schema)) == NULL ) {
TALLOC_FREE( ctx );
return ADS_ERROR(LDAP_NO_MEMORY);
}
status = ads_schema_path(ads, ctx, &schema_path);
if (!ADS_ERR_OK(status)) {
DEBUG(3,("ads_check_posix_mapping: Unable to retrieve schema DN!\n"));
goto done;
}
switch (map_type) {
case WB_POSIX_MAP_SFU:
status = ads_get_attrnames_by_oids(ads, ctx, schema_path, oids_sfu,
ARRAY_SIZE(oids_sfu),
&oids_out, &names_out, &num_names);
break;
case WB_POSIX_MAP_SFU20:
status = ads_get_attrnames_by_oids(ads, ctx, schema_path, oids_sfu20,
ARRAY_SIZE(oids_sfu20),
&oids_out, &names_out, &num_names);
break;
case WB_POSIX_MAP_RFC2307:
status = ads_get_attrnames_by_oids(ads, ctx, schema_path, oids_rfc2307,
ARRAY_SIZE(oids_rfc2307),
&oids_out, &names_out, &num_names);
break;
default:
status = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
break;
}
if (!ADS_ERR_OK(status)) {
DEBUG(3,("ads_check_posix_schema_mapping: failed %s\n",
ads_errstr(status)));
goto done;
}
for (i=0; i<num_names; i++) {
DEBUGADD(10,("\tOID %s has name: %s\n", oids_out[i], names_out[i]));
if (strequal(ADS_ATTR_RFC2307_UIDNUMBER_OID, oids_out[i]) ||
strequal(ADS_ATTR_SFU_UIDNUMBER_OID, oids_out[i]) ||
strequal(ADS_ATTR_SFU20_UIDNUMBER_OID, oids_out[i])) {
schema->posix_uidnumber_attr = talloc_strdup(schema, names_out[i]);
continue;
}
if (strequal(ADS_ATTR_RFC2307_GIDNUMBER_OID, oids_out[i]) ||
strequal(ADS_ATTR_SFU_GIDNUMBER_OID, oids_out[i]) ||
strequal(ADS_ATTR_SFU20_GIDNUMBER_OID, oids_out[i])) {
schema->posix_gidnumber_attr = talloc_strdup(schema, names_out[i]);
continue;
}
if (strequal(ADS_ATTR_RFC2307_HOMEDIR_OID, oids_out[i]) ||
strequal(ADS_ATTR_SFU_HOMEDIR_OID, oids_out[i]) ||
strequal(ADS_ATTR_SFU20_HOMEDIR_OID, oids_out[i])) {
schema->posix_homedir_attr = talloc_strdup(schema, names_out[i]);
continue;
}
if (strequal(ADS_ATTR_RFC2307_SHELL_OID, oids_out[i]) ||
strequal(ADS_ATTR_SFU_SHELL_OID, oids_out[i]) ||
strequal(ADS_ATTR_SFU20_SHELL_OID, oids_out[i])) {
schema->posix_shell_attr = talloc_strdup(schema, names_out[i]);
continue;
}
if (strequal(ADS_ATTR_RFC2307_GECOS_OID, oids_out[i]) ||
strequal(ADS_ATTR_SFU_GECOS_OID, oids_out[i]) ||
strequal(ADS_ATTR_SFU20_GECOS_OID, oids_out[i])) {
schema->posix_gecos_attr = talloc_strdup(schema, names_out[i]);
}
}
if (!schema->posix_uidnumber_attr ||
!schema->posix_gidnumber_attr ||
!schema->posix_homedir_attr ||
!schema->posix_shell_attr ||
!schema->posix_gecos_attr) {
status = ADS_ERROR(LDAP_NO_MEMORY);
TALLOC_FREE( schema );
goto done;
}
*s = schema;
status = ADS_ERROR(LDAP_SUCCESS);
done:
TALLOC_FREE(ctx);
return status;
}
#endif