1 /* $OpenBSD: attributes.c,v 1.3 2010/10/19 09:34:41 martinh 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 28 struct ber_element * 29 ldap_get_attribute(struct ber_element *entry, const char *attr) 30 { 31 char *s; 32 struct ber_element *elm, *a; 33 34 assert(entry); 35 assert(attr); 36 if (entry->be_encoding != BER_TYPE_SEQUENCE) 37 return NULL; 38 39 for (elm = entry->be_sub; elm != NULL; elm = elm->be_next) { 40 a = elm->be_sub; 41 if (a && ber_get_string(a, &s) == 0 && strcasecmp(s, attr) == 0) 42 return a; 43 } 44 45 return NULL; 46 } 47 48 struct ber_element * 49 ldap_find_attribute(struct ber_element *entry, struct attr_type *at) 50 { 51 struct ber_element *elm = NULL; 52 struct name *an; 53 54 SLIST_FOREACH(an, at->names, next) { 55 if ((elm = ldap_get_attribute(entry, an->name)) != NULL) 56 return elm; 57 } 58 if (an == NULL) 59 elm = ldap_get_attribute(entry, at->oid); 60 61 return elm; 62 } 63 64 struct ber_element * 65 ldap_find_value(struct ber_element *elm, const char *value) 66 { 67 char *s; 68 struct ber_element *a; 69 70 if (elm == NULL) 71 return NULL; 72 73 for (a = elm->be_sub; a != NULL; a = a->be_next) { 74 if (ber_get_string(a, &s) == 0 && strcasecmp(s, value) == 0) 75 return a; 76 } 77 78 return NULL; 79 } 80 81 struct ber_element * 82 ldap_add_attribute(struct ber_element *entry, const char *attr, 83 struct ber_element *value_set) 84 { 85 struct ber_element *elm, *a, *last; 86 87 assert(entry); 88 assert(attr); 89 assert(value_set); 90 91 if (entry->be_encoding != BER_TYPE_SEQUENCE) { 92 log_warnx("entries should be a sequence"); 93 return NULL; 94 } 95 96 if (value_set->be_type != BER_TYPE_SET) { 97 log_warnx("values should be a set"); 98 return NULL; 99 } 100 101 last = entry->be_sub; 102 if (last == NULL) 103 last = entry; 104 else while (last != NULL && last->be_next != NULL) 105 last = last->be_next; 106 107 if ((elm = ber_add_sequence(last)) == NULL) 108 return NULL; 109 if ((a = ber_add_string(elm, attr)) == NULL) { 110 ber_free_elements(elm); 111 return NULL; 112 } 113 ber_link_elements(a, value_set); 114 115 return elm; 116 } 117 118 int 119 ldap_set_values(struct ber_element *elm, struct ber_element *vals) 120 { 121 char *attr; 122 struct ber_element *old_vals; 123 124 assert(elm); 125 assert(vals); 126 assert(vals->be_sub); 127 128 if (ber_scanf_elements(elm, "se(", &attr, &old_vals) != 0) { 129 log_warnx("failed to parse element"); 130 return -1; 131 } 132 133 ber_free_elements(old_vals->be_sub); 134 old_vals->be_sub = NULL; 135 ber_link_elements(old_vals, vals->be_sub); 136 137 vals->be_sub = NULL; 138 ber_free_elements(vals); 139 140 return 0; 141 } 142 143 int 144 ldap_merge_values(struct ber_element *elm, struct ber_element *vals) 145 { 146 char *attr; 147 struct ber_element *old_vals, *last; 148 149 assert(elm); 150 assert(vals); 151 assert(vals->be_type == BER_TYPE_SET); 152 assert(vals->be_sub); 153 154 if (ber_scanf_elements(elm, "se(", &attr, &old_vals) != 0) { 155 log_warnx("failed to parse element"); 156 return -1; 157 } 158 159 last = old_vals->be_sub; 160 while (last && last->be_next) 161 last = last->be_next; 162 163 ber_link_elements(last, vals->be_sub); 164 165 vals->be_sub = NULL; 166 ber_free_elements(vals); 167 168 return 0; 169 } 170 171 172 int 173 ldap_del_attribute(struct ber_element *entry, const char *attrdesc) 174 { 175 struct ber_element *attr, *prev = NULL; 176 char *s; 177 178 assert(entry); 179 assert(attrdesc); 180 181 attr = entry->be_sub; 182 while (attr) { 183 if (ber_scanf_elements(attr, "{s(", &s) != 0) { 184 log_warnx("failed to parse attribute"); 185 return -1; 186 } 187 188 if (strcasecmp(s, attrdesc) == 0) { 189 if (prev == NULL) 190 entry->be_sub = attr->be_next; 191 else 192 prev->be_next = attr->be_next; 193 attr->be_next = NULL; 194 ber_free_elements(attr); 195 break; 196 } 197 198 prev = attr; 199 attr = attr->be_next; 200 } 201 202 return 0; 203 } 204 205 int 206 ldap_del_values(struct ber_element *elm, struct ber_element *vals) 207 { 208 char *attr; 209 struct ber_element *old_vals, *v, *x, *vk, *xk, *prev; 210 struct ber_element *removed; 211 212 assert(elm); 213 assert(vals); 214 assert(vals->be_sub); 215 216 if (ber_scanf_elements(elm, "se(", &attr, &old_vals) != 0) { 217 log_warnx("failed to parse element"); 218 return -1; 219 } 220 221 prev = old_vals; 222 for (v = old_vals->be_sub; v; v = v->be_next) { 223 vk = v->be_sub; 224 for (x = vals->be_sub; x; x = x->be_next) { 225 xk = x->be_sub; 226 if (xk && vk->be_len == xk->be_len && 227 memcmp(vk->be_val, xk->be_val, xk->be_len) == 0) { 228 removed = ber_unlink_elements(prev); 229 ber_link_elements(prev, removed->be_next); 230 ber_free_elements(removed); 231 break; 232 } 233 } 234 prev = v; 235 } 236 237 return 0; 238 } 239 240 char * 241 ldap_strftime(time_t tm) 242 { 243 static char tmbuf[16]; 244 struct tm *gmt = gmtime(&tm); 245 246 strftime(tmbuf, sizeof(tmbuf), "%Y%m%d%H%M%SZ", gmt); 247 return tmbuf; 248 } 249 250 char * 251 ldap_now(void) 252 { 253 return ldap_strftime(time(0)); 254 } 255 256