1 /*
2 service.c - service entry lookup routines
3 Parts of this file were part of the nss_ldap library (as ldap-service.c)
4 which has been forked into the nss-pam-ldapd library.
5
6 Copyright (C) 1997-2005 Luke Howard
7 Copyright (C) 2006 West Consulting
8 Copyright (C) 2006-2014 Arthur de Jong
9
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2.1 of the License, or (at your option) any later version.
14
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
19
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 02110-1301 USA
24 */
25
26 #include "config.h"
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #ifdef HAVE_STDINT_H
32 #include <stdint.h>
33 #endif /* HAVE_STDINT_H */
34
35 #include "common.h"
36 #include "log.h"
37 #include "myldap.h"
38 #include "cfg.h"
39 #include "attmap.h"
40
41 /* ( nisSchema.2.3 NAME 'ipService' SUP top STRUCTURAL
42 * DESC 'Abstraction an Internet Protocol service.
43 * Maps an IP port and protocol (such as tcp or udp)
44 * to one or more names; the distinguished value of
45 * the cn attribute denotes the service's canonical
46 * name'
47 * MUST ( cn $ ipServicePort $ ipServiceProtocol )
48 * MAY ( description ) )
49 */
50
51 /* the search base for searches */
52 const char *service_bases[NSS_LDAP_CONFIG_MAX_BASES] = { NULL };
53
54 /* the search scope for searches */
55 int service_scope = LDAP_SCOPE_DEFAULT;
56
57 /* the basic search filter for searches */
58 const char *service_filter = "(objectClass=ipService)";
59
60 /* the attributes to request with searches */
61 const char *attmap_service_cn = "cn";
62 const char *attmap_service_ipServicePort = "ipServicePort";
63 const char *attmap_service_ipServiceProtocol = "ipServiceProtocol";
64
65 /* the attribute list to request with searches */
66 static const char *service_attrs[4];
67
mkfilter_service_byname(const char * name,const char * protocol,char * buffer,size_t buflen)68 static int mkfilter_service_byname(const char *name, const char *protocol,
69 char *buffer, size_t buflen)
70 {
71 char safename[BUFLEN_SAFENAME], safeprotocol[BUFLEN_SAFENAME];
72 /* escape attributes */
73 if (myldap_escape(name, safename, sizeof(safename)))
74 {
75 log_log(LOG_ERR, "mkfilter_service_byname(): safename buffer too small");
76 return -1;
77 }
78 /* build filter */
79 if (*protocol != '\0')
80 {
81 if (myldap_escape(protocol, safeprotocol, sizeof(safeprotocol)))
82 {
83 log_log(LOG_ERR, "mkfilter_service_byname(): safeprotocol buffer too small");
84 return -1;
85 }
86 return mysnprintf(buffer, buflen, "(&%s(%s=%s)(%s=%s))",
87 service_filter, attmap_service_cn, safename,
88 attmap_service_ipServiceProtocol, safeprotocol);
89 }
90 else
91 return mysnprintf(buffer, buflen, "(&%s(%s=%s))",
92 service_filter, attmap_service_cn, safename);
93 }
94
mkfilter_service_bynumber(int number,const char * protocol,char * buffer,size_t buflen)95 static int mkfilter_service_bynumber(int number, const char *protocol,
96 char *buffer, size_t buflen)
97 {
98 char safeprotocol[BUFLEN_SAFENAME];
99 if (*protocol != '\0')
100 {
101 if (myldap_escape(protocol, safeprotocol, sizeof(safeprotocol)))
102 {
103 log_log(LOG_ERR, "mkfilter_service_bynumber(): safeprotocol buffer too small");
104 return -1;
105 }
106 return mysnprintf(buffer, buflen, "(&%s(%s=%d)(%s=%s))",
107 service_filter, attmap_service_ipServicePort, number,
108 attmap_service_ipServiceProtocol, safeprotocol);
109 }
110 else
111 return mysnprintf(buffer, buflen, "(&%s(%s=%d))",
112 service_filter, attmap_service_ipServicePort, number);
113 }
114
service_init(void)115 void service_init(void)
116 {
117 int i;
118 /* set up search bases */
119 if (service_bases[0] == NULL)
120 for (i = 0; i < NSS_LDAP_CONFIG_MAX_BASES; i++)
121 service_bases[i] = nslcd_cfg->bases[i];
122 /* set up scope */
123 if (service_scope == LDAP_SCOPE_DEFAULT)
124 service_scope = nslcd_cfg->scope;
125 /* set up attribute list */
126 service_attrs[0] = attmap_service_cn;
127 service_attrs[1] = attmap_service_ipServicePort;
128 service_attrs[2] = attmap_service_ipServiceProtocol;
129 service_attrs[3] = NULL;
130 }
131
write_service(TFILE * fp,MYLDAP_ENTRY * entry,const char * reqname,const char * reqprotocol)132 static int write_service(TFILE *fp, MYLDAP_ENTRY *entry,
133 const char *reqname, const char *reqprotocol)
134 {
135 int32_t tmpint32, tmp2int32, tmp3int32;
136 const char *name;
137 const char **aliases;
138 const char **ports;
139 const char **protocols;
140 char *tmp;
141 long port;
142 int i;
143 /* get the most canonical name */
144 name = myldap_get_rdn_value(entry, attmap_service_cn);
145 /* get the other names for the service entries */
146 aliases = myldap_get_values(entry, attmap_service_cn);
147 if ((aliases == NULL) || (aliases[0] == NULL))
148 {
149 log_log(LOG_WARNING, "%s: %s: missing",
150 myldap_get_dn(entry), attmap_service_cn);
151 return 0;
152 }
153 /* if the service name is not yet found, get the first entry */
154 if (name == NULL)
155 name = aliases[0];
156 /* check case of returned services entry */
157 if ((reqname != NULL) && (STR_CMP(reqname, name) != 0))
158 {
159 for (i = 0; (aliases[i] != NULL) && (STR_CMP(reqname, aliases[i]) != 0); i++)
160 /* nothing */ ;
161 if (aliases[i] == NULL)
162 return 0; /* neither the name nor any of the aliases matched */
163 }
164 /* get the service number */
165 ports = myldap_get_values(entry, attmap_service_ipServicePort);
166 if ((ports == NULL) || (ports[0] == NULL))
167 {
168 log_log(LOG_WARNING, "%s: %s: missing",
169 myldap_get_dn(entry), attmap_service_ipServicePort);
170 return 0;
171 }
172 else if (ports[1] != NULL)
173 {
174 log_log(LOG_WARNING, "%s: %s: multiple values",
175 myldap_get_dn(entry), attmap_service_ipServicePort);
176 }
177 errno = 0;
178 port = strtol(ports[0], &tmp, 10);
179 if ((*(ports[0]) == '\0') || (*tmp != '\0'))
180 {
181 log_log(LOG_WARNING, "%s: %s: non-numeric value",
182 myldap_get_dn(entry), attmap_service_ipServicePort);
183 return 0;
184 }
185 else if ((errno != 0) || (port <= 0) || (port > (long)UINT16_MAX))
186 {
187 log_log(LOG_WARNING, "%s: %s: out of range",
188 myldap_get_dn(entry), attmap_service_ipServicePort);
189 return 0;
190 }
191 /* get protocols */
192 protocols = myldap_get_values(entry, attmap_service_ipServiceProtocol);
193 if ((protocols == NULL) || (protocols[0] == NULL))
194 {
195 log_log(LOG_WARNING, "%s: %s: missing",
196 myldap_get_dn(entry), attmap_service_ipServiceProtocol);
197 return 0;
198 }
199 /* write the entries */
200 for (i = 0; protocols[i] != NULL; i++)
201 if ((reqprotocol == NULL) || (*reqprotocol == '\0') ||
202 (STR_CMP(reqprotocol, protocols[i]) == 0))
203 {
204 WRITE_INT32(fp, NSLCD_RESULT_BEGIN);
205 WRITE_STRING(fp, name);
206 WRITE_STRINGLIST_EXCEPT(fp, aliases, name);
207 /* port number is actually a 16-bit value but we write 32 bits anyway */
208 WRITE_INT32(fp, port);
209 WRITE_STRING(fp, protocols[i]);
210 }
211 return 0;
212 }
213
214 NSLCD_HANDLE(
215 service, byname, NSLCD_ACTION_SERVICE_BYNAME,
216 char name[BUFLEN_NAME];
217 char protocol[BUFLEN_NAME];
218 char filter[BUFLEN_FILTER];
219 READ_STRING(fp, name);
220 READ_STRING(fp, protocol);
221 log_setrequest("service=\"%s\"%s%s", name,
222 *protocol != '\0' ? "/" : "", protocol);,
223 mkfilter_service_byname(name, protocol, filter, sizeof(filter)),
224 write_service(fp, entry, name, protocol)
225 )
226
227 NSLCD_HANDLE(
228 service, bynumber, NSLCD_ACTION_SERVICE_BYNUMBER,
229 int number;
230 char protocol[BUFLEN_NAME];
231 char filter[BUFLEN_FILTER];
232 READ_INT32(fp, number);
233 READ_STRING(fp, protocol);
234 log_setrequest("service=%lu%s%s", (unsigned long int)number,
235 *protocol != '\0' ? "/" : "", protocol);,
236 mkfilter_service_bynumber(number, protocol, filter, sizeof(filter)),
237 write_service(fp, entry, NULL, protocol)
238 )
239
240 NSLCD_HANDLE(
241 service, all, NSLCD_ACTION_SERVICE_ALL,
242 const char *filter;
243 log_setrequest("service(all)");,
244 (filter = service_filter, 0),
245 write_service(fp, entry, NULL, NULL)
246 )
247