entries.c revision 290931
1290931Srodrigc/*	$OpenBSD: entries.c,v 1.3 2015/01/16 06:40:22 deraadt Exp $ */
2290931Srodrigc/*	$FreeBSD: head/usr.sbin/ypldap/entries.c 290931 2015-11-16 16:48:43Z rodrigc $ */
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>
20290931Srodrigc#include <sys/queue.h>
21290931Srodrigc#include <sys/socket.h>
22290931Srodrigc#include <sys/tree.h>
23290931Srodrigc
24290931Srodrigc#include <netinet/in.h>
25290931Srodrigc#include <arpa/inet.h>
26290931Srodrigc
27290931Srodrigc#include <errno.h>
28290931Srodrigc#include <event.h>
29290931Srodrigc#include <fcntl.h>
30290931Srodrigc#include <unistd.h>
31290931Srodrigc#include <pwd.h>
32290931Srodrigc#include <stdio.h>
33290931Srodrigc#include <stdlib.h>
34290931Srodrigc#include <string.h>
35290931Srodrigc#include <limits.h>
36290931Srodrigc
37290931Srodrigc#include "ypldap.h"
38290931Srodrigc
39290931Srodrigcvoid
40290931Srodrigcflatten_entries(struct env *env)
41290931Srodrigc{
42290931Srodrigc	size_t		 wrlen;
43290931Srodrigc	size_t		 len;
44290931Srodrigc	char		*linep;
45290931Srodrigc	char		*endp;
46290931Srodrigc	char		*tmp;
47290931Srodrigc	struct userent	*ue;
48290931Srodrigc	struct groupent	*ge;
49290931Srodrigc
50290931Srodrigc	log_debug("flattening trees");
51290931Srodrigc	/*
52290931Srodrigc	 * This takes all the line pointers in RB elements and
53290931Srodrigc	 * concatenates them in a single string, to be able to
54290931Srodrigc	 * implement next element lookup without tree traversal.
55290931Srodrigc	 *
56290931Srodrigc	 * An extra octet is alloced to make space for an additional NUL.
57290931Srodrigc	 */
58290931Srodrigc	wrlen = env->sc_user_line_len;
59290931Srodrigc	if ((linep = calloc(1, env->sc_user_line_len + 1)) == NULL) {
60290931Srodrigc		/*
61290931Srodrigc		 * XXX: try allocating a smaller chunk of memory
62290931Srodrigc		 */
63290931Srodrigc		fatal("out of memory");
64290931Srodrigc	}
65290931Srodrigc	endp = linep;
66290931Srodrigc
67290931Srodrigc	RB_FOREACH(ue, user_name_tree, env->sc_user_names) {
68290931Srodrigc		/*
69290931Srodrigc		 * we convert the first nul back to a column,
70290931Srodrigc		 * copy the string and then convert it back to a nul.
71290931Srodrigc		 */
72290931Srodrigc		ue->ue_line[strlen(ue->ue_line)] = ':';
73290931Srodrigc		log_debug("pushing line: %s", ue->ue_line);
74290931Srodrigc		len = strlen(ue->ue_line) + 1;
75290931Srodrigc		memcpy(endp, ue->ue_line, len);
76290931Srodrigc		endp[strcspn(endp, ":")] = '\0';
77290931Srodrigc		free(ue->ue_line);
78290931Srodrigc		ue->ue_line = endp;
79290931Srodrigc		endp += len;
80290931Srodrigc		wrlen -= len;
81290931Srodrigc
82290931Srodrigc		/*
83290931Srodrigc		 * To save memory strdup(3) the netid_line which originally used
84290931Srodrigc		 * LINE_WIDTH bytes
85290931Srodrigc		 */
86290931Srodrigc		tmp = ue->ue_netid_line;
87290931Srodrigc		ue->ue_netid_line = strdup(tmp);
88290931Srodrigc		if (ue->ue_netid_line == NULL) {
89290931Srodrigc			fatal("out of memory");
90290931Srodrigc		}
91290931Srodrigc		free(tmp);
92290931Srodrigc	}
93290931Srodrigc	env->sc_user_lines = linep;
94290931Srodrigc
95290931Srodrigc	wrlen = env->sc_group_line_len;
96290931Srodrigc	if ((linep = calloc(1, env->sc_group_line_len + 1)) == NULL) {
97290931Srodrigc		/*
98290931Srodrigc		 * XXX: try allocating a smaller chunk of memory
99290931Srodrigc		 */
100290931Srodrigc		fatal("out of memory");
101290931Srodrigc	}
102290931Srodrigc	endp = linep;
103290931Srodrigc	RB_FOREACH(ge, group_name_tree, env->sc_group_names) {
104290931Srodrigc		/*
105290931Srodrigc		 * we convert the first nul back to a column,
106290931Srodrigc		 * copy the string and then convert it back to a nul.
107290931Srodrigc		 */
108290931Srodrigc		ge->ge_line[strlen(ge->ge_line)] = ':';
109290931Srodrigc		log_debug("pushing line: %s", ge->ge_line);
110290931Srodrigc		len = strlen(ge->ge_line) + 1;
111290931Srodrigc		memcpy(endp, ge->ge_line, len);
112290931Srodrigc		endp[strcspn(endp, ":")] = '\0';
113290931Srodrigc		free(ge->ge_line);
114290931Srodrigc		ge->ge_line = endp;
115290931Srodrigc		endp += len;
116290931Srodrigc		wrlen -= len;
117290931Srodrigc	}
118290931Srodrigc	env->sc_group_lines = linep;
119290931Srodrigc}
120290931Srodrigc
121290931Srodrigcint
122290931Srodrigcuserent_name_cmp(struct userent *ue1, struct userent *ue2)
123290931Srodrigc{
124290931Srodrigc	return (strcmp(ue1->ue_line, ue2->ue_line));
125290931Srodrigc}
126290931Srodrigc
127290931Srodrigcint
128290931Srodrigcuserent_uid_cmp(struct userent *ue1, struct userent *ue2)
129290931Srodrigc{
130290931Srodrigc	return (ue1->ue_uid - ue2->ue_uid);
131290931Srodrigc}
132290931Srodrigc
133290931Srodrigcint
134290931Srodrigcgroupent_name_cmp(struct groupent *ge1, struct groupent *ge2)
135290931Srodrigc{
136290931Srodrigc	return (strcmp(ge1->ge_line, ge2->ge_line));
137290931Srodrigc}
138290931Srodrigc
139290931Srodrigcint
140290931Srodrigcgroupent_gid_cmp(struct groupent *ge1, struct groupent *ge2)
141290931Srodrigc{
142290931Srodrigc	return (ge1->ge_gid - ge2->ge_gid);
143290931Srodrigc}
144290931Srodrigc
145290931SrodrigcRB_GENERATE(user_name_tree, userent, ue_name_node, userent_name_cmp);
146290931SrodrigcRB_GENERATE(user_uid_tree, userent, ue_uid_node, userent_uid_cmp);
147290931SrodrigcRB_GENERATE(group_name_tree, groupent, ge_name_node, groupent_name_cmp);
148290931SrodrigcRB_GENERATE(group_gid_tree, groupent, ge_gid_node, groupent_gid_cmp);
149