mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
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 52423e01dc
)
This commit is contained in:
parent
e129dc40f7
commit
39c45ce4f1
@ -243,7 +243,8 @@ LIBADS_OBJ = libads/ldap.o libads/ldap_printer.o libads/sasl.o \
|
||||
libads/disp_sec.o libads/ads_utils.o libads/ldap_utils.o \
|
||||
libads/authdata.o libads/cldap.o
|
||||
|
||||
LIBADS_SERVER_OBJ = libads/util.o libads/kerberos_verify.o
|
||||
LIBADS_SERVER_OBJ = libads/util.o libads/kerberos_verify.o \
|
||||
libads/ldap_schema.o sam/nss_info.o
|
||||
|
||||
SECRETS_OBJ = passdb/secrets.o passdb/machine_sid.o
|
||||
|
||||
|
@ -4,6 +4,13 @@
|
||||
basically this is a wrapper around ldap
|
||||
*/
|
||||
|
||||
enum wb_posix_mapping {
|
||||
WB_POSIX_MAP_TEMPLATE = 0,
|
||||
WB_POSIX_MAP_SFU = 1,
|
||||
WB_POSIX_MAP_RFC2307 = 2,
|
||||
WB_POSIX_MAP_UNIXINFO = 3
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
void *ld; /* the active ldap structure */
|
||||
struct in_addr ldap_ip; /* the ip of the active connection, if any */
|
||||
@ -42,11 +49,12 @@ typedef struct {
|
||||
|
||||
/* info derived from the servers schema */
|
||||
struct {
|
||||
char *sfu_homedir_attr;
|
||||
char *sfu_shell_attr;
|
||||
char *sfu_uidnumber_attr;
|
||||
char *sfu_gidnumber_attr;
|
||||
char *sfu_gecos_attr;
|
||||
enum wb_posix_mapping map_type;
|
||||
char *posix_homedir_attr;
|
||||
char *posix_shell_attr;
|
||||
char *posix_uidnumber_attr;
|
||||
char *posix_gidnumber_attr;
|
||||
char *posix_gecos_attr;
|
||||
} schema;
|
||||
|
||||
} ADS_STRUCT;
|
||||
@ -83,6 +91,13 @@ typedef void **ADS_MODLIST;
|
||||
#define ADS_ERR_OK(status) ((status.error_type == ENUM_ADS_ERROR_NT) ? NT_STATUS_IS_OK(status.err.nt_status):(status.err.rc == 0))
|
||||
#define ADS_SUCCESS ADS_ERROR(0)
|
||||
|
||||
#define ADS_ERROR_HAVE_NO_MEMORY(x) do { \
|
||||
if (!(x)) {\
|
||||
return ADS_ERROR(LDAP_NO_MEMORY);\
|
||||
}\
|
||||
} while (0)
|
||||
|
||||
|
||||
/* time between reconnect attempts */
|
||||
#define ADS_RECONNECT_TIME 5
|
||||
|
||||
@ -100,6 +115,13 @@ typedef void **ADS_MODLIST;
|
||||
#define ADS_ATTR_SFU_SHELL_OID "1.2.840.113556.1.6.18.1.312"
|
||||
#define ADS_ATTR_SFU_GECOS_OID "1.2.840.113556.1.6.18.1.337"
|
||||
|
||||
/* ldap attribute oids (RFC2307) */
|
||||
#define ADS_ATTR_RFC2307_UIDNUMBER_OID "1.3.6.1.1.1.1.0"
|
||||
#define ADS_ATTR_RFC2307_GIDNUMBER_OID "1.3.6.1.1.1.1.1"
|
||||
#define ADS_ATTR_RFC2307_HOMEDIR_OID "1.3.6.1.1.1.1.3"
|
||||
#define ADS_ATTR_RFC2307_SHELL_OID "1.3.6.1.1.1.1.4"
|
||||
#define ADS_ATTR_RFC2307_GECOS_OID "1.3.6.1.1.1.1.2"
|
||||
|
||||
/* ldap bitwise searches */
|
||||
#define ADS_LDAP_MATCHING_RULE_BIT_AND "1.2.840.113556.1.4.803"
|
||||
#define ADS_LDAP_MATCHING_RULE_BIT_OR "1.2.840.113556.1.4.804"
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
329
source3/libads/ldap_schema.c
Normal file
329
source3/libads/ldap_schema.c
Normal file
@ -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
|
@ -38,6 +38,9 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
|
||||
{
|
||||
ADS_STRUCT *ads;
|
||||
ADS_STATUS status;
|
||||
enum wb_posix_mapping map_type;
|
||||
|
||||
DEBUG(10,("ads_cached_connection\n"));
|
||||
|
||||
if (domain->private_data) {
|
||||
ads = (ADS_STRUCT *)domain->private_data;
|
||||
@ -125,11 +128,18 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (use_nss_info("sfu") && (!ads_check_sfu_mapping(ads))) {
|
||||
DEBUG(0,("ads_cached_connection: failed to check sfu attributes\n"));
|
||||
return NULL;
|
||||
}
|
||||
map_type = get_nss_info(domain->name);
|
||||
|
||||
if ((map_type == WB_POSIX_MAP_RFC2307)||
|
||||
(map_type == WB_POSIX_MAP_SFU)) {
|
||||
|
||||
status = ads_check_posix_schema_mapping(ads, map_type);
|
||||
if (!ADS_ERR_OK(status)) {
|
||||
DEBUG(10,("ads_check_posix_schema_mapping failed "
|
||||
"with: %s\n", ads_errstr(status)));
|
||||
}
|
||||
}
|
||||
|
||||
/* set the flag that says we don't own the memory even
|
||||
though we do so that ads_destroy() won't destroy the
|
||||
structure we pass back by reference */
|
||||
@ -155,6 +165,9 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
|
||||
ADS_ATTR_SFU_HOMEDIR_OID,
|
||||
ADS_ATTR_SFU_SHELL_OID,
|
||||
ADS_ATTR_SFU_GECOS_OID,
|
||||
ADS_ATTR_RFC2307_HOMEDIR_OID,
|
||||
ADS_ATTR_RFC2307_SHELL_OID,
|
||||
ADS_ATTR_RFC2307_GECOS_OID,
|
||||
NULL};
|
||||
int i, count;
|
||||
ADS_STATUS rc;
|
||||
@ -208,13 +221,17 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
|
||||
|
||||
name = ads_pull_username(ads, mem_ctx, msg);
|
||||
|
||||
if (use_nss_info("sfu")) {
|
||||
if (get_nss_info(domain->name) && ads->schema.map_type) {
|
||||
|
||||
DEBUG(10,("pulling posix attributes (%s schema)\n",
|
||||
wb_posix_map_str(ads->schema.map_type)));
|
||||
|
||||
homedir = ads_pull_string(ads, mem_ctx, msg,
|
||||
ads->schema.sfu_homedir_attr);
|
||||
ads->schema.posix_homedir_attr);
|
||||
shell = ads_pull_string(ads, mem_ctx, msg,
|
||||
ads->schema.sfu_shell_attr);
|
||||
ads->schema.posix_shell_attr);
|
||||
gecos = ads_pull_string(ads, mem_ctx, msg,
|
||||
ads->schema.sfu_gecos_attr);
|
||||
ads->schema.posix_gecos_attr);
|
||||
}
|
||||
|
||||
if (gecos == NULL) {
|
||||
@ -446,6 +463,9 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
|
||||
ADS_ATTR_SFU_HOMEDIR_OID,
|
||||
ADS_ATTR_SFU_SHELL_OID,
|
||||
ADS_ATTR_SFU_GECOS_OID,
|
||||
ADS_ATTR_RFC2307_HOMEDIR_OID,
|
||||
ADS_ATTR_RFC2307_SHELL_OID,
|
||||
ADS_ATTR_RFC2307_GECOS_OID,
|
||||
NULL};
|
||||
ADS_STATUS rc;
|
||||
int count;
|
||||
@ -484,13 +504,17 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
|
||||
|
||||
info->acct_name = ads_pull_username(ads, mem_ctx, msg);
|
||||
|
||||
if (use_nss_info("sfu")) {
|
||||
if (get_nss_info(domain->name) && ads->schema.map_type) {
|
||||
|
||||
DEBUG(10,("pulling posix attributes (%s schema)\n",
|
||||
wb_posix_map_str(ads->schema.map_type)));
|
||||
|
||||
info->homedir = ads_pull_string(ads, mem_ctx, msg,
|
||||
ads->schema.sfu_homedir_attr);
|
||||
ads->schema.posix_homedir_attr);
|
||||
info->shell = ads_pull_string(ads, mem_ctx, msg,
|
||||
ads->schema.sfu_shell_attr);
|
||||
ads->schema.posix_shell_attr);
|
||||
info->full_name = ads_pull_string(ads, mem_ctx, msg,
|
||||
ads->schema.sfu_gecos_attr);
|
||||
ads->schema.posix_gecos_attr);
|
||||
}
|
||||
|
||||
if (info->full_name == NULL) {
|
||||
|
@ -43,7 +43,7 @@ static BOOL fillup_pw_field(const char *lp_template,
|
||||
if (out == NULL)
|
||||
return False;
|
||||
|
||||
if (in && !strequal(in,"") && lp_security() == SEC_ADS && use_nss_info("sfu")) {
|
||||
if (in && !strequal(in,"") && lp_security() == SEC_ADS && (get_nss_info(domname))) {
|
||||
safe_strcpy(out, in, sizeof(fstring) - 1);
|
||||
return True;
|
||||
}
|
||||
|
@ -30,14 +30,6 @@
|
||||
#undef DBGC_CLASS
|
||||
#define DBGC_CLASS DBGC_IDMAP
|
||||
|
||||
#ifndef ATTR_UIDNUMBER
|
||||
#define ATTR_UIDNUMBER ADS_ATTR_SFU_UIDNUMBER_OID
|
||||
#endif
|
||||
|
||||
#ifndef ATTR_GIDNUMBER
|
||||
#define ATTR_GIDNUMBER ADS_ATTR_SFU_GIDNUMBER_OID
|
||||
#endif
|
||||
|
||||
#define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
|
||||
|
||||
NTSTATUS init_module(void);
|
||||
@ -48,28 +40,42 @@ static char *ad_idmap_uri = NULL;
|
||||
static char *attr_uidnumber = NULL;
|
||||
static char *attr_gidnumber = NULL;
|
||||
|
||||
static BOOL ad_idmap_check_attr_mapping(ADS_STRUCT *ads)
|
||||
static ADS_STATUS ad_idmap_check_attr_mapping(ADS_STRUCT *ads)
|
||||
{
|
||||
ADS_STATUS status;
|
||||
enum wb_posix_mapping map_type;
|
||||
|
||||
if (attr_uidnumber != NULL && attr_gidnumber != NULL) {
|
||||
return True;
|
||||
return ADS_ERROR(LDAP_SUCCESS);
|
||||
}
|
||||
|
||||
if (use_nss_info("sfu")) {
|
||||
|
||||
if (!ads_check_sfu_mapping(ads)) {
|
||||
DEBUG(0,("ad_idmap_check_attr_mapping: failed to check for SFU schema\n"));
|
||||
return False;
|
||||
SMB_ASSERT(ads->server.workgroup);
|
||||
|
||||
map_type = get_nss_info(ads->server.workgroup);
|
||||
|
||||
if ((map_type == WB_POSIX_MAP_SFU) ||
|
||||
(map_type == WB_POSIX_MAP_RFC2307)) {
|
||||
|
||||
status = ads_check_posix_schema_mapping(ads, map_type);
|
||||
if (ADS_ERR_OK(status)) {
|
||||
attr_uidnumber = SMB_STRDUP(ads->schema.posix_uidnumber_attr);
|
||||
attr_gidnumber = SMB_STRDUP(ads->schema.posix_gidnumber_attr);
|
||||
ADS_ERROR_HAVE_NO_MEMORY(attr_uidnumber);
|
||||
ADS_ERROR_HAVE_NO_MEMORY(attr_gidnumber);
|
||||
return ADS_ERROR(LDAP_SUCCESS);
|
||||
} else {
|
||||
DEBUG(0,("ads_check_posix_schema_mapping failed: %s\n", ads_errstr(status)));
|
||||
/* return status; */
|
||||
}
|
||||
|
||||
attr_uidnumber = SMB_STRDUP(ads->schema.sfu_uidnumber_attr);
|
||||
attr_gidnumber = SMB_STRDUP(ads->schema.sfu_gidnumber_attr);
|
||||
|
||||
} else {
|
||||
attr_uidnumber = SMB_STRDUP("uidNumber");
|
||||
attr_gidnumber = SMB_STRDUP("gidNumber");
|
||||
}
|
||||
|
||||
/* fallback to XAD defaults */
|
||||
attr_uidnumber = SMB_STRDUP("uidNumber");
|
||||
attr_gidnumber = SMB_STRDUP("gidNumber");
|
||||
ADS_ERROR_HAVE_NO_MEMORY(attr_uidnumber);
|
||||
ADS_ERROR_HAVE_NO_MEMORY(attr_gidnumber);
|
||||
|
||||
return True;
|
||||
return ADS_ERROR(LDAP_SUCCESS);
|
||||
}
|
||||
|
||||
static ADS_STRUCT *ad_idmap_cached_connection(void)
|
||||
@ -123,7 +129,8 @@ static ADS_STRUCT *ad_idmap_cached_connection(void)
|
||||
|
||||
ads->is_mine = False;
|
||||
|
||||
if (!ad_idmap_check_attr_mapping(ads)) {
|
||||
status = ad_idmap_check_attr_mapping(ads);
|
||||
if (!ADS_ERR_OK(status)) {
|
||||
DEBUG(1, ("ad_idmap_init: failed to check attribute mapping\n"));
|
||||
return NULL;
|
||||
}
|
||||
@ -168,14 +175,14 @@ static NTSTATUS ad_idmap_get_sid_from_id(DOM_SID *sid, unid_t unid, int id_type)
|
||||
case ID_USERID:
|
||||
if (asprintf(&expr, "(&(|(sAMAccountType=%d)(sAMAccountType=%d)(sAMAccountType=%d))(%s=%d))",
|
||||
ATYPE_NORMAL_ACCOUNT, ATYPE_WORKSTATION_TRUST, ATYPE_INTERDOMAIN_TRUST,
|
||||
ATTR_UIDNUMBER, (int)unid.uid) == -1) {
|
||||
ads->schema.posix_uidnumber_attr, (int)unid.uid) == -1) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
break;
|
||||
case ID_GROUPID:
|
||||
if (asprintf(&expr, "(&(|(sAMAccountType=%d)(sAMAccountType=%d))(%s=%d))",
|
||||
ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_LOCAL_GROUP,
|
||||
ATTR_GIDNUMBER, (int)unid.gid) == -1) {
|
||||
ads->schema.posix_gidnumber_attr, (int)unid.gid) == -1) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
break;
|
||||
@ -228,7 +235,11 @@ static NTSTATUS ad_idmap_get_id_from_sid(unid_t *unid, int *id_type, const DOM_S
|
||||
{
|
||||
ADS_STATUS rc;
|
||||
NTSTATUS status = NT_STATUS_NONE_MAPPED;
|
||||
const char *attrs[] = { "sAMAccountType", ATTR_UIDNUMBER, ATTR_GIDNUMBER, NULL };
|
||||
const char *attrs[] = { "sAMAccountType", ADS_ATTR_SFU_UIDNUMBER_OID,
|
||||
ADS_ATTR_SFU_GIDNUMBER_OID,
|
||||
ADS_ATTR_RFC2307_UIDNUMBER_OID,
|
||||
ADS_ATTR_RFC2307_GIDNUMBER_OID,
|
||||
NULL };
|
||||
void *res = NULL;
|
||||
void *msg = NULL;
|
||||
char *expr = NULL;
|
||||
|
@ -110,17 +110,3 @@ NTSTATUS idmap_sid_to_gid(const DOM_SID *sid, gid_t *gid, uint32 flags)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* placeholder for checking lp_winbind_nss_info() */
|
||||
BOOL use_nss_info(const char *info)
|
||||
{
|
||||
int i;
|
||||
const char **list = lp_winbind_nss_info();
|
||||
|
||||
for (i=0; list[i]; i++) {
|
||||
if (strequal(list[i], info))
|
||||
return True;
|
||||
}
|
||||
|
||||
return False;
|
||||
}
|
||||
|
111
source3/sam/nss_info.c
Normal file
111
source3/sam/nss_info.c
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
nss info helpers
|
||||
Copyright (C) Guenther Deschner 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"
|
||||
|
||||
#undef DBGC_CLASS
|
||||
#define DBGC_CLASS DBGC_IDMAP
|
||||
|
||||
/* winbind nss info = rfc2307 SO36:sfu FHAIN:rfc2307 PANKOW:template
|
||||
*
|
||||
* syntax is:
|
||||
* 1st param: default setting
|
||||
* following ":" separated list elements:
|
||||
* DOMAIN:setting
|
||||
* setting can be one of "sfu", "rfc2307", "template", "unixinfo"
|
||||
*/
|
||||
|
||||
enum wb_posix_mapping get_nss_info(const char *domain_name)
|
||||
{
|
||||
const char **list = lp_winbind_nss_info();
|
||||
enum wb_posix_mapping map_templ = WB_POSIX_MAP_TEMPLATE;
|
||||
int i;
|
||||
|
||||
DEBUG(11,("get_nss_info for %s\n", domain_name));
|
||||
|
||||
if (!lp_winbind_nss_info() || !*lp_winbind_nss_info()) {
|
||||
return WB_POSIX_MAP_TEMPLATE;
|
||||
}
|
||||
|
||||
if ((map_templ = wb_posix_map_type(list[0])) == -1) {
|
||||
DEBUG(0,("get_nss_info: invalid setting: %s\n", list[0]));
|
||||
return WB_POSIX_MAP_TEMPLATE;
|
||||
}
|
||||
|
||||
DEBUG(11,("get_nss_info: using \"%s\" by default\n", list[0]));
|
||||
|
||||
for (i=0; list[i]; i++) {
|
||||
|
||||
const char *p = list[i];
|
||||
fstring tok;
|
||||
|
||||
if (!next_token(&p, tok, ":", sizeof(tok))) {
|
||||
DEBUG(0,("get_nss_info: no \":\" delimitier found\n"));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strequal(tok, domain_name)) {
|
||||
|
||||
enum wb_posix_mapping type;
|
||||
|
||||
if ((type = wb_posix_map_type(p)) == -1) {
|
||||
DEBUG(0,("get_nss_info: invalid setting: %s\n", p));
|
||||
/* return WB_POSIX_MAP_TEMPLATE; */
|
||||
continue;
|
||||
}
|
||||
|
||||
DEBUG(11,("get_nss_info: using \"%s\" for domain: %s\n", p, tok));
|
||||
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
return map_templ;
|
||||
}
|
||||
|
||||
const char *wb_posix_map_str(enum wb_posix_mapping mtype)
|
||||
{
|
||||
switch (mtype) {
|
||||
case WB_POSIX_MAP_TEMPLATE:
|
||||
return "template";
|
||||
case WB_POSIX_MAP_SFU:
|
||||
return "sfu";
|
||||
case WB_POSIX_MAP_RFC2307:
|
||||
return "rfc2307";
|
||||
case WB_POSIX_MAP_UNIXINFO:
|
||||
return "unixinfo";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
enum wb_posix_mapping wb_posix_map_type(const char *map_str)
|
||||
{
|
||||
if (strequal(map_str, "template"))
|
||||
return WB_POSIX_MAP_TEMPLATE;
|
||||
else if (strequal(map_str, "sfu"))
|
||||
return WB_POSIX_MAP_SFU;
|
||||
else if (strequal(map_str, "rfc2307"))
|
||||
return WB_POSIX_MAP_RFC2307;
|
||||
else if (strequal(map_str, "unixinfo"))
|
||||
return WB_POSIX_MAP_UNIXINFO;
|
||||
|
||||
return -1;
|
||||
}
|
Loading…
Reference in New Issue
Block a user