1 /* $OpenBSD: entries.c,v 1.4 2017/07/12 23:18:24 jca 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/queue.h> 20 #include <sys/socket.h> 21 #include <sys/tree.h> 22 23 #include <netinet/in.h> 24 #include <arpa/inet.h> 25 26 #include <errno.h> 27 #include <event.h> 28 #include <fcntl.h> 29 #include <unistd.h> 30 #include <pwd.h> 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <string.h> 34 #include <limits.h> 35 36 #include "ypldap.h" 37 38 void 39 flatten_entries(struct env *env) 40 { 41 size_t wrlen; 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 wrlen = env->sc_user_line_len; 58 if ((linep = calloc(1, env->sc_user_line_len + 1)) == NULL) { 59 /* 60 * XXX: try allocating a smaller chunk of memory 61 */ 62 fatal("out of memory"); 63 } 64 endp = linep; 65 66 RB_FOREACH(ue, user_name_tree, env->sc_user_names) { 67 /* 68 * we convert the first nul back to a column, 69 * copy the string and then convert it back to a nul. 70 */ 71 ue->ue_line[strlen(ue->ue_line)] = ':'; 72 log_debug("pushing line: %s", ue->ue_line); 73 len = strlen(ue->ue_line) + 1; 74 memcpy(endp, ue->ue_line, len); 75 endp[strcspn(endp, ":")] = '\0'; 76 free(ue->ue_line); 77 ue->ue_line = endp; 78 endp += len; 79 wrlen -= len; 80 81 /* 82 * To save memory strdup(3) the netid_line which originally used 83 * LINE_WIDTH bytes 84 */ 85 tmp = ue->ue_netid_line; 86 ue->ue_netid_line = strdup(tmp); 87 if (ue->ue_netid_line == NULL) { 88 fatal("out of memory"); 89 } 90 free(tmp); 91 } 92 env->sc_user_lines = linep; 93 log_debug("done pushing users"); 94 95 wrlen = env->sc_group_line_len; 96 if ((linep = calloc(1, env->sc_group_line_len + 1)) == NULL) { 97 /* 98 * XXX: try allocating a smaller chunk of memory 99 */ 100 fatal("out of memory"); 101 } 102 endp = linep; 103 RB_FOREACH(ge, group_name_tree, env->sc_group_names) { 104 /* 105 * we convert the first nul back to a column, 106 * copy the string and then convert it back to a nul. 107 */ 108 ge->ge_line[strlen(ge->ge_line)] = ':'; 109 log_debug("pushing line: %s", ge->ge_line); 110 len = strlen(ge->ge_line) + 1; 111 memcpy(endp, ge->ge_line, len); 112 endp[strcspn(endp, ":")] = '\0'; 113 free(ge->ge_line); 114 ge->ge_line = endp; 115 endp += len; 116 wrlen -= len; 117 } 118 env->sc_group_lines = linep; 119 log_debug("done pushing groups"); 120 } 121 122 int 123 userent_name_cmp(struct userent *ue1, struct userent *ue2) 124 { 125 return (strcmp(ue1->ue_line, ue2->ue_line)); 126 } 127 128 int 129 userent_uid_cmp(struct userent *ue1, struct userent *ue2) 130 { 131 return (ue1->ue_uid - ue2->ue_uid); 132 } 133 134 int 135 groupent_name_cmp(struct groupent *ge1, struct groupent *ge2) 136 { 137 return (strcmp(ge1->ge_line, ge2->ge_line)); 138 } 139 140 int 141 groupent_gid_cmp(struct groupent *ge1, struct groupent *ge2) 142 { 143 return (ge1->ge_gid - ge2->ge_gid); 144 } 145 146 RB_GENERATE(user_name_tree, userent, ue_name_node, userent_name_cmp); 147 RB_GENERATE(user_uid_tree, userent, ue_uid_node, userent_uid_cmp); 148 RB_GENERATE(group_name_tree, groupent, ge_name_node, groupent_name_cmp); 149 RB_GENERATE(group_gid_tree, groupent, ge_gid_node, groupent_gid_cmp); 150