1 /*
2 attmap.c - attribute mapping values and functions
3 This file is part of the nss-pam-ldapd library.
4
5 Copyright (C) 2007-2014 Arthur de Jong
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301 USA
21 */
22
23 #include "config.h"
24
25 #include <stdlib.h>
26 #include <strings.h>
27
28 #include "attmap.h"
29 #include "log.h"
30 #include "common/expr.h"
31
32 /* these are the bases that are defined per database */
33 extern const char *alias_bases[];
34 extern const char *ether_bases[];
35 extern const char *group_bases[];
36 extern const char *host_bases[];
37 extern const char *netgroup_bases[];
38 extern const char *network_bases[];
39 extern const char *passwd_bases[];
40 extern const char *protocol_bases[];
41 extern const char *rpc_bases[];
42 extern const char *service_bases[];
43 extern const char *shadow_bases[];
44
base_get_var(enum ldap_map_selector map)45 const char **base_get_var(enum ldap_map_selector map)
46 {
47 switch (map)
48 {
49 case LM_ALIASES: return alias_bases;
50 case LM_ETHERS: return ether_bases;
51 case LM_GROUP: return group_bases;
52 case LM_HOSTS: return host_bases;
53 case LM_NETGROUP: return netgroup_bases;
54 case LM_NETWORKS: return network_bases;
55 case LM_PASSWD: return passwd_bases;
56 case LM_PROTOCOLS: return protocol_bases;
57 case LM_RPC: return rpc_bases;
58 case LM_SERVICES: return service_bases;
59 case LM_SHADOW: return shadow_bases;
60 case LM_NFSIDMAP:
61 case LM_NONE:
62 default: return NULL;
63 }
64 }
65
66 /* these are the scopes that are defined per database */
67 extern int alias_scope;
68 extern int ether_scope;
69 extern int group_scope;
70 extern int host_scope;
71 extern int netgroup_scope;
72 extern int network_scope;
73 extern int passwd_scope;
74 extern int protocol_scope;
75 extern int rpc_scope;
76 extern int service_scope;
77 extern int shadow_scope;
78
scope_get_var(enum ldap_map_selector map)79 int *scope_get_var(enum ldap_map_selector map)
80 {
81 switch (map)
82 {
83 case LM_ALIASES: return &alias_scope;
84 case LM_ETHERS: return ðer_scope;
85 case LM_GROUP: return &group_scope;
86 case LM_HOSTS: return &host_scope;
87 case LM_NETGROUP: return &netgroup_scope;
88 case LM_NETWORKS: return &network_scope;
89 case LM_PASSWD: return &passwd_scope;
90 case LM_PROTOCOLS: return &protocol_scope;
91 case LM_RPC: return &rpc_scope;
92 case LM_SERVICES: return &service_scope;
93 case LM_SHADOW: return &shadow_scope;
94 case LM_NFSIDMAP:
95 case LM_NONE:
96 default: return NULL;
97 }
98 }
99
100 /* these are the filters that are defined per database */
101 extern const char *alias_filter;
102 extern const char *ether_filter;
103 extern const char *group_filter;
104 extern const char *host_filter;
105 extern const char *netgroup_filter;
106 extern const char *network_filter;
107 extern const char *passwd_filter;
108 extern const char *protocol_filter;
109 extern const char *rpc_filter;
110 extern const char *service_filter;
111 extern const char *shadow_filter;
112
filter_get_var(enum ldap_map_selector map)113 const char **filter_get_var(enum ldap_map_selector map)
114 {
115 switch (map)
116 {
117 case LM_ALIASES: return &alias_filter;
118 case LM_ETHERS: return ðer_filter;
119 case LM_GROUP: return &group_filter;
120 case LM_HOSTS: return &host_filter;
121 case LM_NETGROUP: return &netgroup_filter;
122 case LM_NETWORKS: return &network_filter;
123 case LM_PASSWD: return &passwd_filter;
124 case LM_PROTOCOLS: return &protocol_filter;
125 case LM_RPC: return &rpc_filter;
126 case LM_SERVICES: return &service_filter;
127 case LM_SHADOW: return &shadow_filter;
128 case LM_NFSIDMAP:
129 case LM_NONE:
130 default: return NULL;
131 }
132 }
133
attmap_get_var(enum ldap_map_selector map,const char * name)134 const char **attmap_get_var(enum ldap_map_selector map, const char *name)
135 {
136 if (map == LM_ALIASES)
137 {
138 if (strcasecmp(name, "cn") == 0) return &attmap_alias_cn;
139 if (strcasecmp(name, "rfc822MailMember") == 0) return &attmap_alias_rfc822MailMember;
140 }
141 else if (map == LM_ETHERS)
142 {
143 if (strcasecmp(name, "cn") == 0) return &attmap_ether_cn;
144 if (strcasecmp(name, "macAddress") == 0) return &attmap_ether_macAddress;
145 }
146 else if (map == LM_GROUP)
147 {
148 if (strcasecmp(name, "cn") == 0) return &attmap_group_cn;
149 if (strcasecmp(name, "userPassword") == 0) return &attmap_group_userPassword;
150 if (strcasecmp(name, "gidNumber") == 0) return &attmap_group_gidNumber;
151 if (strcasecmp(name, "memberUid") == 0) return &attmap_group_memberUid;
152 if (strcasecmp(name, "member") == 0) return &attmap_group_member;
153 }
154 else if (map == LM_HOSTS)
155 {
156 if (strcasecmp(name, "cn") == 0) return &attmap_host_cn;
157 if (strcasecmp(name, "ipHostNumber") == 0) return &attmap_host_ipHostNumber;
158 }
159 else if (map == LM_NETGROUP)
160 {
161 if (strcasecmp(name, "cn") == 0) return &attmap_netgroup_cn;
162 if (strcasecmp(name, "nisNetgroupTriple") == 0) return &attmap_netgroup_nisNetgroupTriple;
163 if (strcasecmp(name, "memberNisNetgroup") == 0) return &attmap_netgroup_memberNisNetgroup;
164 }
165 else if (map == LM_NETWORKS)
166 {
167 if (strcasecmp(name, "cn") == 0) return &attmap_network_cn;
168 if (strcasecmp(name, "ipNetworkNumber") == 0) return &attmap_network_ipNetworkNumber;
169 }
170 else if (map == LM_PASSWD)
171 {
172 if (strcasecmp(name, "uid") == 0) return &attmap_passwd_uid;
173 if (strcasecmp(name, "userPassword") == 0) return &attmap_passwd_userPassword;
174 if (strcasecmp(name, "uidNumber") == 0) return &attmap_passwd_uidNumber;
175 if (strcasecmp(name, "gidNumber") == 0) return &attmap_passwd_gidNumber;
176 if (strcasecmp(name, "gecos") == 0) return &attmap_passwd_gecos;
177 if (strcasecmp(name, "homeDirectory") == 0) return &attmap_passwd_homeDirectory;
178 if (strcasecmp(name, "loginShell") == 0) return &attmap_passwd_loginShell;
179 }
180 else if (map == LM_PROTOCOLS)
181 {
182 if (strcasecmp(name, "cn") == 0) return &attmap_protocol_cn;
183 if (strcasecmp(name, "ipProtocolNumber") == 0) return &attmap_protocol_ipProtocolNumber;
184 }
185 else if (map == LM_RPC)
186 {
187 if (strcasecmp(name, "cn") == 0) return &attmap_rpc_cn;
188 if (strcasecmp(name, "oncRpcNumber") == 0) return &attmap_rpc_oncRpcNumber;
189 }
190 else if (map == LM_SERVICES)
191 {
192 if (strcasecmp(name, "cn") == 0) return &attmap_service_cn;
193 if (strcasecmp(name, "ipServicePort") == 0) return &attmap_service_ipServicePort;
194 if (strcasecmp(name, "ipServiceProtocol") == 0) return &attmap_service_ipServiceProtocol;
195 }
196 else if (map == LM_SHADOW)
197 {
198 if (strcasecmp(name, "uid") == 0) return &attmap_shadow_uid;
199 if (strcasecmp(name, "userPassword") == 0) return &attmap_shadow_userPassword;
200 if (strcasecmp(name, "shadowLastChange") == 0) return &attmap_shadow_shadowLastChange;
201 if (strcasecmp(name, "shadowMin") == 0) return &attmap_shadow_shadowMin;
202 if (strcasecmp(name, "shadowMax") == 0) return &attmap_shadow_shadowMax;
203 if (strcasecmp(name, "shadowWarning") == 0) return &attmap_shadow_shadowWarning;
204 if (strcasecmp(name, "shadowInactive") == 0) return &attmap_shadow_shadowInactive;
205 if (strcasecmp(name, "shadowExpire") == 0) return &attmap_shadow_shadowExpire;
206 if (strcasecmp(name, "shadowFlag") == 0) return &attmap_shadow_shadowFlag;
207 }
208 return NULL;
209 }
210
attmap_set_mapping(const char ** var,const char * value)211 const char *attmap_set_mapping(const char **var, const char *value)
212 {
213 /* check if we are setting an expression */
214 if (value[0] == '"')
215 {
216 /* these attributes may contain an expression
217 (note that this needs to match the functionality in the specific
218 lookup module) */
219 if ((var != &attmap_group_userPassword) &&
220 (var != &attmap_group_member) &&
221 (var != &attmap_passwd_userPassword) &&
222 (var != &attmap_passwd_gidNumber) &&
223 (var != &attmap_passwd_gecos) &&
224 (var != &attmap_passwd_homeDirectory) &&
225 (var != &attmap_passwd_loginShell) &&
226 (var != &attmap_shadow_userPassword) &&
227 (var != &attmap_shadow_shadowLastChange) &&
228 (var != &attmap_shadow_shadowMin) &&
229 (var != &attmap_shadow_shadowMax) &&
230 (var != &attmap_shadow_shadowWarning) &&
231 (var != &attmap_shadow_shadowInactive) &&
232 (var != &attmap_shadow_shadowExpire) &&
233 (var != &attmap_shadow_shadowFlag))
234 return NULL;
235 /* the member attribute may only be set to an empty string */
236 if ((var == &attmap_group_member) && (strcmp(value, "\"\"") != 0))
237 return NULL;
238 }
239 /* check if the value will be changed */
240 if ((*var == NULL) || (strcmp(*var, value) != 0))
241 *var = strdup(value);
242 return *var;
243 }
244
entry_expand(const char * name,void * expander_attr)245 static const char *entry_expand(const char *name, void *expander_attr)
246 {
247 MYLDAP_ENTRY *entry = (MYLDAP_ENTRY *)expander_attr;
248 const char **values;
249 if (strcasecmp(name, "dn") == 0)
250 return myldap_get_dn(entry);
251 values = myldap_get_values(entry, name);
252 if (values == NULL)
253 return "";
254 /* TODO: handle userPassword attribute specially */
255 if ((values[0] != NULL) && (values[1] != NULL))
256 {
257 log_log(LOG_WARNING, "%s: %s: multiple values",
258 myldap_get_dn(entry), name);
259 }
260 return values[0];
261 }
262
attmap_get_value(MYLDAP_ENTRY * entry,const char * attr,char * buffer,size_t buflen)263 const char *attmap_get_value(MYLDAP_ENTRY *entry, const char *attr,
264 char *buffer, size_t buflen)
265 {
266 const char **values;
267 /* check and clear buffer */
268 if ((buffer == NULL) || (buflen <= 0))
269 return NULL;
270 buffer[0] = '\0';
271 /* for simple values just return the attribute */
272 if (attr[0] != '"')
273 {
274 values = myldap_get_values(entry, attr);
275 if ((values == NULL) || (values[0] == NULL))
276 return NULL;
277 if (strlen(values[0]) >= buflen)
278 {
279 log_log(LOG_ERR, "attmap_get_value(): buffer too small (%lu required)",
280 (unsigned long) strlen(values[0]));
281 return NULL;
282 }
283 strncpy(buffer, values[0], buflen);
284 buffer[buflen - 1] = '\0';
285 return buffer;
286 /* TODO: maybe warn when multiple values are found */
287 }
288 /* we have an expression, try to parse */
289 if ((attr[strlen(attr) - 1] != '"') ||
290 (expr_parse(attr + 1, buffer, buflen, entry_expand, (void *)entry) == NULL))
291 {
292 log_log(LOG_ERR, "attribute mapping %s is invalid", attr);
293 buffer[0] = '\0';
294 return NULL;
295 }
296 /* strip trailing " */
297 if (buffer[strlen(buffer) - 1] == '"')
298 buffer[strlen(buffer) - 1] = '\0';
299 return buffer;
300 }
301
attmap_add_attributes(SET * set,const char * attr)302 SET *attmap_add_attributes(SET *set, const char *attr)
303 {
304 if (attr[0] != '\"')
305 set_add(set, attr);
306 else
307 expr_vars(attr, set);
308 return set;
309 }
310