1 /* $OpenBSD: conn.c,v 1.21 2023/06/26 10:28:12 claudio Exp $ */
2
3 /*
4 * Copyright (c) 2009, 2010 Martin Hedenfalk <martin@bzero.se>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <sys/queue.h>
20 #include <sys/types.h>
21
22 #include <stdlib.h>
23 #include <errno.h>
24 #include <unistd.h>
25
26 #include "ldapd.h"
27 #include "log.h"
28
29 int conn_dispatch(struct conn *conn);
30 int conn_tls_init(struct conn *);
31 unsigned int ldap_application(struct ber_element *elm);
32
33 struct conn_list conn_list;
34
35 unsigned int
ldap_application(struct ber_element * elm)36 ldap_application(struct ber_element *elm)
37 {
38 return BER_TYPE_OCTETSTRING;
39 }
40
41 void
request_free(struct request * req)42 request_free(struct request *req)
43 {
44 if (req->root != NULL)
45 ober_free_elements(req->root);
46 free(req);
47 }
48
49 void
conn_close(struct conn * conn)50 conn_close(struct conn *conn)
51 {
52 struct search *search, *next;
53 struct listener *l = conn->listener;
54
55 log_debug("closing connection %d", conn->fd);
56
57 /* Cancel any ongoing searches on this connection. */
58 for (search = TAILQ_FIRST(&conn->searches); search; search = next) {
59 next = TAILQ_NEXT(search, next);
60 search_close(search);
61 }
62
63 /* Cancel any queued requests on this connection. */
64 namespace_cancel_conn(conn);
65
66 tls_free(conn->tls);
67
68 TAILQ_REMOVE(&conn_list, conn, next);
69 ober_free(&conn->ber);
70 if (conn->bev != NULL)
71 bufferevent_free(conn->bev);
72 close(conn->fd);
73
74 /* Some file descriptors are available again. */
75 if (evtimer_pending(&l->evt, NULL)) {
76 evtimer_del(&l->evt);
77 event_add(&l->ev, NULL);
78 }
79
80 free(conn->binddn);
81 free(conn->pending_binddn);
82 free(conn);
83
84 --stats.conns;
85 }
86
87 /* Marks a connection for disconnect. The connection will be closed when
88 * any remaining data has been flushed to the socket.
89 */
90 void
conn_disconnect(struct conn * conn)91 conn_disconnect(struct conn *conn)
92 {
93 conn->disconnect = 1;
94 bufferevent_enable(conn->bev, EV_WRITE);
95 }
96
97 void
request_dispatch(struct request * req)98 request_dispatch(struct request *req)
99 {
100 unsigned long i;
101 struct {
102 unsigned int type;
103 int (*fn)(struct request *);
104 } requests[] = {
105 { LDAP_REQ_SEARCH, ldap_search },
106 { LDAP_REQ_BIND, ldap_bind },
107 { LDAP_REQ_COMPARE, ldap_compare },
108 { LDAP_REQ_ADD, ldap_add },
109 { LDAP_REQ_UNBIND_30, ldap_unbind },
110 { LDAP_REQ_MODIFY, ldap_modify },
111 { LDAP_REQ_ABANDON_30, ldap_abandon },
112 { LDAP_REQ_DELETE_30, ldap_delete },
113 { LDAP_REQ_EXTENDED, ldap_extended },
114 { 0, NULL }
115 };
116
117 /* RFC4511, section 4.2.1 says we shouldn't process other requests
118 * while binding. A bind operation can, however, be aborted by sending
119 * another bind operation.
120 */
121 if (req->conn->bind_req != NULL && req->type != LDAP_REQ_BIND) {
122 log_warnx("got request while bind in progress");
123 ldap_respond(req, LDAP_SASL_BIND_IN_PROGRESS);
124 return;
125 }
126
127 for (i = 0; requests[i].fn != NULL; i++) {
128 if (requests[i].type == req->type) {
129 requests[i].fn(req);
130 break;
131 }
132 }
133
134 if (requests[i].fn == NULL) {
135 log_warnx("unhandled request %u (not implemented)", req->type);
136 ldap_respond(req, LDAP_PROTOCOL_ERROR);
137 }
138 }
139
140 int
conn_dispatch(struct conn * conn)141 conn_dispatch(struct conn *conn)
142 {
143 int class;
144 struct request *req;
145 u_char *rptr;
146
147 ++stats.requests;
148
149 if ((req = calloc(1, sizeof(*req))) == NULL) {
150 log_warn("calloc");
151 conn_disconnect(conn);
152 return -1;
153 }
154
155 req->conn = conn;
156 rptr = conn->ber.br_rptr; /* save where we start reading */
157
158 if ((req->root = ober_read_elements(&conn->ber, NULL)) == NULL) {
159 if (errno != ECANCELED) {
160 log_warnx("protocol error");
161 hexdump(rptr, conn->ber.br_rend - rptr,
162 "failed to parse request from %zi bytes:",
163 conn->ber.br_rend - rptr);
164 conn_disconnect(conn);
165 }
166 request_free(req);
167 return -1;
168 }
169 log_debug("consumed %ld bytes", conn->ber.br_rptr - rptr);
170
171 /* Read message id and request type.
172 */
173 if (ober_scanf_elements(req->root, "{ite",
174 &req->msgid, &class, &req->type, &req->op) != 0) {
175 log_warnx("protocol error");
176 ldap_debug_elements(req->root, -1,
177 "received invalid request on fd %d", conn->fd);
178 conn_disconnect(conn);
179 request_free(req);
180 return -1;
181 }
182
183 ldap_debug_elements(req->root, req->type,
184 "received request on fd %d", conn->fd);
185
186 log_debug("got request type %u, id %lld", req->type, req->msgid);
187 request_dispatch(req);
188 return 0;
189 }
190
191 void
conn_read(struct bufferevent * bev,void * data)192 conn_read(struct bufferevent *bev, void *data)
193 {
194 size_t nused = 0;
195 struct conn *conn = data;
196 struct evbuffer *input;
197
198 input = EVBUFFER_INPUT(bev);
199 ober_set_readbuf(&conn->ber,
200 EVBUFFER_DATA(input), EVBUFFER_LENGTH(input));
201
202 while (conn->ber.br_rend - conn->ber.br_rptr > 0) {
203 if (conn_dispatch(conn) == 0)
204 nused = conn->ber.br_rptr - conn->ber.br_rbuf;
205 else
206 break;
207 }
208
209 evbuffer_drain(input, nused);
210 }
211
212 void
conn_write(struct bufferevent * bev,void * data)213 conn_write(struct bufferevent *bev, void *data)
214 {
215 struct search *search, *next;
216 struct conn *conn = data;
217
218 /* Continue any ongoing searches.
219 * Note that the search may be unlinked and freed by conn_search.
220 */
221 for (search = TAILQ_FIRST(&conn->searches); search; search = next) {
222 next = TAILQ_NEXT(search, next);
223 conn_search(search);
224 }
225
226 if (conn->disconnect)
227 conn_close(conn);
228 else if (conn->s_flags & F_STARTTLS) {
229 conn->s_flags &= ~F_STARTTLS;
230 if (conn_tls_init(conn) == -1)
231 conn_close(conn);
232 }
233 }
234
235 void
conn_err(struct bufferevent * bev,short why,void * data)236 conn_err(struct bufferevent *bev, short why, void *data)
237 {
238 struct conn *conn = data;
239
240 if ((why & EVBUFFER_EOF) == EVBUFFER_EOF)
241 log_debug("end-of-file on connection %d", conn->fd);
242 else if ((why & EVBUFFER_TIMEOUT) == EVBUFFER_TIMEOUT)
243 log_debug("timeout on connection %d", conn->fd);
244 else
245 log_warn("%s error on connection %d",
246 why & EVBUFFER_WRITE ? "write" : "read", conn->fd);
247
248 conn_close(conn);
249 }
250
251 void
conn_accept(int fd,short event,void * data)252 conn_accept(int fd, short event, void *data)
253 {
254 int afd;
255 socklen_t addrlen;
256 struct conn *conn;
257 struct listener *l = data;
258 struct sockaddr_storage remote_addr;
259 char host[128];
260
261 event_add(&l->ev, NULL);
262 if ((event & EV_TIMEOUT))
263 return;
264
265 addrlen = sizeof(remote_addr);
266 afd = accept_reserve(fd, (struct sockaddr *)&remote_addr, &addrlen,
267 FD_RESERVE);
268 if (afd == -1) {
269 /*
270 * Pause accept if we are out of file descriptors, or
271 * libevent will haunt us here too.
272 */
273 if (errno == ENFILE || errno == EMFILE) {
274 struct timeval evtpause = { 1, 0 };
275
276 event_del(&l->ev);
277 evtimer_add(&l->evt, &evtpause);
278 } else if (errno != EWOULDBLOCK && errno != EINTR)
279 log_warn("conn_accept");
280 return;
281 }
282
283 if (l->ss.ss_family == AF_UNIX) {
284 uid_t euid;
285 gid_t egid;
286
287 if (getpeereid(afd, &euid, &egid) == -1)
288 log_warnx("conn_accept: getpeereid");
289 else
290 log_debug("accepted local connection by uid %d", euid);
291 } else {
292 print_host(&remote_addr, host, sizeof(host));
293 log_debug("accepted connection from %s on fd %d", host, afd);
294 }
295
296 if ((conn = calloc(1, sizeof(*conn))) == NULL) {
297 log_warn("malloc");
298 goto giveup;
299 }
300 ober_set_application(&conn->ber, ldap_application);
301 conn->fd = afd;
302 conn->listener = l;
303
304 conn->bev = bufferevent_new(afd, conn_read, conn_write,
305 conn_err, conn);
306 if (conn->bev == NULL) {
307 log_warn("conn_accept: bufferevent_new");
308 free(conn);
309 goto giveup;
310 }
311 bufferevent_enable(conn->bev, EV_READ);
312 bufferevent_settimeout(conn->bev, 0, 60);
313 if (l->flags & F_LDAPS)
314 if (conn_tls_init(conn) == -1) {
315 conn_close(conn);
316 goto giveup;
317 }
318
319 TAILQ_INIT(&conn->searches);
320 TAILQ_INSERT_HEAD(&conn_list, conn, next);
321
322 if (l->flags & F_SECURE)
323 conn->s_flags |= F_SECURE;
324
325 ++stats.conns;
326 return;
327 giveup:
328 close(afd);
329 /* Some file descriptors are available again. */
330 if (evtimer_pending(&l->evt, NULL)) {
331 evtimer_del(&l->evt);
332 event_add(&l->ev, NULL);
333 }
334 }
335
336 struct conn *
conn_by_fd(int fd)337 conn_by_fd(int fd)
338 {
339 struct conn *conn;
340
341 TAILQ_FOREACH(conn, &conn_list, next) {
342 if (conn->fd == fd)
343 return conn;
344 }
345 return NULL;
346 }
347
348 int
conn_close_any(void)349 conn_close_any(void)
350 {
351 struct conn *conn;
352
353 /* Close oldest idle connection */
354 TAILQ_FOREACH_REVERSE(conn, &conn_list, conn_list, next) {
355 if (namespace_conn_queue_count(conn) == 0) {
356 conn_close(conn);
357 return 0;
358 }
359 }
360
361 /* Close oldest connection */
362 conn = TAILQ_LAST(&conn_list, conn_list);
363 if (conn != NULL) {
364 conn_close(conn);
365 return 0;
366 }
367
368 return -1;
369 }
370
371 int
conn_tls_init(struct conn * conn)372 conn_tls_init(struct conn *conn)
373 {
374 struct listener *l = conn->listener;
375
376 if (!(l->flags & F_SSL))
377 return 0;
378
379 log_debug("conn_tls_init: switching to TLS");
380
381 if (tls_accept_socket(l->tls, &conn->tls, conn->fd) < 0) {
382 log_debug("tls_accept_socket failed");
383 return -1;
384 }
385
386 conn->s_flags |= F_SECURE;
387 buffertls_set(&conn->buftls, conn->bev, conn->tls, conn->fd);
388 buffertls_accept(&conn->buftls, conn->fd);
389 return 0;
390 }
391