1290931Srodrigc/*	$OpenBSD: entries.c,v 1.3 2015/01/16 06:40:22 deraadt Exp $ */
2290931Srodrigc/*	$FreeBSD: stable/11/usr.sbin/ypldap/entries.c 322882 2017-08-25 08:24:29Z araujo $ */
3290931Srodrigc/*
4290931Srodrigc * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
5290931Srodrigc *
6290931Srodrigc * Permission to use, copy, modify, and distribute this software for any
7290931Srodrigc * purpose with or without fee is hereby granted, provided that the above
8290931Srodrigc * copyright notice and this permission notice appear in all copies.
9290931Srodrigc *
10290931Srodrigc * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11290931Srodrigc * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12290931Srodrigc * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13290931Srodrigc * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14290931Srodrigc * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15290931Srodrigc * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16290931Srodrigc * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17290931Srodrigc */
18290931Srodrigc
19290931Srodrigc#include <sys/types.h>
20290937Srodrigc#include <sys/param.h>
21290931Srodrigc#include <sys/queue.h>
22290931Srodrigc#include <sys/socket.h>
23290931Srodrigc#include <sys/tree.h>
24290931Srodrigc
25290931Srodrigc#include <netinet/in.h>
26290931Srodrigc#include <arpa/inet.h>
27290931Srodrigc
28290931Srodrigc#include <errno.h>
29290931Srodrigc#include <event.h>
30290931Srodrigc#include <fcntl.h>
31290931Srodrigc#include <unistd.h>
32290931Srodrigc#include <pwd.h>
33290931Srodrigc#include <stdio.h>
34290931Srodrigc#include <stdlib.h>
35290931Srodrigc#include <string.h>
36290931Srodrigc#include <limits.h>
37290931Srodrigc
38290931Srodrigc#include "ypldap.h"
39290931Srodrigc
40290931Srodrigcvoid
41290931Srodrigcflatten_entries(struct env *env)
42290931Srodrigc{
43290931Srodrigc	size_t		 wrlen;
44290931Srodrigc	size_t		 len;
45290931Srodrigc	char		*linep;
46290931Srodrigc	char		*endp;
47290931Srodrigc	char		*tmp;
48290931Srodrigc	struct userent	*ue;
49290931Srodrigc	struct groupent	*ge;
50290931Srodrigc
51290931Srodrigc	log_debug("flattening trees");
52290931Srodrigc	/*
53290931Srodrigc	 * This takes all the line pointers in RB elements and
54290931Srodrigc	 * concatenates them in a single string, to be able to
55290931Srodrigc	 * implement next element lookup without tree traversal.
56290931Srodrigc	 *
57290931Srodrigc	 * An extra octet is alloced to make space for an additional NUL.
58290931Srodrigc	 */
59290931Srodrigc	wrlen = env->sc_user_line_len;
60290931Srodrigc	if ((linep = calloc(1, env->sc_user_line_len + 1)) == NULL) {
61290931Srodrigc		/*
62290931Srodrigc		 * XXX: try allocating a smaller chunk of memory
63290931Srodrigc		 */
64290931Srodrigc		fatal("out of memory");
65290931Srodrigc	}
66290931Srodrigc	endp = linep;
67290931Srodrigc
68290931Srodrigc	RB_FOREACH(ue, user_name_tree, env->sc_user_names) {
69290931Srodrigc		/*
70290931Srodrigc		 * we convert the first nul back to a column,
71290931Srodrigc		 * copy the string and then convert it back to a nul.
72290931Srodrigc		 */
73290931Srodrigc		ue->ue_line[strlen(ue->ue_line)] = ':';
74290931Srodrigc		log_debug("pushing line: %s", ue->ue_line);
75290931Srodrigc		len = strlen(ue->ue_line) + 1;
76290931Srodrigc		memcpy(endp, ue->ue_line, len);
77290931Srodrigc		endp[strcspn(endp, ":")] = '\0';
78290931Srodrigc		free(ue->ue_line);
79290931Srodrigc		ue->ue_line = endp;
80290931Srodrigc		endp += len;
81290931Srodrigc		wrlen -= len;
82290931Srodrigc
83290931Srodrigc		/*
84290931Srodrigc		 * To save memory strdup(3) the netid_line which originally used
85290931Srodrigc		 * LINE_WIDTH bytes
86290931Srodrigc		 */
87290931Srodrigc		tmp = ue->ue_netid_line;
88290931Srodrigc		ue->ue_netid_line = strdup(tmp);
89290931Srodrigc		if (ue->ue_netid_line == NULL) {
90290931Srodrigc			fatal("out of memory");
91290931Srodrigc		}
92290931Srodrigc		free(tmp);
93290931Srodrigc	}
94290931Srodrigc	env->sc_user_lines = linep;
95322882Saraujo	log_debug("done pushing users");
96290931Srodrigc
97290931Srodrigc	wrlen = env->sc_group_line_len;
98290931Srodrigc	if ((linep = calloc(1, env->sc_group_line_len + 1)) == NULL) {
99290931Srodrigc		/*
100290931Srodrigc		 * XXX: try allocating a smaller chunk of memory
101290931Srodrigc		 */
102290931Srodrigc		fatal("out of memory");
103290931Srodrigc	}
104290931Srodrigc	endp = linep;
105290931Srodrigc	RB_FOREACH(ge, group_name_tree, env->sc_group_names) {
106290931Srodrigc		/*
107290931Srodrigc		 * we convert the first nul back to a column,
108290931Srodrigc		 * copy the string and then convert it back to a nul.
109290931Srodrigc		 */
110290931Srodrigc		ge->ge_line[strlen(ge->ge_line)] = ':';
111290931Srodrigc		log_debug("pushing line: %s", ge->ge_line);
112290931Srodrigc		len = strlen(ge->ge_line) + 1;
113290931Srodrigc		memcpy(endp, ge->ge_line, len);
114290931Srodrigc		endp[strcspn(endp, ":")] = '\0';
115290931Srodrigc		free(ge->ge_line);
116290931Srodrigc		ge->ge_line = endp;
117290931Srodrigc		endp += len;
118290931Srodrigc		wrlen -= len;
119290931Srodrigc	}
120290931Srodrigc	env->sc_group_lines = linep;
121322882Saraujo	log_debug("done pushing groups");
122290931Srodrigc}
123290931Srodrigc
124290931Srodrigcint
125290931Srodrigcuserent_name_cmp(struct userent *ue1, struct userent *ue2)
126290931Srodrigc{
127290931Srodrigc	return (strcmp(ue1->ue_line, ue2->ue_line));
128290931Srodrigc}
129290931Srodrigc
130290931Srodrigcint
131290931Srodrigcuserent_uid_cmp(struct userent *ue1, struct userent *ue2)
132290931Srodrigc{
133290931Srodrigc	return (ue1->ue_uid - ue2->ue_uid);
134290931Srodrigc}
135290931Srodrigc
136290931Srodrigcint
137290931Srodrigcgroupent_name_cmp(struct groupent *ge1, struct groupent *ge2)
138290931Srodrigc{
139290931Srodrigc	return (strcmp(ge1->ge_line, ge2->ge_line));
140290931Srodrigc}
141290931Srodrigc
142290931Srodrigcint
143290931Srodrigcgroupent_gid_cmp(struct groupent *ge1, struct groupent *ge2)
144290931Srodrigc{
145290931Srodrigc	return (ge1->ge_gid - ge2->ge_gid);
146290931Srodrigc}
147290931Srodrigc
148290931SrodrigcRB_GENERATE(user_name_tree, userent, ue_name_node, userent_name_cmp);
149290931SrodrigcRB_GENERATE(user_uid_tree, userent, ue_uid_node, userent_uid_cmp);
150290931SrodrigcRB_GENERATE(group_name_tree, groupent, ge_name_node, groupent_name_cmp);
151290931SrodrigcRB_GENERATE(group_gid_tree, groupent, ge_gid_node, groupent_gid_cmp);
152