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