sdap.c revision fcb8e3f1f49bb34c409d8dbd75889eb72be05517
/*
SSSD
LDAP Helper routines
Copyright (C) Simo Sorce <ssorce@redhat.com>
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 "util/crypto/sss_crypto.h"
#include "providers/ldap/ldap_common.h"
#include "providers/ldap/sdap_range.h"
/* =Retrieve-Options====================================================== */
struct sdap_attr_map *src_map,
int num_entries,
struct sdap_attr_map **_map)
{
struct sdap_attr_map *map;
int i;
if (!map) {
return ENOMEM;
}
for (i = 0; i < num_entries; i++) {
return ENOMEM;
}
return ENOMEM;
}
} else {
}
}
/* Include the sentinel */
return EOK;
}
struct confdb_ctx *cdb,
const char *conf_path,
struct sdap_attr_map *def_map,
int num_entries,
struct sdap_attr_map **_map)
{
struct sdap_attr_map *map;
char *name;
int i, ret;
if (!map) {
return ENOMEM;
}
for (i = 0; i < num_entries; i++) {
&name);
return EINVAL;
}
if (name) {
"Could not sanitize attribute [%s]\n", name);
return EINVAL;
}
} else {
}
return EINVAL;
}
}
return EOK;
}
/* =Parse-msg============================================================= */
bool disable_range_retrieval)
{
struct sysdb_attrs *attrs;
struct ldb_val v;
char *str;
int lerrno;
int a, i, ret;
const char *name;
bool store;
bool base64;
char *base_attr;
lerrno = 0;
if (ret != LDAP_OPT_SUCCESS) {
}
if (!attrs) {
goto done;
}
if (!str) {
goto done;
}
if (_dn) {
if (!dn) {
goto done;
}
}
if (map) {
if (!vals) {
"Unknown entry type, no objectClasses found!\n");
goto done;
}
for (i = 0; vals[i]; i++) {
/* the objectclass is always the first name in the map */
/* ok it's an entry of the right type */
break;
}
}
if (!vals[i]) {
goto done;
}
}
if (!str) {
"Entry has no attributes [%d(%s)]!?\n",
if (map) {
goto done;
}
}
while (str) {
base64 = false;
switch(ret) {
case EAGAIN:
/* This attribute contained range values and needs more to
* be retrieved
*/
/* TODO: return the set of attributes that need additional retrieval
* For now, we'll continue below and treat it as regular values.
*/
/* FALLTHROUGH */
case ECANCELED:
/* FALLTHROUGH */
case EOK:
break;
default:
"Could not determine if attribute [%s] was ranged\n", str);
goto done;
}
if (map) {
for (a = 1; a < attrs_num; a++) {
/* check if this attr is valid with the chosen schema */
/* check if it is an attr we are interested in */
}
/* interesting attr */
if (a < attrs_num) {
store = true;
base64 = true;
}
} else {
store = false;
}
} else {
store = true;
}
store = false;
}
if (store) {
if (!vals) {
if (lerrno != LDAP_SUCCESS) {
goto done;
}
"Attribute [%s] has no values, skipping.\n", str);
} else {
if (!vals[0]) {
"Missing value after ldap_get_values() ??\n");
goto done;
}
for (i = 0; vals[i]; i++) {
"Value of attribute [%s] is empty. "
"Skipping this value.\n", str);
continue;
}
if (base64) {
if (!v.data) {
goto done;
}
} else {
}
}
}
}
}
if (lerrno) {
goto done;
}
done:
return ret;
}
/* Parses an LDAPDerefRes into sdap_deref_attrs structure */
struct sdap_attr_map_info *minfo,
struct sdap_deref_attrs ***_res)
{
const char *orig_dn;
const char **ocs;
struct sdap_attr_map *map;
int num_attrs;
const char *name;
struct sdap_deref_attrs **res;
if (!res) {
goto done;
}
for (i=0; i < num_maps; i++) {
if (!res[i]) {
goto done;
}
}
goto done;
}
"Dereferenced DN: %s\n", orig_dn);
"Dereferenced entry [%s] has no attributes\n",
orig_dn);
goto done;
}
"No value for objectClass, skipping\n");
continue;
}
if (!ocs) {
goto done;
}
for (i=0; i<len; i++) {
if (!ocs[i]) {
goto done;
}
}
break;
}
}
if (!ocs) {
"Unknown entry type, no objectClasses found!\n");
goto done;
}
for (i=0; ocs[i]; i++) {
/* the objectclass is always the first name in the map */
"Found map for objectclass '%s'\n", ocs[i]);
break;
}
}
if (!map) continue;
goto done;
}
orig_dn);
if (ret) {
goto done;
}
for (a = 1; a < num_attrs; a++) {
/* check if this attr is valid with the chosen schema */
/* check if it is an attr we are interested in */
}
/* interesting attr */
if (a < num_attrs) {
} else {
continue;
}
"No value for attribute %s, skipping\n", name);
continue;
}
}
}
}
done:
return ret;
}
/* =Get-DN-from-message=================================================== */
{
char *str;
int lerrno;
int ret;
lerrno = 0;
if (ret != LDAP_OPT_SUCCESS) {
}
if (!str) {
return EIO;
}
return EOK;
}
{
int ret;
const char *tls_opt;
if (tls_opt) {
}
}
}
}
}
else {
return EINVAL;
}
/* LDAP_OPT_X_TLS_REQUIRE_CERT has to be set as a global option,
if (ret != LDAP_OPT_SUCCESS) {
return EIO;
}
}
if (tls_opt) {
if (ret != LDAP_OPT_SUCCESS) {
return EIO;
}
}
if (tls_opt) {
if (ret != LDAP_OPT_SUCCESS) {
return EIO;
}
}
if (tls_opt) {
if (ret != LDAP_OPT_SUCCESS) {
return EIO;
}
}
if (tls_opt) {
if (ret != LDAP_OPT_SUCCESS) {
return EIO;
}
}
if (tls_opt) {
if (ret != LDAP_OPT_SUCCESS) {
return EIO;
}
}
return EOK;
}
{
int i;
if (!val) {
return false;
}
for (i = 0; i < l->num_vals; i++) {
continue;
}
return true;
}
return false;
}
{
int i;
return ENOMEM;
}
for (i = 0; i < num; i++) {
return ENOMEM;
}
}
return EOK;
}
struct sdap_handle *sh)
{
int ret;
int i;
if (ret) {
return ret;
}
if (ret) {
return ret;
}
if (ret) {
return ret;
}
}
}
return EOK;
}
struct ldb_message_element *el)
{
if (el->num_values == 0) {
}
} else {
}
return str;
}
struct sysdb_attrs *rootdse)
{
int i;
char *naming_context = NULL;
SDAP_ROOTDSE_ATTR_NAMING_CONTEXTS) == 0) {
}
}
"No attributes [%s] or [%s] found in rootDSE.\n",
} else {
"Using value from [%s] as naming context.\n",
}
"Using value from [%s] as naming context.\n",
}
}
/* Some directory servers such as Novell eDirectory will return
* a zero-length namingContexts value in some situations. In this
* case, we should return it as NULL so things fail gracefully.
*/
}
return naming_context;
}
struct sdap_domain *sdom,
enum sdap_basic_opt class,
char *naming_context)
{
struct sdap_search_base ***bases;
switch(class) {
case SDAP_SEARCH_BASE:
break;
case SDAP_USER_SEARCH_BASE:
break;
case SDAP_GROUP_SEARCH_BASE:
break;
break;
case SDAP_SUDO_SEARCH_BASE:
break;
case SDAP_SERVICE_SEARCH_BASE:
break;
case SDAP_AUTOFS_SEARCH_BASE:
break;
default:
return EINVAL;
}
"Setting option [%s] to [%s].\n",
goto done;
}
done:
return ret;
}
struct sdap_options *opts,
struct sdap_domain *sdom)
{
int ret;
char *naming_context = NULL;
if (!sdom->search_bases
|| !sdom->user_search_bases
|| !sdom->group_search_bases
|| !sdom->sudo_search_bases
|| !sdom->autofs_search_bases) {
if (naming_context == NULL) {
/* This has to be non-fatal, since some servers offer
* multiple namingContexts entries. We will just
* add NULL checks for the search bases in the lookups.
*/
goto done;
}
}
/* Default */
if (!sdom->search_bases) {
}
/* Users */
if (!sdom->user_search_bases) {
}
/* Groups */
if (!sdom->group_search_bases) {
}
/* Netgroups */
if (!sdom->netgroup_search_bases) {
}
/* Sudo */
if (!sdom->sudo_search_bases) {
}
/* Services */
if (!sdom->service_search_bases) {
}
/* autofs */
if (!sdom->autofs_search_bases) {
}
done:
return ret;
}
const char *server,
struct sysdb_attrs *rootdse,
struct sdap_options *opts,
struct sdap_server_opts **srv_opts)
{
struct sdap_server_opts *so;
struct {
const char *last_name;
const char *entry_name;
{ SDAP_AD_LAST_USN, SDAP_AD_USN },
const char *last_usn_name;
const char *last_usn_value;
const char *entry_usn_name;
int ret;
int i;
if (!so) {
return ENOMEM;
}
return ENOMEM;
}
if (rootdse) {
if (last_usn_name) {
switch (ret) {
case ENOENT:
"%s configured but not found in rootdse!\n",
break;
case ERANGE:
"Multiple values of %s found in rootdse!\n",
break;
default:
"Unkown error (%d) checking rootdse!\n", ret);
}
} else {
if (!entry_usn_name) {
"%s found in rootdse but %s is not set!\n",
} else {
so->supports_usn = true;
"USN is not valid (value: %s)\n", last_usn_value);
} else {
}
}
}
} else {
/* no usn option configure, let's try to autodetect. */
/* Fixate discovered configuration */
so->supports_usn = true;
"USN is not valid (value: %s)\n", last_usn_value);
} else {
}
break;
}
}
}
/* Detect Active Directory version if available */
&dc_level);
/* Validate that the DC level matches an expected value */
switch(dc_level) {
case DS_BEHAVIOR_WIN2000:
case DS_BEHAVIOR_WIN2003:
case DS_BEHAVIOR_WIN2008:
case DS_BEHAVIOR_WIN2008R2:
case DS_BEHAVIOR_WIN2012:
"Setting AD compatibility level to [%d]\n",
break;
default:
"Received invalid value for AD compatibility level. "
"Continuing without AD performance enhancements\n");
}
"Error detecting Active Directory compatibility level "
"(%s). Continuing without AD performance enhancements\n",
}
}
if (!last_usn_name) {
"No known USN scheme is supported by this server!\n");
if (!entry_usn_name) {
"Will use modification timestamp as usn!\n");
}
}
}
}
}
if (opts->sudorule_map &&
}
return EOK;
}
struct sdap_server_opts **srv_opts)
{
return;
}
return;
}
/* discard if same as previous so we do not reset max usn values
* unnecessarily */
return;
}
}
{
int i;
if (filter) {
i = 0;
while (filter[i]) {
return true;
}
i++;
}
}
return false;
}
struct sdap_attr_map *map,
const char **filter,
const char ***_attrs,
{
const char **attrs;
int i, j;
/* Assume that all entries in the map have values */
if (!attrs) {
goto done;
}
/* first attribute is "objectclass" not the specifc one */
/* add the others */
for (i = j = 1; i < size; i++) {
j++;
}
}
/* Trim down the used memory if some attributes were NULL */
if (!attrs) {
goto done;
}
if (attr_count) *attr_count = j;
done:
return ret;
}
{
int ret;
if (ret != LDAP_SUCCESS) {
"sss_ldap_control_create failed [%d][%s].\n",
}
} else {
"Server does not support the requested control [%s].\n", oid);
}
return ret;
}
{
char *str;
struct ldb_message_element *el;
} else if (ret) {
return ret;
}
return EINVAL;
}
if (!str) {
return ENOMEM;
}
return EOK;
}
static errno_t
const char *attr_name,
struct sysdb_attrs *attrs,
struct sss_domain_info *dom,
const char **_primary_name)
{
char *name;
return EINVAL;
}
"Failed to format original name [%s]\n", orig_name);
return ENOMEM;
}
*_primary_name = name;
return EOK;
}
struct sdap_options *opts,
struct sysdb_attrs *attrs,
struct sss_domain_info *dom,
const char **_user_name)
{
return sdap_get_primary_name(memctx,
}
struct sdap_options *opts,
struct sysdb_attrs *attrs,
struct sss_domain_info *dom,
const char **_group_name)
{
return sdap_get_primary_name(memctx,
}
struct sdap_options *opts,
struct sysdb_attrs *attrs,
struct sss_domain_info *dom,
const char **_netgroup_name)
{
return sdap_get_primary_name(memctx,
}