summaryrefslogtreecommitdiff
path: root/source3/libads
diff options
context:
space:
mode:
authorGünther Deschner <gd@samba.org>2006-05-18 16:08:28 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 11:17:08 -0500
commit39c45ce4f1a0cce9dc23e6d8df3f93bb124a19a0 (patch)
tree29d57a8b855a9f98c42d7b8c4e940419c2d68639 /source3/libads
parente129dc40f71e9b10c293d8d3f923c5636597bf6f (diff)
downloadsamba-39c45ce4f1a0cce9dc23e6d8df3f93bb124a19a0.tar.gz
samba-39c45ce4f1a0cce9dc23e6d8df3f93bb124a19a0.tar.bz2
samba-39c45ce4f1a0cce9dc23e6d8df3f93bb124a19a0.zip
r15697: I take no comments as no objections :)
Expand the "winbind nss info" to also take "rfc2307" to support the plain posix attributes LDAP schema from win2k3-r2. This work is based on patches from Howard Wilkinson and Bob Gautier (and closes bug #3345). Guenther (This used to be commit 52423e01dc209ba5abde808a446287714ed11567)
Diffstat (limited to 'source3/libads')
-rw-r--r--source3/libads/ads_struct.c10
-rw-r--r--source3/libads/ldap.c150
-rw-r--r--source3/libads/ldap_schema.c329
3 files changed, 334 insertions, 155 deletions
diff --git a/source3/libads/ads_struct.c b/source3/libads/ads_struct.c
index 48533c7ffb..e546f2ae8a 100644
--- a/source3/libads/ads_struct.c
+++ b/source3/libads/ads_struct.c
@@ -135,11 +135,11 @@ void ads_destroy(ADS_STRUCT **ads)
SAFE_FREE((*ads)->config.bind_path);
SAFE_FREE((*ads)->config.ldap_server_name);
- SAFE_FREE((*ads)->schema.sfu_uidnumber_attr);
- SAFE_FREE((*ads)->schema.sfu_gidnumber_attr);
- SAFE_FREE((*ads)->schema.sfu_shell_attr);
- SAFE_FREE((*ads)->schema.sfu_homedir_attr);
- SAFE_FREE((*ads)->schema.sfu_gecos_attr);
+ SAFE_FREE((*ads)->schema.posix_uidnumber_attr);
+ SAFE_FREE((*ads)->schema.posix_gidnumber_attr);
+ SAFE_FREE((*ads)->schema.posix_shell_attr);
+ SAFE_FREE((*ads)->schema.posix_homedir_attr);
+ SAFE_FREE((*ads)->schema.posix_gecos_attr);
ZERO_STRUCTP(*ads);
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index b208e58504..4a14527a22 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -2322,49 +2322,6 @@ static time_t ads_parse_time(const char *str)
return timegm(&tm);
}
-
-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;
- void *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;
-}
-
/**
* Find the servers name and realm - this can be done before authentication
* The ldapServiceName field on w2k looks like this:
@@ -2436,113 +2393,6 @@ done:
return status;
}
-/*********************************************************************
-*********************************************************************/
-
-static ADS_STATUS ads_schema_path(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **schema_path)
-{
- ADS_STATUS status;
- void *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 ) {
- return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
- }
-
- if ( (*schema_path = talloc_strdup(mem_ctx, schema)) == NULL ) {
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
-
- ads_msgfree(ads, res);
-
- return status;
-}
-
-/**
- * Check for "Services for Unix"-Schema and load some attributes into the ADS_STRUCT
- * @param ads connection to ads server
- * @return BOOL status of search (False if one or more attributes couldn't be
- * found in Active Directory)
- **/
-BOOL ads_check_sfu_mapping(ADS_STRUCT *ads)
-{
- BOOL ret = False;
- TALLOC_CTX *ctx = NULL;
- const char *gidnumber, *uidnumber, *homedir, *shell, *gecos;
- char *schema_path = NULL;
- ADS_STRUCT *ads_s = ads;
- ADS_STATUS status;
-
- if ( (ctx = talloc_init("ads_check_sfu_mapping")) == NULL ) {
- goto done;
- }
-
- /* establish a new ldap tcp session if necessary */
-
- if ( !ads->ld ) {
- if ( (ads_s = ads_init( ads->server.realm, ads->server.workgroup,
- ads->server.ldap_server )) == NULL )
- {
- goto done;
- }
-
- ads_s->auth.flags = ADS_AUTH_ANON_BIND;
- status = ads_connect( ads_s );
- if ( !ADS_ERR_OK(status))
- goto done;
- }
-
- status = ads_schema_path( ads, ctx, &schema_path );
- if ( !ADS_ERR_OK(status) ) {
- DEBUG(3,("ads_check_sfu_mapping: Unable to retrieve schema DN!\n"));
- goto done;
- }
-
- gidnumber = ads_get_attrname_by_oid(ads_s, schema_path, ctx, ADS_ATTR_SFU_GIDNUMBER_OID);
- if (gidnumber == NULL)
- goto done;
- ads->schema.sfu_gidnumber_attr = SMB_STRDUP(gidnumber);
-
- uidnumber = ads_get_attrname_by_oid(ads_s, schema_path, ctx, ADS_ATTR_SFU_UIDNUMBER_OID);
- if (uidnumber == NULL)
- goto done;
- ads->schema.sfu_uidnumber_attr = SMB_STRDUP(uidnumber);
-
- homedir = ads_get_attrname_by_oid(ads_s, schema_path, ctx, ADS_ATTR_SFU_HOMEDIR_OID);
- if (homedir == NULL)
- goto done;
- ads->schema.sfu_homedir_attr = SMB_STRDUP(homedir);
-
- shell = ads_get_attrname_by_oid(ads_s, schema_path, ctx, ADS_ATTR_SFU_SHELL_OID);
- if (shell == NULL)
- goto done;
- ads->schema.sfu_shell_attr = SMB_STRDUP(shell);
-
- gecos = ads_get_attrname_by_oid(ads_s, schema_path, ctx, ADS_ATTR_SFU_GECOS_OID);
- if (gecos == NULL)
- goto done;
- ads->schema.sfu_gecos_attr = SMB_STRDUP(gecos);
-
- ret = True;
-done:
- /* free any temporary ads connections */
- if ( ads_s != ads ) {
- ads_destroy( &ads_s );
- }
-
- if (ctx) {
- talloc_destroy(ctx);
- }
-
- return ret;
-}
-
/**
* find the domain sid for our domain
* @param ads connection to ads server
diff --git a/source3/libads/ldap_schema.c b/source3/libads/ldap_schema.c
new file mode 100644
index 0000000000..a0c735208f
--- /dev/null
+++ b/source3/libads/ldap_schema.c
@@ -0,0 +1,329 @@
+/*
+ Unix SMB/CIFS implementation.
+ ads (active directory) utility library
+ Copyright (C) Guenther Deschner 2005-2006
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#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;
+ void *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_oid(ADS_STRUCT *ads, const char *schema_path, TALLOC_CTX *mem_ctx, const char * OID)
+{
+ ADS_STATUS rc;
+ int count = 0;
+ void *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;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+static ADS_STATUS ads_schema_path(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **schema_path)
+{
+ ADS_STATUS status;
+ void *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 ) {
+ return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
+ }
+
+ if ( (*schema_path = talloc_strdup(mem_ctx, schema)) == NULL ) {
+ 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 BOOL status of search (False if one or more attributes couldn't be
+ * found in Active Directory)
+ **/
+ADS_STATUS ads_check_posix_schema_mapping(ADS_STRUCT *ads, enum wb_posix_mapping map_type)
+{
+ TALLOC_CTX *ctx = NULL;
+ ADS_STATUS status;
+ char **oids_out, **names_out;
+ size_t num_names;
+ char *schema_path = NULL;
+ ADS_STRUCT *ads_s = ads;
+ int i;
+
+ 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_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\n"));
+
+ 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_RFC2307:
+ break;
+
+ default:
+ DEBUG(0,("ads_check_posix_schema_mapping: "
+ "unknown enum %d\n", map_type));
+ return ADS_ERROR(LDAP_PARAM_ERROR);
+ }
+
+ ads->schema.posix_uidnumber_attr = NULL;
+ ads->schema.posix_gidnumber_attr = NULL;
+ ads->schema.posix_homedir_attr = NULL;
+ ads->schema.posix_shell_attr = NULL;
+ ads->schema.posix_gecos_attr = NULL;
+
+ ctx = talloc_init("ads_check_posix_schema_mapping");
+ if (ctx == NULL) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ /* establish a new ldap tcp session if necessary */
+
+ if (!ads->ld) {
+ if ((ads_s = ads_init(ads->server.realm, ads->server.workgroup,
+ ads->server.ldap_server)) == NULL) {
+ status = ADS_ERROR(LDAP_SERVER_DOWN);
+ goto done;
+ }
+
+ ads_s->auth.flags = ADS_AUTH_ANON_BIND;
+ status = ads_connect(ads_s);
+ if (!ADS_ERR_OK(status)) {
+ goto done;
+ }
+ }
+
+ 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;
+ }
+
+ if (map_type == 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);
+ } else {
+ status = ads_get_attrnames_by_oids(ads, ctx, schema_path, oids_rfc2307,
+ ARRAY_SIZE(oids_rfc2307),
+ &oids_out, &names_out, &num_names);
+ }
+
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(3,("ads_check_posix_schema_mapping: failed %s\n",
+ ads_errstr(status)));
+ goto done;
+ }
+
+ DEBUG(10,("ads_check_posix_schema_mapping: query succeeded, identified: %s\n",
+ wb_posix_map_str(map_type)));
+
+ 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])) {
+ ads->schema.posix_uidnumber_attr = SMB_STRDUP(names_out[i]);
+ }
+ if (strequal(ADS_ATTR_RFC2307_GIDNUMBER_OID, oids_out[i]) ||
+ strequal(ADS_ATTR_SFU_GIDNUMBER_OID, oids_out[i])) {
+ ads->schema.posix_gidnumber_attr = SMB_STRDUP(names_out[i]);
+ }
+ if (strequal(ADS_ATTR_RFC2307_HOMEDIR_OID, oids_out[i]) ||
+ strequal(ADS_ATTR_SFU_HOMEDIR_OID, oids_out[i])) {
+ ads->schema.posix_homedir_attr = SMB_STRDUP(names_out[i]);
+ }
+ if (strequal(ADS_ATTR_RFC2307_SHELL_OID, oids_out[i]) ||
+ strequal(ADS_ATTR_SFU_SHELL_OID, oids_out[i])) {
+ ads->schema.posix_shell_attr = SMB_STRDUP(names_out[i]);
+ }
+ if (strequal(ADS_ATTR_RFC2307_GECOS_OID, oids_out[i]) ||
+ strequal(ADS_ATTR_SFU_GECOS_OID, oids_out[i])) {
+ ads->schema.posix_gecos_attr = SMB_STRDUP(names_out[i]);
+ }
+ }
+
+ talloc_destroy(ctx);
+
+ ADS_ERROR_HAVE_NO_MEMORY(ads->schema.posix_uidnumber_attr);
+ ADS_ERROR_HAVE_NO_MEMORY(ads->schema.posix_gidnumber_attr);
+ ADS_ERROR_HAVE_NO_MEMORY(ads->schema.posix_homedir_attr);
+ ADS_ERROR_HAVE_NO_MEMORY(ads->schema.posix_shell_attr);
+ ADS_ERROR_HAVE_NO_MEMORY(ads->schema.posix_gecos_attr);
+
+ status = ADS_ERROR(LDAP_SUCCESS);
+
+ ads->schema.map_type = map_type;
+done:
+ /* free any temporary ads connections */
+ if (ads_s != ads) {
+ ads_destroy(&ads_s);
+ }
+ if (ctx) {
+ talloc_destroy(ctx);
+ }
+
+ return status;
+}
+
+#endif