1 /* $OpenBSD: entries.c,v 1.3 2015/01/16 06:40:22 deraadt Exp $ */ 2 /* 3 * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/types.h> 19 #include <sys/param.h> 20 #include <sys/queue.h> 21 #include <sys/socket.h> 22 #include <sys/tree.h> 23 24 #include <netinet/in.h> 25 #include <arpa/inet.h> 26 27 #include <errno.h> 28 #include <event.h> 29 #include <fcntl.h> 30 #include <unistd.h> 31 #include <pwd.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <limits.h> 36 37 #include "ypldap.h" 38 39 void 40 flatten_entries(struct env *env) 41 { 42 size_t len; 43 char *linep; 44 char *endp; 45 char *tmp; 46 struct userent *ue; 47 struct groupent *ge; 48 49 log_debug("flattening trees"); 50 /* 51 * This takes all the line pointers in RB elements and 52 * concatenates them in a single string, to be able to 53 * implement next element lookup without tree traversal. 54 * 55 * An extra octet is alloced to make space for an additional NUL. 56 */ 57 if ((linep = calloc(1, env->sc_user_line_len + 1)) == NULL) { 58 /* 59 * XXX: try allocating a smaller chunk of memory 60 */ 61 fatal("out of memory"); 62 } 63 endp = linep; 64 65 RB_FOREACH(ue, user_name_tree, env->sc_user_names) { 66 /* 67 * we convert the first nul back to a column, 68 * copy the string and then convert it back to a nul. 69 */ 70 ue->ue_line[strlen(ue->ue_line)] = ':'; 71 log_debug("pushing line: %s", ue->ue_line); 72 len = strlen(ue->ue_line) + 1; 73 memcpy(endp, ue->ue_line, len); 74 endp[strcspn(endp, ":")] = '\0'; 75 free(ue->ue_line); 76 ue->ue_line = endp; 77 endp += len; 78 79 /* 80 * To save memory strdup(3) the netid_line which originally used 81 * LINE_WIDTH bytes 82 */ 83 tmp = ue->ue_netid_line; 84 ue->ue_netid_line = strdup(tmp); 85 if (ue->ue_netid_line == NULL) { 86 fatal("out of memory"); 87 } 88 free(tmp); 89 } 90 env->sc_user_lines = linep; 91 log_debug("done pushing users"); 92 93 if ((linep = calloc(1, env->sc_group_line_len + 1)) == NULL) { 94 /* 95 * XXX: try allocating a smaller chunk of memory 96 */ 97 fatal("out of memory"); 98 } 99 endp = linep; 100 RB_FOREACH(ge, group_name_tree, env->sc_group_names) { 101 /* 102 * we convert the first nul back to a column, 103 * copy the string and then convert it back to a nul. 104 */ 105 ge->ge_line[strlen(ge->ge_line)] = ':'; 106 log_debug("pushing line: %s", ge->ge_line); 107 len = strlen(ge->ge_line) + 1; 108 memcpy(endp, ge->ge_line, len); 109 endp[strcspn(endp, ":")] = '\0'; 110 free(ge->ge_line); 111 ge->ge_line = endp; 112 endp += len; 113 } 114 env->sc_group_lines = linep; 115 log_debug("done pushing groups"); 116 } 117 118 int 119 userent_name_cmp(struct userent *ue1, struct userent *ue2) 120 { 121 return (strcmp(ue1->ue_line, ue2->ue_line)); 122 } 123 124 int 125 userent_uid_cmp(struct userent *ue1, struct userent *ue2) 126 { 127 return (ue1->ue_uid - ue2->ue_uid); 128 } 129 130 int 131 groupent_name_cmp(struct groupent *ge1, struct groupent *ge2) 132 { 133 return (strcmp(ge1->ge_line, ge2->ge_line)); 134 } 135 136 int 137 groupent_gid_cmp(struct groupent *ge1, struct groupent *ge2) 138 { 139 return (ge1->ge_gid - ge2->ge_gid); 140 } 141 142 RB_GENERATE(user_name_tree, userent, ue_name_node, userent_name_cmp); 143 RB_GENERATE(user_uid_tree, userent, ue_uid_node, userent_uid_cmp); 144 RB_GENERATE(group_name_tree, groupent, ge_name_node, groupent_name_cmp); 145 RB_GENERATE(group_gid_tree, groupent, ge_gid_node, groupent_gid_cmp); 146