1*225a5b88Stb /* $OpenBSD: util.c,v 1.14 2021/12/15 20:43:31 tb Exp $ */
25d465952Smartinh
35d465952Smartinh /*
45d465952Smartinh * Copyright (c) 2009 Martin Hedenfalk <martin@bzero.se>
55d465952Smartinh *
65d465952Smartinh * Permission to use, copy, modify, and distribute this software for any
75d465952Smartinh * purpose with or without fee is hereby granted, provided that the above
85d465952Smartinh * copyright notice and this permission notice appear in all copies.
95d465952Smartinh *
105d465952Smartinh * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
115d465952Smartinh * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
125d465952Smartinh * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
135d465952Smartinh * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
145d465952Smartinh * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
155d465952Smartinh * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
165d465952Smartinh * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
175d465952Smartinh */
185d465952Smartinh
195d465952Smartinh #include <sys/queue.h>
205d465952Smartinh #include <sys/types.h>
215d465952Smartinh #include <sys/socket.h>
220d43ad28Sjmatthew #include <sys/resource.h>
235d465952Smartinh #include <netinet/in.h>
245d465952Smartinh #include <arpa/inet.h>
255d465952Smartinh
26f5f15bc0Smartinh #include <assert.h>
275d465952Smartinh #include <ctype.h>
28*225a5b88Stb #include <errno.h>
295d465952Smartinh #include <stdio.h>
305d465952Smartinh #include <stdlib.h>
315d465952Smartinh #include <string.h>
32*225a5b88Stb #include <unistd.h>
335d465952Smartinh #include <zlib.h>
345d465952Smartinh
355d465952Smartinh #include "ldapd.h"
36fdd30f56Sbenno #include "log.h"
375d465952Smartinh
385d465952Smartinh int
bsnprintf(char * str,size_t size,const char * format,...)395d465952Smartinh bsnprintf(char *str, size_t size, const char *format, ...)
405d465952Smartinh {
415d465952Smartinh int ret;
425d465952Smartinh va_list ap;
435d465952Smartinh
445d465952Smartinh va_start(ap, format);
455d465952Smartinh ret = vsnprintf(str, size, format, ap);
465d465952Smartinh va_end(ap);
47070a2af0Stb if (ret < 0 || (size_t)ret >= size)
485d465952Smartinh return 0;
495d465952Smartinh
505d465952Smartinh return 1;
515d465952Smartinh }
525d465952Smartinh
535d465952Smartinh /* Normalize a DN in preparation for searches.
545d465952Smartinh * Modifies its argument.
555d465952Smartinh * Currently only made lowercase, and spaces around comma is removed.
565d465952Smartinh * TODO: unescape backslash escapes, handle UTF-8.
575d465952Smartinh */
585d465952Smartinh void
normalize_dn(char * dn)595d465952Smartinh normalize_dn(char *dn)
605d465952Smartinh {
615d465952Smartinh size_t n;
625d465952Smartinh char *s, *p;
635d465952Smartinh
645d465952Smartinh for (s = p = dn; *s != '\0'; s++) {
655d465952Smartinh if (*s == ' ') {
665d465952Smartinh if (p == dn || p[-1] == ',')
675d465952Smartinh continue;
685d465952Smartinh n = strspn(s, " ");
695d465952Smartinh if (s[n] == '\0' || s[n] == ',')
705d465952Smartinh continue;
715d465952Smartinh }
72a509009bSderaadt *p++ = tolower((unsigned char)*s);
735d465952Smartinh }
745d465952Smartinh *p = '\0';
755d465952Smartinh }
765d465952Smartinh
775d465952Smartinh /* Returns true (1) if key ends with suffix.
785d465952Smartinh */
795d465952Smartinh int
has_suffix(struct btval * key,const char * suffix)805d465952Smartinh has_suffix(struct btval *key, const char *suffix)
815d465952Smartinh {
825d465952Smartinh size_t slen;
835d465952Smartinh
845d465952Smartinh slen = strlen(suffix);
855d465952Smartinh
865d465952Smartinh if (key->size < slen)
875d465952Smartinh return 0;
885d465952Smartinh return (bcmp((char *)key->data + key->size - slen, suffix, slen) == 0);
895d465952Smartinh }
905d465952Smartinh
915d465952Smartinh /* Returns true (1) if key begins with prefix.
925d465952Smartinh */
935d465952Smartinh int
has_prefix(struct btval * key,const char * prefix)945d465952Smartinh has_prefix(struct btval *key, const char *prefix)
955d465952Smartinh {
965d465952Smartinh size_t pfxlen;
975d465952Smartinh
985d465952Smartinh pfxlen = strlen(prefix);
995d465952Smartinh if (pfxlen > key->size)
1005d465952Smartinh return 0;
1015d465952Smartinh return (memcmp(key->data, prefix, pfxlen) == 0);
1025d465952Smartinh }
1035d465952Smartinh
104f5f15bc0Smartinh int
ber2db(struct ber_element * root,struct btval * val,int compression_level)105f5f15bc0Smartinh ber2db(struct ber_element *root, struct btval *val, int compression_level)
106f5f15bc0Smartinh {
107f5f15bc0Smartinh int rc;
108f5f15bc0Smartinh ssize_t len;
109f5f15bc0Smartinh uLongf destlen;
110f5f15bc0Smartinh Bytef *dest;
111f5f15bc0Smartinh void *buf;
112f5f15bc0Smartinh struct ber ber;
113f5f15bc0Smartinh
11437f4b933Smmcc memset(val, 0, sizeof(*val));
115f5f15bc0Smartinh
11637f4b933Smmcc memset(&ber, 0, sizeof(ber));
117696b5899Stb ober_write_elements(&ber, root);
118f5f15bc0Smartinh
119696b5899Stb if ((len = ober_get_writebuf(&ber, &buf)) == -1)
120f5f15bc0Smartinh return -1;
121f5f15bc0Smartinh
122f5f15bc0Smartinh if (compression_level > 0) {
123f5f15bc0Smartinh val->size = compressBound(len);
124f5f15bc0Smartinh val->data = malloc(val->size + sizeof(uint32_t));
125f5f15bc0Smartinh if (val->data == NULL) {
126c0785a05Sreyk log_warn("malloc(%zu)", val->size + sizeof(uint32_t));
127696b5899Stb ober_free(&ber);
128f5f15bc0Smartinh return -1;
129f5f15bc0Smartinh }
130f5f15bc0Smartinh dest = (char *)val->data + sizeof(uint32_t);
131f5f15bc0Smartinh destlen = val->size - sizeof(uint32_t);
132f5f15bc0Smartinh if ((rc = compress2(dest, &destlen, buf, len,
133f5f15bc0Smartinh compression_level)) != Z_OK) {
13448318e0bSderaadt log_warn("compress returned %d", rc);
135f5f15bc0Smartinh free(val->data);
136696b5899Stb ober_free(&ber);
137f5f15bc0Smartinh return -1;
138f5f15bc0Smartinh }
139c0785a05Sreyk log_debug("compressed entry from %zd -> %lu byte",
140f5f15bc0Smartinh len, destlen + sizeof(uint32_t));
141f5f15bc0Smartinh
142f5f15bc0Smartinh *(uint32_t *)val->data = len;
143f5f15bc0Smartinh val->size = destlen + sizeof(uint32_t);
144f5f15bc0Smartinh val->free_data = 1;
145f5f15bc0Smartinh } else {
146f5f15bc0Smartinh val->data = buf;
147f5f15bc0Smartinh val->size = len;
148f5f15bc0Smartinh val->free_data = 1; /* XXX: take over internal br_wbuf */
149f5f15bc0Smartinh ber.br_wbuf = NULL;
150f5f15bc0Smartinh }
151f5f15bc0Smartinh
152696b5899Stb ober_free(&ber);
153f5f15bc0Smartinh
154f5f15bc0Smartinh return 0;
155f5f15bc0Smartinh }
156f5f15bc0Smartinh
157f5f15bc0Smartinh struct ber_element *
db2ber(struct btval * val,int compression_level)158f5f15bc0Smartinh db2ber(struct btval *val, int compression_level)
159f5f15bc0Smartinh {
160f5f15bc0Smartinh int rc;
161f5f15bc0Smartinh uLongf len;
162f5f15bc0Smartinh void *buf;
163f5f15bc0Smartinh Bytef *src;
164f5f15bc0Smartinh uLong srclen;
165f5f15bc0Smartinh struct ber_element *elm;
166f5f15bc0Smartinh struct ber ber;
167f5f15bc0Smartinh
168f5f15bc0Smartinh assert(val != NULL);
169f5f15bc0Smartinh
17037f4b933Smmcc memset(&ber, 0, sizeof(ber));
171f5f15bc0Smartinh
172f5f15bc0Smartinh if (compression_level > 0) {
173f5f15bc0Smartinh if (val->size < sizeof(uint32_t))
174f5f15bc0Smartinh return NULL;
175f5f15bc0Smartinh
176f5f15bc0Smartinh len = *(uint32_t *)val->data;
177f5f15bc0Smartinh if ((buf = malloc(len)) == NULL) {
178c0785a05Sreyk log_warn("malloc(%lu)", len);
179f5f15bc0Smartinh return NULL;
180f5f15bc0Smartinh }
181f5f15bc0Smartinh
182f5f15bc0Smartinh src = (char *)val->data + sizeof(uint32_t);
183f5f15bc0Smartinh srclen = val->size - sizeof(uint32_t);
184f5f15bc0Smartinh rc = uncompress(buf, &len, src, srclen);
185f5f15bc0Smartinh if (rc != Z_OK) {
18648318e0bSderaadt log_warnx("dbt_to_ber: uncompress returned %d", rc);
187f5f15bc0Smartinh free(buf);
188f5f15bc0Smartinh return NULL;
189f5f15bc0Smartinh }
190f5f15bc0Smartinh
191c0785a05Sreyk log_debug("uncompressed entry from %zu -> %lu byte",
192f5f15bc0Smartinh val->size, len);
193f5f15bc0Smartinh
194696b5899Stb ober_set_readbuf(&ber, buf, len);
195696b5899Stb elm = ober_read_elements(&ber, NULL);
196f5f15bc0Smartinh free(buf);
197f5f15bc0Smartinh return elm;
198f5f15bc0Smartinh } else {
199696b5899Stb ober_set_readbuf(&ber, val->data, val->size);
200696b5899Stb return ober_read_elements(&ber, NULL);
201f5f15bc0Smartinh }
202f5f15bc0Smartinh }
203f5f15bc0Smartinh
2040d43ad28Sjmatthew int
accept_reserve(int sockfd,struct sockaddr * addr,socklen_t * addrlen,int reserve)2050d43ad28Sjmatthew accept_reserve(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
2060d43ad28Sjmatthew int reserve)
2070d43ad28Sjmatthew {
2080d43ad28Sjmatthew if (getdtablecount() + reserve >= getdtablesize()) {
2090d43ad28Sjmatthew errno = EMFILE;
2100d43ad28Sjmatthew return -1;
2110d43ad28Sjmatthew }
2120d43ad28Sjmatthew
213576ea306Sjmatthew return accept4(sockfd, addr, addrlen, SOCK_NONBLOCK);
2140d43ad28Sjmatthew }
215