xref: /openbsd-src/usr.sbin/ldapd/util.c (revision 225a5b8812e57ed621f70606c36a4d65607a1463)
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