Blame nslcd/attmap.c

Packit 6bd9ab
/*
Packit 6bd9ab
   attmap.c - attribute mapping values and functions
Packit 6bd9ab
   This file is part of the nss-pam-ldapd library.
Packit 6bd9ab
Packit 6bd9ab
   Copyright (C) 2007-2014 Arthur de Jong
Packit 6bd9ab
Packit 6bd9ab
   This library is free software; you can redistribute it and/or
Packit 6bd9ab
   modify it under the terms of the GNU Lesser General Public
Packit 6bd9ab
   License as published by the Free Software Foundation; either
Packit 6bd9ab
   version 2.1 of the License, or (at your option) any later version.
Packit 6bd9ab
Packit 6bd9ab
   This library is distributed in the hope that it will be useful,
Packit 6bd9ab
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6bd9ab
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6bd9ab
   Lesser General Public License for more details.
Packit 6bd9ab
Packit 6bd9ab
   You should have received a copy of the GNU Lesser General Public
Packit 6bd9ab
   License along with this library; if not, write to the Free Software
Packit 6bd9ab
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit 6bd9ab
   02110-1301 USA
Packit 6bd9ab
*/
Packit 6bd9ab
Packit 6bd9ab
#include "config.h"
Packit 6bd9ab
Packit 6bd9ab
#include <stdlib.h>
Packit 6bd9ab
#include <strings.h>
Packit 6bd9ab
Packit 6bd9ab
#include "attmap.h"
Packit 6bd9ab
#include "log.h"
Packit 6bd9ab
#include "common/expr.h"
Packit 6bd9ab
Packit 6bd9ab
/* these are the bases that are defined per database */
Packit 6bd9ab
extern const char *alias_bases[];
Packit 6bd9ab
extern const char *ether_bases[];
Packit 6bd9ab
extern const char *group_bases[];
Packit 6bd9ab
extern const char *host_bases[];
Packit 6bd9ab
extern const char *netgroup_bases[];
Packit 6bd9ab
extern const char *network_bases[];
Packit 6bd9ab
extern const char *passwd_bases[];
Packit 6bd9ab
extern const char *protocol_bases[];
Packit 6bd9ab
extern const char *rpc_bases[];
Packit 6bd9ab
extern const char *service_bases[];
Packit 6bd9ab
extern const char *shadow_bases[];
Packit 6bd9ab
Packit 6bd9ab
const char **base_get_var(enum ldap_map_selector map)
Packit 6bd9ab
{
Packit 6bd9ab
  switch (map)
Packit 6bd9ab
  {
Packit 6bd9ab
    case LM_ALIASES:   return alias_bases;
Packit 6bd9ab
    case LM_ETHERS:    return ether_bases;
Packit 6bd9ab
    case LM_GROUP:     return group_bases;
Packit 6bd9ab
    case LM_HOSTS:     return host_bases;
Packit 6bd9ab
    case LM_NETGROUP:  return netgroup_bases;
Packit 6bd9ab
    case LM_NETWORKS:  return network_bases;
Packit 6bd9ab
    case LM_PASSWD:    return passwd_bases;
Packit 6bd9ab
    case LM_PROTOCOLS: return protocol_bases;
Packit 6bd9ab
    case LM_RPC:       return rpc_bases;
Packit 6bd9ab
    case LM_SERVICES:  return service_bases;
Packit 6bd9ab
    case LM_SHADOW:    return shadow_bases;
Packit 6bd9ab
    case LM_NFSIDMAP:
Packit 6bd9ab
    case LM_NONE:
Packit 6bd9ab
    default:           return NULL;
Packit 6bd9ab
  }
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
/* these are the scopes that are defined per database */
Packit 6bd9ab
extern int alias_scope;
Packit 6bd9ab
extern int ether_scope;
Packit 6bd9ab
extern int group_scope;
Packit 6bd9ab
extern int host_scope;
Packit 6bd9ab
extern int netgroup_scope;
Packit 6bd9ab
extern int network_scope;
Packit 6bd9ab
extern int passwd_scope;
Packit 6bd9ab
extern int protocol_scope;
Packit 6bd9ab
extern int rpc_scope;
Packit 6bd9ab
extern int service_scope;
Packit 6bd9ab
extern int shadow_scope;
Packit 6bd9ab
Packit 6bd9ab
int *scope_get_var(enum ldap_map_selector map)
Packit 6bd9ab
{
Packit 6bd9ab
  switch (map)
Packit 6bd9ab
  {
Packit 6bd9ab
    case LM_ALIASES:   return &alias_scope;
Packit 6bd9ab
    case LM_ETHERS:    return &ether_scope;
Packit 6bd9ab
    case LM_GROUP:     return &group_scope;
Packit 6bd9ab
    case LM_HOSTS:     return &host_scope;
Packit 6bd9ab
    case LM_NETGROUP:  return &netgroup_scope;
Packit 6bd9ab
    case LM_NETWORKS:  return &network_scope;
Packit 6bd9ab
    case LM_PASSWD:    return &passwd_scope;
Packit 6bd9ab
    case LM_PROTOCOLS: return &protocol_scope;
Packit 6bd9ab
    case LM_RPC:       return &rpc_scope;
Packit 6bd9ab
    case LM_SERVICES:  return &service_scope;
Packit 6bd9ab
    case LM_SHADOW:    return &shadow_scope;
Packit 6bd9ab
    case LM_NFSIDMAP:
Packit 6bd9ab
    case LM_NONE:
Packit 6bd9ab
    default:           return NULL;
Packit 6bd9ab
  }
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
/* these are the filters that are defined per database */
Packit 6bd9ab
extern const char *alias_filter;
Packit 6bd9ab
extern const char *ether_filter;
Packit 6bd9ab
extern const char *group_filter;
Packit 6bd9ab
extern const char *host_filter;
Packit 6bd9ab
extern const char *netgroup_filter;
Packit 6bd9ab
extern const char *network_filter;
Packit 6bd9ab
extern const char *passwd_filter;
Packit 6bd9ab
extern const char *protocol_filter;
Packit 6bd9ab
extern const char *rpc_filter;
Packit 6bd9ab
extern const char *service_filter;
Packit 6bd9ab
extern const char *shadow_filter;
Packit 6bd9ab
Packit 6bd9ab
const char **filter_get_var(enum ldap_map_selector map)
Packit 6bd9ab
{
Packit 6bd9ab
  switch (map)
Packit 6bd9ab
  {
Packit 6bd9ab
    case LM_ALIASES:   return &alias_filter;
Packit 6bd9ab
    case LM_ETHERS:    return &ether_filter;
Packit 6bd9ab
    case LM_GROUP:     return &group_filter;
Packit 6bd9ab
    case LM_HOSTS:     return &host_filter;
Packit 6bd9ab
    case LM_NETGROUP:  return &netgroup_filter;
Packit 6bd9ab
    case LM_NETWORKS:  return &network_filter;
Packit 6bd9ab
    case LM_PASSWD:    return &passwd_filter;
Packit 6bd9ab
    case LM_PROTOCOLS: return &protocol_filter;
Packit 6bd9ab
    case LM_RPC:       return &rpc_filter;
Packit 6bd9ab
    case LM_SERVICES:  return &service_filter;
Packit 6bd9ab
    case LM_SHADOW:    return &shadow_filter;
Packit 6bd9ab
    case LM_NFSIDMAP:
Packit 6bd9ab
    case LM_NONE:
Packit 6bd9ab
    default:           return NULL;
Packit 6bd9ab
  }
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
const char **attmap_get_var(enum ldap_map_selector map, const char *name)
Packit 6bd9ab
{
Packit 6bd9ab
  if (map == LM_ALIASES)
Packit 6bd9ab
  {
Packit 6bd9ab
    if (strcasecmp(name, "cn") == 0)                return &attmap_alias_cn;
Packit 6bd9ab
    if (strcasecmp(name, "rfc822MailMember") == 0)  return &attmap_alias_rfc822MailMember;
Packit 6bd9ab
  }
Packit 6bd9ab
  else if (map == LM_ETHERS)
Packit 6bd9ab
  {
Packit 6bd9ab
    if (strcasecmp(name, "cn") == 0)                return &attmap_ether_cn;
Packit 6bd9ab
    if (strcasecmp(name, "macAddress") == 0)        return &attmap_ether_macAddress;
Packit 6bd9ab
  }
Packit 6bd9ab
  else if (map == LM_GROUP)
Packit 6bd9ab
  {
Packit 6bd9ab
    if (strcasecmp(name, "cn") == 0)                return &attmap_group_cn;
Packit 6bd9ab
    if (strcasecmp(name, "userPassword") == 0)      return &attmap_group_userPassword;
Packit 6bd9ab
    if (strcasecmp(name, "gidNumber") == 0)         return &attmap_group_gidNumber;
Packit 6bd9ab
    if (strcasecmp(name, "memberUid") == 0)         return &attmap_group_memberUid;
Packit 6bd9ab
    if (strcasecmp(name, "member") == 0)            return &attmap_group_member;
Packit 6bd9ab
  }
Packit 6bd9ab
  else if (map == LM_HOSTS)
Packit 6bd9ab
  {
Packit 6bd9ab
    if (strcasecmp(name, "cn") == 0)                return &attmap_host_cn;
Packit 6bd9ab
    if (strcasecmp(name, "ipHostNumber") == 0)      return &attmap_host_ipHostNumber;
Packit 6bd9ab
  }
Packit 6bd9ab
  else if (map == LM_NETGROUP)
Packit 6bd9ab
  {
Packit 6bd9ab
    if (strcasecmp(name, "cn") == 0)                return &attmap_netgroup_cn;
Packit 6bd9ab
    if (strcasecmp(name, "nisNetgroupTriple") == 0) return &attmap_netgroup_nisNetgroupTriple;
Packit 6bd9ab
    if (strcasecmp(name, "memberNisNetgroup") == 0) return &attmap_netgroup_memberNisNetgroup;
Packit 6bd9ab
  }
Packit 6bd9ab
  else if (map == LM_NETWORKS)
Packit 6bd9ab
  {
Packit 6bd9ab
    if (strcasecmp(name, "cn") == 0)                return &attmap_network_cn;
Packit 6bd9ab
    if (strcasecmp(name, "ipNetworkNumber") == 0)   return &attmap_network_ipNetworkNumber;
Packit 6bd9ab
  }
Packit 6bd9ab
  else if (map == LM_PASSWD)
Packit 6bd9ab
  {
Packit 6bd9ab
    if (strcasecmp(name, "uid") == 0)               return &attmap_passwd_uid;
Packit 6bd9ab
    if (strcasecmp(name, "userPassword") == 0)      return &attmap_passwd_userPassword;
Packit 6bd9ab
    if (strcasecmp(name, "uidNumber") == 0)         return &attmap_passwd_uidNumber;
Packit 6bd9ab
    if (strcasecmp(name, "gidNumber") == 0)         return &attmap_passwd_gidNumber;
Packit 6bd9ab
    if (strcasecmp(name, "gecos") == 0)             return &attmap_passwd_gecos;
Packit 6bd9ab
    if (strcasecmp(name, "homeDirectory") == 0)     return &attmap_passwd_homeDirectory;
Packit 6bd9ab
    if (strcasecmp(name, "loginShell") == 0)        return &attmap_passwd_loginShell;
Packit 6bd9ab
  }
Packit 6bd9ab
  else if (map == LM_PROTOCOLS)
Packit 6bd9ab
  {
Packit 6bd9ab
    if (strcasecmp(name, "cn") == 0)                return &attmap_protocol_cn;
Packit 6bd9ab
    if (strcasecmp(name, "ipProtocolNumber") == 0)  return &attmap_protocol_ipProtocolNumber;
Packit 6bd9ab
  }
Packit 6bd9ab
  else if (map == LM_RPC)
Packit 6bd9ab
  {
Packit 6bd9ab
    if (strcasecmp(name, "cn") == 0)                return &attmap_rpc_cn;
Packit 6bd9ab
    if (strcasecmp(name, "oncRpcNumber") == 0)      return &attmap_rpc_oncRpcNumber;
Packit 6bd9ab
  }
Packit 6bd9ab
  else if (map == LM_SERVICES)
Packit 6bd9ab
  {
Packit 6bd9ab
    if (strcasecmp(name, "cn") == 0)                return &attmap_service_cn;
Packit 6bd9ab
    if (strcasecmp(name, "ipServicePort") == 0)     return &attmap_service_ipServicePort;
Packit 6bd9ab
    if (strcasecmp(name, "ipServiceProtocol") == 0) return &attmap_service_ipServiceProtocol;
Packit 6bd9ab
  }
Packit 6bd9ab
  else if (map == LM_SHADOW)
Packit 6bd9ab
  {
Packit 6bd9ab
    if (strcasecmp(name, "uid") == 0)               return &attmap_shadow_uid;
Packit 6bd9ab
    if (strcasecmp(name, "userPassword") == 0)      return &attmap_shadow_userPassword;
Packit 6bd9ab
    if (strcasecmp(name, "shadowLastChange") == 0)  return &attmap_shadow_shadowLastChange;
Packit 6bd9ab
    if (strcasecmp(name, "shadowMin") == 0)         return &attmap_shadow_shadowMin;
Packit 6bd9ab
    if (strcasecmp(name, "shadowMax") == 0)         return &attmap_shadow_shadowMax;
Packit 6bd9ab
    if (strcasecmp(name, "shadowWarning") == 0)     return &attmap_shadow_shadowWarning;
Packit 6bd9ab
    if (strcasecmp(name, "shadowInactive") == 0)    return &attmap_shadow_shadowInactive;
Packit 6bd9ab
    if (strcasecmp(name, "shadowExpire") == 0)      return &attmap_shadow_shadowExpire;
Packit 6bd9ab
    if (strcasecmp(name, "shadowFlag") == 0)        return &attmap_shadow_shadowFlag;
Packit 6bd9ab
  }
Packit 6bd9ab
  return NULL;
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
const char *attmap_set_mapping(const char **var, const char *value)
Packit 6bd9ab
{
Packit 6bd9ab
  /* check if we are setting an expression */
Packit 6bd9ab
  if (value[0] == '"')
Packit 6bd9ab
  {
Packit 6bd9ab
    /* these attributes may contain an expression
Packit 6bd9ab
       (note that this needs to match the functionality in the specific
Packit 6bd9ab
       lookup module) */
Packit 6bd9ab
    if ((var != &attmap_group_userPassword) &&
Packit 6bd9ab
        (var != &attmap_group_member) &&
Packit 6bd9ab
        (var != &attmap_passwd_userPassword) &&
Packit 6bd9ab
        (var != &attmap_passwd_gidNumber) &&
Packit 6bd9ab
        (var != &attmap_passwd_gecos) &&
Packit 6bd9ab
        (var != &attmap_passwd_homeDirectory) &&
Packit 6bd9ab
        (var != &attmap_passwd_loginShell) &&
Packit 6bd9ab
        (var != &attmap_shadow_userPassword) &&
Packit 6bd9ab
        (var != &attmap_shadow_shadowLastChange) &&
Packit 6bd9ab
        (var != &attmap_shadow_shadowMin) &&
Packit 6bd9ab
        (var != &attmap_shadow_shadowMax) &&
Packit 6bd9ab
        (var != &attmap_shadow_shadowWarning) &&
Packit 6bd9ab
        (var != &attmap_shadow_shadowInactive) &&
Packit 6bd9ab
        (var != &attmap_shadow_shadowExpire) &&
Packit 6bd9ab
        (var != &attmap_shadow_shadowFlag))
Packit 6bd9ab
      return NULL;
Packit 6bd9ab
    /* the member attribute may only be set to an empty string */
Packit 6bd9ab
    if ((var == &attmap_group_member) && (strcmp(value, "\"\"") != 0))
Packit 6bd9ab
      return NULL;
Packit 6bd9ab
  }
Packit 6bd9ab
  /* check if the value will be changed */
Packit 6bd9ab
  if ((*var == NULL) || (strcmp(*var, value) != 0))
Packit 6bd9ab
    *var = strdup(value);
Packit 6bd9ab
  return *var;
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
static const char *entry_expand(const char *name, void *expander_attr)
Packit 6bd9ab
{
Packit 6bd9ab
  MYLDAP_ENTRY *entry = (MYLDAP_ENTRY *)expander_attr;
Packit 6bd9ab
  const char **values;
Packit 6bd9ab
  if (strcasecmp(name, "dn") == 0)
Packit 6bd9ab
    return myldap_get_dn(entry);
Packit 6bd9ab
  values = myldap_get_values(entry, name);
Packit 6bd9ab
  if (values == NULL)
Packit 6bd9ab
    return "";
Packit 6bd9ab
  /* TODO: handle userPassword attribute specially */
Packit 6bd9ab
  if ((values[0] != NULL) && (values[1] != NULL))
Packit 6bd9ab
  {
Packit 6bd9ab
    log_log(LOG_WARNING, "%s: %s: multiple values",
Packit 6bd9ab
            myldap_get_dn(entry), name);
Packit 6bd9ab
  }
Packit 6bd9ab
  return values[0];
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
const char *attmap_get_value(MYLDAP_ENTRY *entry, const char *attr,
Packit 6bd9ab
                             char *buffer, size_t buflen)
Packit 6bd9ab
{
Packit 6bd9ab
  const char **values;
Packit 6bd9ab
  /* check and clear buffer */
Packit 6bd9ab
  if ((buffer == NULL) || (buflen <= 0))
Packit 6bd9ab
    return NULL;
Packit 6bd9ab
  buffer[0] = '\0';
Packit 6bd9ab
  /* for simple values just return the attribute */
Packit 6bd9ab
  if (attr[0] != '"')
Packit 6bd9ab
  {
Packit 6bd9ab
    values = myldap_get_values(entry, attr);
Packit 6bd9ab
    if ((values == NULL) || (values[0] == NULL))
Packit 6bd9ab
      return NULL;
Packit 6bd9ab
    if (strlen(values[0]) >= buflen)
Packit 6bd9ab
    {
Packit 6bd9ab
      log_log(LOG_ERR, "attmap_get_value(): buffer too small (%lu required)",
Packit 6bd9ab
              (unsigned long) strlen(values[0]));
Packit 6bd9ab
      return NULL;
Packit 6bd9ab
    }
Packit 6bd9ab
    strncpy(buffer, values[0], buflen);
Packit 6bd9ab
    buffer[buflen - 1] = '\0';
Packit 6bd9ab
    return buffer;
Packit 6bd9ab
    /* TODO: maybe warn when multiple values are found */
Packit 6bd9ab
  }
Packit 6bd9ab
  /* we have an expression, try to parse */
Packit 6bd9ab
  if ((attr[strlen(attr) - 1] != '"') ||
Packit 6bd9ab
      (expr_parse(attr + 1, buffer, buflen, entry_expand, (void *)entry) == NULL))
Packit 6bd9ab
  {
Packit 6bd9ab
    log_log(LOG_ERR, "attribute mapping %s is invalid", attr);
Packit 6bd9ab
    buffer[0] = '\0';
Packit 6bd9ab
    return NULL;
Packit 6bd9ab
  }
Packit 6bd9ab
  /* strip trailing " */
Packit 6bd9ab
  if (buffer[strlen(buffer) - 1] == '"')
Packit 6bd9ab
    buffer[strlen(buffer) - 1] = '\0';
Packit 6bd9ab
  return buffer;
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
SET *attmap_add_attributes(SET *set, const char *attr)
Packit 6bd9ab
{
Packit 6bd9ab
  if (attr[0] != '\"')
Packit 6bd9ab
    set_add(set, attr);
Packit 6bd9ab
  else
Packit 6bd9ab
    expr_vars(attr, set);
Packit 6bd9ab
  return set;
Packit 6bd9ab
}