1 /* $OpenBSD: attributes.c,v 1.7 2021/12/20 13:26:11 claudio Exp $ */ 2 3 /* 4 * Copyright (c) 2009 Martin Hedenfalk <martin@bzero.se> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/queue.h> 20 #include <sys/types.h> 21 22 #include <assert.h> 23 #include <string.h> 24 #include <time.h> 25 26 #include "ldapd.h" 27 #include "log.h" 28 29 struct ber_element * 30 ldap_get_attribute(struct ber_element *entry, const char *attr) 31 { 32 char *s; 33 struct ber_element *elm, *a; 34 35 assert(entry); 36 assert(attr); 37 if (entry->be_encoding != BER_TYPE_SEQUENCE) 38 return NULL; 39 40 for (elm = entry->be_sub; elm != NULL; elm = elm->be_next) { 41 a = elm->be_sub; 42 if (a && ober_get_string(a, &s) == 0 && strcasecmp(s, attr) == 0) 43 return a; 44 } 45 46 return NULL; 47 } 48 49 struct ber_element * 50 ldap_find_attribute(struct ber_element *entry, struct attr_type *at) 51 { 52 struct ber_element *elm = NULL; 53 struct name *an; 54 55 SLIST_FOREACH(an, at->names, next) { 56 if ((elm = ldap_get_attribute(entry, an->name)) != NULL) 57 return elm; 58 } 59 if (an == NULL) 60 elm = ldap_get_attribute(entry, at->oid); 61 62 return elm; 63 } 64 65 struct ber_element * 66 ldap_find_value(struct ber_element *elm, const char *value) 67 { 68 char *s; 69 struct ber_element *a; 70 71 if (elm == NULL) 72 return NULL; 73 74 for (a = elm->be_sub; a != NULL; a = a->be_next) { 75 if (ober_get_string(a, &s) == 0 && strcasecmp(s, value) == 0) 76 return a; 77 } 78 79 return NULL; 80 } 81 82 struct ber_element * 83 ldap_add_attribute(struct ber_element *entry, const char *attr, 84 struct ber_element *value_set) 85 { 86 struct ber_element *elm, *a, *last; 87 88 assert(entry); 89 assert(attr); 90 assert(value_set); 91 92 if (entry->be_encoding != BER_TYPE_SEQUENCE) { 93 log_warnx("entries should be a sequence"); 94 return NULL; 95 } 96 97 if (value_set->be_type != BER_TYPE_SET) { 98 log_warnx("values should be a set"); 99 return NULL; 100 } 101 102 last = entry->be_sub; 103 if (last == NULL) 104 last = entry; 105 else while (last != NULL && last->be_next != NULL) 106 last = last->be_next; 107 108 if ((elm = ober_add_sequence(last)) == NULL) 109 return NULL; 110 if ((a = ober_add_string(elm, attr)) == NULL) { 111 ober_free_elements(elm); 112 return NULL; 113 } 114 ober_link_elements(a, value_set); 115 116 return elm; 117 } 118 119 int 120 ldap_set_values(struct ber_element *elm, struct ber_element *vals) 121 { 122 char *attr; 123 struct ber_element *old_vals; 124 125 assert(elm); 126 assert(vals); 127 assert(vals->be_sub); 128 129 if (ober_scanf_elements(elm, "se(", &attr, &old_vals) != 0) { 130 log_warnx("failed to parse element"); 131 return -1; 132 } 133 134 ober_free_elements(old_vals->be_sub); 135 old_vals->be_sub = NULL; 136 ober_link_elements(old_vals, vals->be_sub); 137 138 vals->be_sub = NULL; 139 ober_free_elements(vals); 140 141 return 0; 142 } 143 144 int 145 ldap_merge_values(struct ber_element *elm, struct ber_element *vals) 146 { 147 char *attr; 148 struct ber_element *old_vals, *last; 149 150 assert(elm); 151 assert(vals); 152 assert(vals->be_type == BER_TYPE_SET); 153 assert(vals->be_sub); 154 155 if (ober_scanf_elements(elm, "se(", &attr, &old_vals) != 0) { 156 log_warnx("failed to parse element"); 157 return -1; 158 } 159 160 last = old_vals->be_sub; 161 while (last && last->be_next) 162 last = last->be_next; 163 164 ober_link_elements(last, vals->be_sub); 165 166 vals->be_sub = NULL; 167 ober_free_elements(vals); 168 169 return 0; 170 } 171 172 173 int 174 ldap_del_attribute(struct ber_element *entry, const char *attrdesc) 175 { 176 struct ber_element *attr, *prev = NULL; 177 char *s; 178 179 assert(entry); 180 assert(attrdesc); 181 182 attr = entry->be_sub; 183 while (attr) { 184 if (ober_scanf_elements(attr, "{s", &s) != 0) { 185 log_warnx("failed to parse attribute"); 186 return -1; 187 } 188 189 if (strcasecmp(s, attrdesc) == 0) { 190 if (prev == NULL) 191 entry->be_sub = attr->be_next; 192 else 193 prev->be_next = attr->be_next; 194 attr->be_next = NULL; 195 ober_free_elements(attr); 196 break; 197 } 198 199 prev = attr; 200 attr = attr->be_next; 201 } 202 203 return 0; 204 } 205 206 int 207 ldap_del_values(struct ber_element *elm, struct ber_element *vals) 208 { 209 char *attr; 210 struct ber_element *old_vals, *v, *x, *prev, *next; 211 struct ber_element *removed; 212 int removed_p; 213 assert(elm); 214 assert(vals); 215 assert(vals->be_sub); 216 217 if (ober_scanf_elements(elm, "se(", &attr, &old_vals) != 0) { 218 log_warnx("failed to parse element"); 219 return -1; 220 } 221 222 prev = old_vals; 223 removed_p = 0; 224 for (v = old_vals->be_sub; v; v = next) { 225 next = v->be_next; 226 227 for (x = vals->be_sub; x; x = x->be_next) { 228 if (x && v->be_len == x->be_len && 229 memcmp(v->be_val, x->be_val, x->be_len) == 0) { 230 removed = ober_unlink_elements(prev); 231 ober_link_elements(prev, removed->be_next); 232 ober_free_element(removed); 233 removed_p = 1; 234 break; 235 } 236 } 237 if (removed_p) { 238 removed_p = 0; 239 } else { 240 prev = v; 241 } 242 } 243 244 if (old_vals->be_sub == NULL) 245 return 1; 246 247 return 0; 248 } 249 250 char * 251 ldap_strftime(time_t tm) 252 { 253 static char tmbuf[16]; 254 struct tm *gmt = gmtime(&tm); 255 256 strftime(tmbuf, sizeof(tmbuf), "%Y%m%d%H%M%SZ", gmt); 257 return tmbuf; 258 } 259 260 char * 261 ldap_now(void) 262 { 263 return ldap_strftime(time(0)); 264 } 265 266