| File: | daemons/ipa-slapi-plugins/ipa-uuid/ipa_uuid.c |
| Warning: | line 908, column 5 Value stored to 'list' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /** BEGIN COPYRIGHT BLOCK |
| 2 | * This program is free software; you can redistribute it and/or modify |
| 3 | * it under the terms of the GNU General Public License as published by |
| 4 | * the Free Software Foundation, either version 3 of the License, or |
| 5 | * (at your option) any later version. |
| 6 | * |
| 7 | * This program is distributed in the hope that it will be useful, |
| 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 10 | * GNU General Public License for more details. |
| 11 | * |
| 12 | * You should have received a copy of the GNU General Public License |
| 13 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 14 | * |
| 15 | * Additional permission under GPLv3 section 7: |
| 16 | * |
| 17 | * In the following paragraph, "GPL" means the GNU General Public |
| 18 | * License, version 3 or any later version, and "Non-GPL Code" means |
| 19 | * code that is governed neither by the GPL nor a license |
| 20 | * compatible with the GPL. |
| 21 | * |
| 22 | * You may link the code of this Program with Non-GPL Code and convey |
| 23 | * linked combinations including the two, provided that such Non-GPL |
| 24 | * Code only links to the code of this Program through those well |
| 25 | * defined interfaces identified in the file named EXCEPTION found in |
| 26 | * the source code files (the "Approved Interfaces"). The files of |
| 27 | * Non-GPL Code may instantiate templates or use macros or inline |
| 28 | * functions from the Approved Interfaces without causing the resulting |
| 29 | * work to be covered by the GPL. Only the copyright holders of this |
| 30 | * Program may make changes or additions to the list of Approved |
| 31 | * Interfaces. |
| 32 | * |
| 33 | * Copyright (C) 2010 Red Hat, Inc. |
| 34 | * All rights reserved. |
| 35 | * END COPYRIGHT BLOCK **/ |
| 36 | |
| 37 | /** |
| 38 | * IPA UUID plug-in |
| 39 | */ |
| 40 | #include <string.h> |
| 41 | #include <stdbool.h> |
| 42 | #include "slapi-plugin.h" |
| 43 | #include "nspr.h" |
| 44 | #include "prclist.h" |
| 45 | #include "uuid/uuid.h" |
| 46 | #include <pthread.h> |
| 47 | |
| 48 | #include "util.h" |
| 49 | |
| 50 | #define IPAUUID_STR_SIZE36 36 |
| 51 | |
| 52 | #define IPAUUID_PLUGIN_NAME"ipa-uuid-plugin" "ipa-uuid-plugin" |
| 53 | #define IPAUUID_PLUGIN_VERSION0x00010000 0x00010000 |
| 54 | |
| 55 | #define IPAUUID_DN"cn=IPA UUID,cn=plugins,cn=config" "cn=IPA UUID,cn=plugins,cn=config" /* temporary */ |
| 56 | |
| 57 | #define IPA_PLUGIN_NAME"ipa-uuid-plugin" IPAUUID_PLUGIN_NAME"ipa-uuid-plugin" |
| 58 | |
| 59 | /** |
| 60 | * IPA UUID config types |
| 61 | */ |
| 62 | #define IPAUUID_ATTR"ipaUuidAttr" "ipaUuidAttr" |
| 63 | #define IPAUUID_PREFIX"ipaUuidPrefix" "ipaUuidPrefix" |
| 64 | #define IPAUUID_GENERATE"ipaUuidMagicRegen" "ipaUuidMagicRegen" |
| 65 | #define IPAUUID_FILTER"ipaUuidFilter" "ipaUuidFilter" |
| 66 | #define IPAUUID_SCOPE"ipaUuidScope" "ipaUuidScope" |
| 67 | #define IPAUUID_EXCLUDE_SUBTREE"ipaUuidExcludeSubtree" "ipaUuidExcludeSubtree" |
| 68 | #define IPAUUID_ENFORCE"ipaUuidEnforce" "ipaUuidEnforce" |
| 69 | |
| 70 | #define IPAUUID_FEATURE_DESC"IPA UUID" "IPA UUID" |
| 71 | #define IPAUUID_PLUGIN_DESC"IPA UUID plugin" "IPA UUID plugin" |
| 72 | #define IPAUUID_INT_PREOP_DESC"IPA UUID internal preop plugin" "IPA UUID internal preop plugin" |
| 73 | #define IPAUUID_POSTOP_DESC"IPA UUID postop plugin" "IPA UUID postop plugin" |
| 74 | |
| 75 | static Slapi_PluginDesc pdesc = { |
| 76 | IPAUUID_FEATURE_DESC"IPA UUID", |
| 77 | "Red Hat, Inc.", |
| 78 | "1.0", |
| 79 | IPAUUID_PLUGIN_DESC"IPA UUID plugin" |
| 80 | }; |
| 81 | |
| 82 | /** |
| 83 | * linked list of config entries |
| 84 | */ |
| 85 | |
| 86 | struct configEntry { |
| 87 | PRCList list; |
| 88 | char *dn; |
| 89 | char *attr; |
| 90 | char *prefix; |
| 91 | char *filter; |
| 92 | Slapi_Filter *slapi_filter; |
| 93 | char *generate; |
| 94 | char *scope; |
| 95 | char *exclude_subtree; |
| 96 | bool_Bool enforce; |
| 97 | }; |
| 98 | |
| 99 | static PRCList *ipauuid_global_config = NULL((void*)0); |
| 100 | static pthread_rwlock_t g_ipauuid_cache_lock; |
| 101 | |
| 102 | static void *_PluginID = NULL((void*)0); |
| 103 | static char *_PluginDN = NULL((void*)0); |
| 104 | |
| 105 | static int g_plugin_started = 0; |
| 106 | |
| 107 | |
| 108 | /** |
| 109 | * |
| 110 | * management functions |
| 111 | * |
| 112 | */ |
| 113 | int ipauuid_init(Slapi_PBlock * pb); |
| 114 | static int ipauuid_start(Slapi_PBlock * pb); |
| 115 | static int ipauuid_close(Slapi_PBlock * pb); |
| 116 | static int ipauuid_internal_preop_init(Slapi_PBlock *pb); |
| 117 | static int ipauuid_postop_init(Slapi_PBlock * pb); |
| 118 | |
| 119 | /** |
| 120 | * |
| 121 | * Local operation functions |
| 122 | * |
| 123 | */ |
| 124 | static int ipauuid_load_plugin_config(void); |
| 125 | static int ipauuid_parse_config_entry(Slapi_Entry * e, bool_Bool apply); |
| 126 | static void ipauuid_delete_config(void); |
| 127 | static void ipauuid_free_config_entry(struct configEntry ** entry); |
| 128 | |
| 129 | /** |
| 130 | * |
| 131 | * helpers |
| 132 | * |
| 133 | */ |
| 134 | static char *ipauuid_get_dn(Slapi_PBlock * pb); |
| 135 | static int ipauuid_dn_is_config(char *dn); |
| 136 | static int ipauuid_list_contains_attr(char **list, char *attr); |
| 137 | |
| 138 | /** |
| 139 | * |
| 140 | * the ops (where the real work is done) |
| 141 | * |
| 142 | */ |
| 143 | static int ipauuid_config_check_post_op(Slapi_PBlock * pb); |
| 144 | static int ipauuid_pre_op(Slapi_PBlock * pb, int modtype); |
| 145 | static int ipauuid_mod_pre_op(Slapi_PBlock * pb); |
| 146 | static int ipauuid_add_pre_op(Slapi_PBlock * pb); |
| 147 | |
| 148 | /** |
| 149 | * debug functions - global, for the debugger |
| 150 | */ |
| 151 | void ipauuid_dump_config(void); |
| 152 | void ipauuid_dump_config_entry(struct configEntry *); |
| 153 | |
| 154 | /** |
| 155 | * |
| 156 | * Deal with cache locking |
| 157 | * |
| 158 | */ |
| 159 | void ipauuid_read_lock(void) |
| 160 | { |
| 161 | pthread_rwlock_rdlock(&g_ipauuid_cache_lock); |
| 162 | } |
| 163 | |
| 164 | void ipauuid_write_lock(void) |
| 165 | { |
| 166 | pthread_rwlock_wrlock(&g_ipauuid_cache_lock); |
| 167 | } |
| 168 | |
| 169 | void ipauuid_unlock(void) |
| 170 | { |
| 171 | pthread_rwlock_unlock(&g_ipauuid_cache_lock); |
| 172 | } |
| 173 | |
| 174 | /** |
| 175 | * |
| 176 | * Get the plug-in version |
| 177 | * |
| 178 | */ |
| 179 | int ipauuid_version(void) |
| 180 | { |
| 181 | return IPAUUID_PLUGIN_VERSION0x00010000; |
| 182 | } |
| 183 | |
| 184 | /** |
| 185 | * Plugin identity mgmt |
| 186 | */ |
| 187 | void setPluginID(void *pluginID) |
| 188 | { |
| 189 | _PluginID = pluginID; |
| 190 | } |
| 191 | |
| 192 | void *getPluginID(void) |
| 193 | { |
| 194 | return _PluginID; |
| 195 | } |
| 196 | |
| 197 | void setPluginDN(char *pluginDN) |
| 198 | { |
| 199 | _PluginDN = pluginDN; |
| 200 | } |
| 201 | |
| 202 | char *getPluginDN(void) |
| 203 | { |
| 204 | return _PluginDN; |
| 205 | } |
| 206 | |
| 207 | /* |
| 208 | ipauuid_init |
| 209 | ------------- |
| 210 | adds our callbacks to the list |
| 211 | */ |
| 212 | int |
| 213 | ipauuid_init(Slapi_PBlock *pb) |
| 214 | { |
| 215 | int status = EOK0; |
| 216 | char *plugin_identity = NULL((void*)0); |
| 217 | |
| 218 | LOG_TRACE("--in-->\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "--in-->\n" ); |
| 219 | |
| 220 | /** |
| 221 | * Store the plugin identity for later use. |
| 222 | * Used for internal operations |
| 223 | */ |
| 224 | |
| 225 | slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY13, &plugin_identity); |
| 226 | PR_ASSERT(plugin_identity)((void) 0); |
| 227 | setPluginID(plugin_identity); |
| 228 | |
| 229 | if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION8, |
| 230 | SLAPI_PLUGIN_VERSION_01"01") != 0 || |
| 231 | slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN212, |
| 232 | (void *) ipauuid_start) != 0 || |
| 233 | slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN210, |
| 234 | (void *) ipauuid_close) != 0 || |
| 235 | slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION12, |
| 236 | (void *) &pdesc) != 0 || |
| 237 | slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_MODIFY_FN405, |
| 238 | (void *) ipauuid_mod_pre_op) != 0 || |
| 239 | slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_ADD_FN407, |
| 240 | (void *) ipauuid_add_pre_op) != 0 || |
| 241 | /* internal preoperation */ |
| 242 | slapi_register_plugin("internalpreoperation", /* op type */ |
| 243 | 1, /* Enabled */ |
| 244 | "ipauuid_init", /* this function desc */ |
| 245 | ipauuid_internal_preop_init, /* init func */ |
| 246 | IPAUUID_INT_PREOP_DESC"IPA UUID internal preop plugin", /* plugin desc */ |
| 247 | NULL((void*)0), /* ? */ |
| 248 | plugin_identity /* access control */ |
| 249 | ) || |
| 250 | /* the config change checking post op */ |
| 251 | slapi_register_plugin("postoperation", /* op type */ |
| 252 | 1, /* Enabled */ |
| 253 | "ipauuid_init", /* this function desc */ |
| 254 | ipauuid_postop_init, /* init func for post op */ |
| 255 | IPAUUID_POSTOP_DESC"IPA UUID postop plugin", /* plugin desc */ |
| 256 | NULL((void*)0), /* ? */ |
| 257 | plugin_identity /* access control */ |
| 258 | ) |
| 259 | ) { |
| 260 | LOG_FATAL("failed to register plugin\n")slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "failed to register plugin\n", "ipa_uuid.c", 260); |
| 261 | status = EFAIL-1; |
| 262 | } |
| 263 | |
| 264 | LOG_TRACE("<--out--\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "<--out--\n" ); |
| 265 | return status; |
| 266 | } |
| 267 | |
| 268 | static int |
| 269 | ipauuid_internal_preop_init(Slapi_PBlock *pb) |
| 270 | { |
| 271 | int status = EOK0; |
| 272 | |
| 273 | if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION8, |
| 274 | SLAPI_PLUGIN_VERSION_01"01") != 0 || |
| 275 | slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION12, |
| 276 | (void *) &pdesc) != 0 || |
| 277 | slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_PRE_MODIFY_FN421, |
| 278 | (void *) ipauuid_mod_pre_op) != 0 || |
| 279 | slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_PRE_ADD_FN420, |
| 280 | (void *) ipauuid_add_pre_op) != 0) { |
| 281 | status = EFAIL-1; |
| 282 | } |
| 283 | |
| 284 | return status; |
| 285 | } |
| 286 | |
| 287 | static int |
| 288 | ipauuid_postop_init(Slapi_PBlock *pb) |
| 289 | { |
| 290 | int status = EOK0; |
| 291 | |
| 292 | if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION8, |
| 293 | SLAPI_PLUGIN_VERSION_01"01") != 0 || |
| 294 | slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION12, |
| 295 | (void *) &pdesc) != 0 || |
| 296 | slapi_pblock_set(pb, SLAPI_PLUGIN_POST_ADD_FN507, |
| 297 | (void *) ipauuid_config_check_post_op) != 0 || |
| 298 | slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODRDN_FN506, |
| 299 | (void *) ipauuid_config_check_post_op) != 0 || |
| 300 | slapi_pblock_set(pb, SLAPI_PLUGIN_POST_DELETE_FN508, |
| 301 | (void *) ipauuid_config_check_post_op) != 0 || |
| 302 | slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODIFY_FN505, |
| 303 | (void *) ipauuid_config_check_post_op) != 0) { |
| 304 | LOG_FATAL("failed to register plugin\n")slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "failed to register plugin\n", "ipa_uuid.c", 304); |
| 305 | status = EFAIL-1; |
| 306 | } |
| 307 | |
| 308 | return status; |
| 309 | } |
| 310 | |
| 311 | |
| 312 | /* |
| 313 | ipauuid_start |
| 314 | -------------- |
| 315 | Kicks off the config cache. |
| 316 | It is called after ipauuid_init. |
| 317 | */ |
| 318 | static int |
| 319 | ipauuid_start(Slapi_PBlock * pb) |
| 320 | { |
| 321 | char *plugindn = NULL((void*)0); |
| 322 | |
| 323 | LOG_TRACE("--in-->\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "--in-->\n" ); |
| 324 | |
| 325 | /* Check if we're already started */ |
| 326 | if (g_plugin_started) { |
| 327 | goto done; |
| 328 | } |
| 329 | |
| 330 | if (pthread_rwlock_init(&g_ipauuid_cache_lock, NULL((void*)0)) != 0) { |
| 331 | LOG_FATAL("lock creation failed\n")slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "lock creation failed\n", "ipa_uuid.c", 331); |
| 332 | |
| 333 | return EFAIL-1; |
| 334 | } |
| 335 | |
| 336 | /** |
| 337 | * Get the plug-in target dn from the system |
| 338 | * and store it for future use. This should avoid |
| 339 | * hardcoding of DN's in the code. |
| 340 | */ |
| 341 | slapi_pblock_get(pb, SLAPI_TARGET_DN50, &plugindn); |
| 342 | if (NULL((void*)0) == plugindn || 0 == strlen(plugindn)) { |
| 343 | LOG("had to use hard coded config dn\n")slapi_log_error(14, "ipa-uuid-plugin", "had to use hard coded config dn\n" ); |
| 344 | plugindn = IPAUUID_DN"cn=IPA UUID,cn=plugins,cn=config"; |
| 345 | } else { |
| 346 | LOG("config at %s\n", plugindn)slapi_log_error(14, "ipa-uuid-plugin", "config at %s\n", plugindn ); |
| 347 | |
| 348 | } |
| 349 | |
| 350 | setPluginDN(plugindn); |
| 351 | |
| 352 | /* |
| 353 | * Load the config for our plug-in |
| 354 | */ |
| 355 | ipauuid_global_config = (PRCList *) |
| 356 | slapi_ch_calloc(1, sizeof(struct configEntry)); |
| 357 | PR_INIT_CLIST(ipauuid_global_config)do { (ipauuid_global_config)->next = (ipauuid_global_config ); (ipauuid_global_config)->prev = (ipauuid_global_config) ; } while (0); |
| 358 | |
| 359 | if (ipauuid_load_plugin_config() != EOK0) { |
| 360 | LOG_FATAL("unable to load plug-in configuration\n")slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "unable to load plug-in configuration\n", "ipa_uuid.c", 360); |
| 361 | return EFAIL-1; |
| 362 | } |
| 363 | |
| 364 | g_plugin_started = 1; |
| 365 | LOG("ready for service\n")slapi_log_error(14, "ipa-uuid-plugin", "ready for service\n"); |
| 366 | LOG_TRACE("<--out--\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "<--out--\n" ); |
| 367 | |
| 368 | done: |
| 369 | return EOK0; |
| 370 | } |
| 371 | |
| 372 | /* |
| 373 | ipauuid_close |
| 374 | -------------- |
| 375 | closes down the cache |
| 376 | */ |
| 377 | static int |
| 378 | ipauuid_close(Slapi_PBlock * pb) |
| 379 | { |
| 380 | LOG_TRACE( "--in-->\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "--in-->\n" ); |
| 381 | |
| 382 | ipauuid_delete_config(); |
| 383 | |
| 384 | slapi_ch_free((void **)&ipauuid_global_config); |
| 385 | |
| 386 | LOG_TRACE("<--out--\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "<--out--\n" ); |
| 387 | |
| 388 | return EOK0; |
| 389 | } |
| 390 | |
| 391 | /* |
| 392 | * config looks like this |
| 393 | * - cn=myplugin |
| 394 | * --- cn=posix |
| 395 | * ------ cn=accounts |
| 396 | * ------ cn=groups |
| 397 | * --- cn=samba |
| 398 | * --- cn=etc |
| 399 | * ------ cn=etc etc |
| 400 | */ |
| 401 | static int |
| 402 | ipauuid_load_plugin_config() |
| 403 | { |
| 404 | int status = EOK0; |
| 405 | int result; |
| 406 | int i; |
| 407 | Slapi_PBlock *search_pb; |
| 408 | Slapi_Entry **entries = NULL((void*)0); |
| 409 | |
| 410 | LOG_TRACE("--in-->\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "--in-->\n" ); |
| 411 | |
| 412 | ipauuid_write_lock(); |
| 413 | ipauuid_delete_config(); |
| 414 | |
| 415 | search_pb = slapi_pblock_new(); |
| 416 | |
| 417 | slapi_search_internal_set_pb(search_pb, getPluginDN(), |
| 418 | LDAP_SCOPE_SUBTREE((ber_int_t) 0x0002), "objectclass=*", |
| 419 | NULL((void*)0), 0, NULL((void*)0), NULL((void*)0), getPluginID(), 0); |
| 420 | slapi_search_internal_pb(search_pb); |
| 421 | slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT15, &result); |
| 422 | |
| 423 | if (LDAP_SUCCESS0x00 != result) { |
| 424 | status = EFAIL-1; |
| 425 | goto cleanup; |
| 426 | } |
| 427 | |
| 428 | slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES16, |
| 429 | &entries); |
| 430 | if (NULL((void*)0) == entries || NULL((void*)0) == entries[0]) { |
| 431 | status = EOK0; |
| 432 | goto cleanup; |
| 433 | } |
| 434 | |
| 435 | for (i = 0; (entries[i] != NULL((void*)0)); i++) { |
| 436 | /* We don't care about the status here because we may have |
| 437 | * some invalid config entries, but we just want to continue |
| 438 | * looking for valid ones. */ |
| 439 | ipauuid_parse_config_entry(entries[i], true1); |
| 440 | } |
| 441 | |
| 442 | cleanup: |
| 443 | slapi_free_search_results_internal(search_pb); |
| 444 | slapi_pblock_destroy(search_pb); |
| 445 | ipauuid_unlock(); |
| 446 | LOG_TRACE("<--out--\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "<--out--\n" ); |
| 447 | |
| 448 | return status; |
| 449 | } |
| 450 | |
| 451 | /* |
| 452 | * ipauuid_parse_config_entry() |
| 453 | * |
| 454 | * Parses a single config entry. If apply is non-zero, then |
| 455 | * we will load and start using the new config. You can simply |
| 456 | * validate config without making any changes by setting apply |
| 457 | * to 0. |
| 458 | * |
| 459 | * Returns EOK if the entry is valid and EFAIL |
| 460 | * if it is invalid. |
| 461 | */ |
| 462 | static int |
| 463 | ipauuid_parse_config_entry(Slapi_Entry * e, bool_Bool apply) |
| 464 | { |
| 465 | char *value; |
| 466 | struct configEntry *entry = NULL((void*)0); |
| 467 | struct configEntry *config_entry; |
| 468 | PRCList *list; |
| 469 | int entry_added = 0; |
| 470 | int ret = EOK0; |
| 471 | |
| 472 | LOG_TRACE("--in-->\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "--in-->\n" ); |
| 473 | |
| 474 | /* If this is the main UUID plug-in config entry, just bail. */ |
| 475 | if (strcasecmp(getPluginDN(), slapi_entry_get_ndn(e)) == 0) { |
| 476 | ret = EFAIL-1; |
| 477 | goto bail; |
| 478 | } |
| 479 | |
| 480 | entry = (struct configEntry *) |
| 481 | slapi_ch_calloc(1, sizeof(struct configEntry)); |
| 482 | if (NULL((void*)0) == entry) { |
| 483 | ret = EFAIL-1; |
| 484 | goto bail; |
| 485 | } |
| 486 | |
| 487 | value = slapi_entry_get_ndn(e); |
| 488 | if (value) { |
| 489 | entry->dn = slapi_ch_strdup(value); |
| 490 | } |
| 491 | LOG_CONFIG("----------> dn [%s]\n", entry->dn)slapi_log_error(7, "ipa-uuid-plugin", "----------> dn [%s]\n" , entry->dn); |
| 492 | |
| 493 | entry->attr = slapi_entry_attr_get_charptr(e, IPAUUID_ATTR"ipaUuidAttr"); |
| 494 | if (!entry->attr) { |
| 495 | LOG_FATAL("The %s config setting is required for %s.\n",slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "The %s config setting is required for %s.\n", "ipa_uuid.c", 496, "ipaUuidAttr", entry->dn) |
| 496 | IPAUUID_ATTR, entry->dn)slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "The %s config setting is required for %s.\n", "ipa_uuid.c", 496, "ipaUuidAttr", entry->dn); |
| 497 | ret = EFAIL-1; |
| 498 | goto bail; |
| 499 | } |
| 500 | LOG_CONFIG("----------> %s [%s]\n", IPAUUID_ATTR, entry->attr)slapi_log_error(7, "ipa-uuid-plugin", "----------> %s [%s]\n" , "ipaUuidAttr", entry->attr); |
| 501 | |
| 502 | value = slapi_entry_attr_get_charptr(e, IPAUUID_PREFIX"ipaUuidPrefix"); |
| 503 | if (value && value[0]) { |
| 504 | entry->prefix = value; |
| 505 | } |
| 506 | LOG_CONFIG("----------> %s [%s]\n", IPAUUID_PREFIX, entry->prefix)slapi_log_error(7, "ipa-uuid-plugin", "----------> %s [%s]\n" , "ipaUuidPrefix", entry->prefix); |
| 507 | |
| 508 | value = slapi_entry_attr_get_charptr(e, IPAUUID_GENERATE"ipaUuidMagicRegen"); |
| 509 | if (value) { |
| 510 | entry->generate = value; |
| 511 | } |
| 512 | LOG_CONFIG("----------> %s [%s]\n", IPAUUID_GENERATE, entry->generate)slapi_log_error(7, "ipa-uuid-plugin", "----------> %s [%s]\n" , "ipaUuidMagicRegen", entry->generate); |
| 513 | |
| 514 | value = slapi_entry_attr_get_charptr(e, IPAUUID_FILTER"ipaUuidFilter"); |
| 515 | if (value) { |
| 516 | entry->filter = value; |
| 517 | if (NULL((void*)0) == (entry->slapi_filter = slapi_str2filter(value))) { |
| 518 | LOG_FATAL("Error: Invalid search filter in entry [%s]: [%s]\n",slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "Error: Invalid search filter in entry [%s]: [%s]\n", "ipa_uuid.c" , 519, entry->dn, value) |
| 519 | entry->dn, value)slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "Error: Invalid search filter in entry [%s]: [%s]\n", "ipa_uuid.c" , 519, entry->dn, value); |
| 520 | ret = EFAIL-1; |
| 521 | goto bail; |
| 522 | } |
| 523 | } else { |
| 524 | LOG_FATAL("The %s config setting is required for %s.\n",slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "The %s config setting is required for %s.\n", "ipa_uuid.c", 525, "ipaUuidFilter", entry->dn) |
| 525 | IPAUUID_FILTER, entry->dn)slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "The %s config setting is required for %s.\n", "ipa_uuid.c", 525, "ipaUuidFilter", entry->dn); |
| 526 | ret = EFAIL-1; |
| 527 | goto bail; |
| 528 | } |
| 529 | LOG_CONFIG("----------> %s [%s]\n", IPAUUID_FILTER, value)slapi_log_error(7, "ipa-uuid-plugin", "----------> %s [%s]\n" , "ipaUuidFilter", value); |
| 530 | |
| 531 | value = slapi_entry_attr_get_charptr(e, IPAUUID_SCOPE"ipaUuidScope"); |
| 532 | if (value) { |
| 533 | entry->scope = value; |
| 534 | } else { |
| 535 | LOG_FATAL("The %s config config setting is required for %s.\n",slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "The %s config config setting is required for %s.\n", "ipa_uuid.c" , 536, "ipaUuidScope", entry->dn) |
| 536 | IPAUUID_SCOPE, entry->dn)slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "The %s config config setting is required for %s.\n", "ipa_uuid.c" , 536, "ipaUuidScope", entry->dn); |
| 537 | ret = EFAIL-1; |
| 538 | goto bail; |
| 539 | } |
| 540 | LOG_CONFIG("----------> %s [%s]\n", IPAUUID_SCOPE, entry->scope)slapi_log_error(7, "ipa-uuid-plugin", "----------> %s [%s]\n" , "ipaUuidScope", entry->scope); |
| 541 | |
| 542 | value = slapi_entry_attr_get_charptr(e, IPAUUID_EXCLUDE_SUBTREE"ipaUuidExcludeSubtree"); |
| 543 | entry->exclude_subtree = value; |
| 544 | LOG_CONFIG("----------> %s [%s]\n", IPAUUID_EXCLUDE_SUBTREE, entry->exclude_subtree)slapi_log_error(7, "ipa-uuid-plugin", "----------> %s [%s]\n" , "ipaUuidExcludeSubtree", entry->exclude_subtree); |
| 545 | |
| 546 | entry->enforce = slapi_entry_attr_get_bool(e, IPAUUID_ENFORCE"ipaUuidEnforce"); |
| 547 | LOG_CONFIG("----------> %s [%s]\n",slapi_log_error(7, "ipa-uuid-plugin", "----------> %s [%s]\n" , "ipaUuidEnforce", entry->enforce ? "True" : "False") |
| 548 | IPAUUID_ENFORCE, entry->enforce ? "True" : "False")slapi_log_error(7, "ipa-uuid-plugin", "----------> %s [%s]\n" , "ipaUuidEnforce", entry->enforce ? "True" : "False"); |
| 549 | |
| 550 | /* If we were only called to validate config, we can |
| 551 | * just bail out before applying the config changes */ |
| 552 | if (!apply) { |
| 553 | goto bail; |
| 554 | } |
| 555 | |
| 556 | /** |
| 557 | * Finally add the entry to the list. |
| 558 | * We sort by scope dn length with longer |
| 559 | * dn's first - this allows the scope |
| 560 | * checking code to be simple and quick and |
| 561 | * cunningly linear. |
| 562 | */ |
| 563 | if (!PR_CLIST_IS_EMPTY(ipauuid_global_config)((ipauuid_global_config)->next == (ipauuid_global_config))) { |
| 564 | list = PR_LIST_HEAD(ipauuid_global_config)(ipauuid_global_config)->next; |
| 565 | while (list != ipauuid_global_config) { |
| 566 | config_entry = (struct configEntry *) list; |
| 567 | |
| 568 | if (slapi_dn_issuffix(entry->scope, config_entry->scope)) { |
| 569 | PR_INSERT_BEFORE(&(entry->list), list)do { (&(entry->list))->next = (list); (&(entry-> list))->prev = (list)->prev; (list)->prev->next = (&(entry->list)); (list)->prev = (&(entry-> list)); } while (0); |
| 570 | LOG_CONFIG("store [%s] before [%s] \n",slapi_log_error(7, "ipa-uuid-plugin", "store [%s] before [%s] \n" , entry->scope, config_entry->scope) |
| 571 | entry->scope, config_entry->scope)slapi_log_error(7, "ipa-uuid-plugin", "store [%s] before [%s] \n" , entry->scope, config_entry->scope); |
| 572 | entry_added = 1; |
| 573 | break; |
| 574 | } |
| 575 | |
| 576 | list = PR_NEXT_LINK(list)((list)->next); |
| 577 | |
| 578 | if (ipauuid_global_config == list) { |
| 579 | /* add to tail */ |
| 580 | PR_INSERT_BEFORE(&(entry->list), list)do { (&(entry->list))->next = (list); (&(entry-> list))->prev = (list)->prev; (list)->prev->next = (&(entry->list)); (list)->prev = (&(entry-> list)); } while (0); |
| 581 | LOG_CONFIG("store [%s] at tail\n", entry->scope)slapi_log_error(7, "ipa-uuid-plugin", "store [%s] at tail\n", entry->scope); |
| 582 | entry_added = 1; |
| 583 | break; |
| 584 | } |
| 585 | } |
| 586 | } else { |
| 587 | /* first entry */ |
| 588 | PR_INSERT_LINK(&(entry->list), ipauuid_global_config)do { (&(entry->list))->next = (ipauuid_global_config )->next; (&(entry->list))->prev = (ipauuid_global_config ); (ipauuid_global_config)->next->prev = (&(entry-> list)); (ipauuid_global_config)->next = (&(entry->list )); } while (0); |
| 589 | LOG_CONFIG("store [%s] at head \n", entry->scope)slapi_log_error(7, "ipa-uuid-plugin", "store [%s] at head \n" , entry->scope); |
| 590 | entry_added = 1; |
| 591 | } |
| 592 | |
| 593 | bail: |
| 594 | if (0 == entry_added) { |
| 595 | /* Don't log error if we weren't asked to apply config */ |
| 596 | if (apply && (entry != NULL((void*)0))) { |
| 597 | LOG_FATAL("Invalid config entry [%s] skipped\n", entry->dn)slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "Invalid config entry [%s] skipped\n", "ipa_uuid.c", 597, entry ->dn); |
| 598 | } |
| 599 | ipauuid_free_config_entry(&entry); |
| 600 | } else { |
| 601 | ret = EOK0; |
| 602 | } |
| 603 | |
| 604 | LOG_TRACE("<--out--\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "<--out--\n" ); |
| 605 | |
| 606 | return ret; |
| 607 | } |
| 608 | |
| 609 | static void |
| 610 | ipauuid_free_config_entry(struct configEntry **entry) |
| 611 | { |
| 612 | struct configEntry *e; |
| 613 | |
| 614 | if (!entry || !*entry) { |
| 615 | return; |
| 616 | } |
| 617 | |
| 618 | e = *entry; |
| 619 | |
| 620 | if (e->dn) { |
| 621 | LOG_CONFIG("freeing config entry [%s]\n", e->dn)slapi_log_error(7, "ipa-uuid-plugin", "freeing config entry [%s]\n" , e->dn); |
| 622 | slapi_ch_free_string(&e->dn); |
| 623 | } |
| 624 | |
| 625 | if (e->attr) { |
| 626 | slapi_ch_free_string(&e->attr); |
| 627 | } |
| 628 | |
| 629 | if (e->prefix) { |
| 630 | slapi_ch_free_string(&e->prefix); |
| 631 | } |
| 632 | |
| 633 | if (e->filter) { |
| 634 | slapi_ch_free_string(&e->filter); |
| 635 | } |
| 636 | |
| 637 | if (e->slapi_filter) { |
| 638 | slapi_filter_free(e->slapi_filter, 1); |
| 639 | } |
| 640 | |
| 641 | if (e->generate) { |
| 642 | slapi_ch_free_string(&e->generate); |
| 643 | } |
| 644 | |
| 645 | if (e->scope) { |
| 646 | slapi_ch_free_string(&e->scope); |
| 647 | } |
| 648 | |
| 649 | if (e->exclude_subtree) { |
| 650 | slapi_ch_free_string(&e->exclude_subtree); |
| 651 | } |
| 652 | |
| 653 | slapi_ch_free((void **)entry); |
| 654 | } |
| 655 | |
| 656 | static void |
| 657 | ipauuid_delete_configEntry(PRCList *entry) |
| 658 | { |
| 659 | PR_REMOVE_LINK(entry)do { (entry)->prev->next = (entry)->next; (entry)-> next->prev = (entry)->prev; } while (0); |
| 660 | ipauuid_free_config_entry((struct configEntry **) &entry); |
| 661 | } |
| 662 | |
| 663 | static void |
| 664 | ipauuid_delete_config() |
| 665 | { |
| 666 | PRCList *list; |
| 667 | |
| 668 | while (!PR_CLIST_IS_EMPTY(ipauuid_global_config)((ipauuid_global_config)->next == (ipauuid_global_config))) { |
| 669 | list = PR_LIST_HEAD(ipauuid_global_config)(ipauuid_global_config)->next; |
| 670 | ipauuid_delete_configEntry(list); |
| 671 | } |
| 672 | |
| 673 | return; |
| 674 | } |
| 675 | |
| 676 | /**************************************************** |
| 677 | Helpers |
| 678 | ****************************************************/ |
| 679 | |
| 680 | static char *ipauuid_get_dn(Slapi_PBlock * pb) |
| 681 | { |
| 682 | char *dn = NULL((void*)0); |
| 683 | |
| 684 | LOG_TRACE("--in-->\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "--in-->\n" ); |
| 685 | |
| 686 | if (slapi_pblock_get(pb, SLAPI_TARGET_DN50, &dn)) { |
| 687 | LOG_FATAL("failed to get dn of changed entry")slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "failed to get dn of changed entry", "ipa_uuid.c", 687); |
| 688 | } |
| 689 | |
| 690 | LOG_TRACE("<--out--\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "<--out--\n" ); |
| 691 | |
| 692 | return dn; |
| 693 | } |
| 694 | |
| 695 | /* config check |
| 696 | matching config dn or a descendent reloads config |
| 697 | */ |
| 698 | static int ipauuid_dn_is_config(char *dn) |
| 699 | { |
| 700 | int ret = 0; |
| 701 | |
| 702 | LOG_TRACE("--in-->\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "--in-->\n" ); |
| 703 | |
| 704 | if (slapi_dn_issuffix(dn, getPluginDN())) { |
| 705 | ret = 1; |
| 706 | } |
| 707 | |
| 708 | LOG_TRACE("<--out--\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "<--out--\n" ); |
| 709 | |
| 710 | return ret; |
| 711 | } |
| 712 | |
| 713 | /**************************************************** |
| 714 | Functions that actually do things other |
| 715 | than config and startup |
| 716 | ****************************************************/ |
| 717 | |
| 718 | /* |
| 719 | * ipauuid_list_contains_attr() |
| 720 | * |
| 721 | * Checks if a attr is contained in a list of attrs. |
| 722 | * Returns 1 if the attr is found, 0 otherwise. |
| 723 | */ |
| 724 | static int |
| 725 | ipauuid_list_contains_attr(char **list, char *attr) |
| 726 | { |
| 727 | int ret = 0; |
| 728 | int i = 0; |
| 729 | |
| 730 | if (list && attr) { |
| 731 | for (i = 0; list[i]; i++) { |
| 732 | if (slapi_attr_types_equivalent(attr, list[i])) { |
| 733 | ret = 1; |
| 734 | break; |
| 735 | } |
| 736 | } |
| 737 | } |
| 738 | |
| 739 | return ret; |
| 740 | } |
| 741 | |
| 742 | /* this function must be passed a preallocated buffer of 37 characters in the |
| 743 | * out parameter */ |
| 744 | static void ipauuid_generate_uuid(char *out) |
| 745 | { |
| 746 | uuid_t uu; |
| 747 | |
| 748 | uuid_generate_time(uu); |
| 749 | uuid_unparse_lower(uu, out); |
| 750 | } |
| 751 | |
| 752 | /* for mods and adds: |
| 753 | where dn's are supplied, the closest in scope |
| 754 | is used as long as the type filter matches |
| 755 | and the attr value has not been generated yet. |
| 756 | */ |
| 757 | |
| 758 | static int ipauuid_pre_op(Slapi_PBlock *pb, int modtype) |
| 759 | { |
| 760 | char *dn = NULL((void*)0); |
| 761 | PRCList *list = NULL((void*)0); |
| 762 | struct configEntry *cfgentry = NULL((void*)0); |
| 763 | struct slapi_entry *e = NULL((void*)0); |
| 764 | Slapi_Entry *resulting_e = NULL((void*)0); |
| 765 | char *value = NULL((void*)0); |
| 766 | char **generated_attrs = NULL((void*)0); |
| 767 | Slapi_Mods *smods = NULL((void*)0); |
| 768 | Slapi_Mod *smod = NULL((void*)0); |
| 769 | Slapi_Mod *next_mod; |
| 770 | LDAPMod **mods; |
| 771 | bool_Bool free_entry = false0; |
| 772 | char *errstr = NULL((void*)0); |
| 773 | bool_Bool generate; |
| 774 | int ret = LDAP_SUCCESS0x00; |
| 775 | bool_Bool locked = false0; |
| 776 | bool_Bool set_attr; |
| 777 | int is_repl_op; |
| 778 | int is_config_dn; |
| 779 | |
| 780 | LOG_TRACE("--in-->\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "--in-->\n" ); |
| 781 | |
| 782 | /* Just bail if we aren't ready to service requests yet. */ |
| 783 | if (!g_plugin_started) { |
| 784 | goto done; |
| 785 | } |
| 786 | |
| 787 | dn = ipauuid_get_dn(pb); |
| 788 | if (!dn) { |
| 789 | goto done; |
| 790 | } |
| 791 | |
| 792 | is_config_dn = ipauuid_dn_is_config(dn); |
| 793 | |
| 794 | ret = slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION142, &is_repl_op); |
| 795 | if (ret != 0) { |
| 796 | LOG_FATAL("slapi_pblock_get failed!?\n")slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "slapi_pblock_get failed!?\n", "ipa_uuid.c", 796); |
| 797 | ret = LDAP_OPERATIONS_ERROR0x01; |
| 798 | goto done; |
| 799 | } |
| 800 | |
| 801 | /* pass through if this is a replicated operation */ |
| 802 | if (is_repl_op && !is_config_dn) { |
| 803 | return 0; |
| 804 | } |
| 805 | |
| 806 | if (modtype != LDAP_CHANGETYPE_ADD1 && |
| 807 | modtype != LDAP_CHANGETYPE_MODIFY4) { |
| 808 | goto done; |
| 809 | } |
| 810 | |
| 811 | if (LDAP_CHANGETYPE_ADD1 == modtype) { |
| 812 | slapi_pblock_get(pb, SLAPI_ADD_ENTRY60, &e); |
| 813 | } else { |
| 814 | /* xxxPAR: Ideally SLAPI_MODIFY_EXISTING_ENTRY should be |
| 815 | * available but it turns out that is only true if you are |
| 816 | * a dbm backend pre-op plugin - lucky dbm backend pre-op |
| 817 | * plugins. |
| 818 | * I think that is wrong since the entry is useful for filter |
| 819 | * tests and schema checks and this plugin shouldn't be limited |
| 820 | * to a single backend type, but I don't want that fight right |
| 821 | * now so we go get the entry here |
| 822 | * |
| 823 | slapi_pblock_get( pb, SLAPI_MODIFY_EXISTING_ENTRY, &e); |
| 824 | */ |
| 825 | Slapi_DN *tmp_dn = slapi_sdn_new_dn_byref(dn); |
| 826 | if (tmp_dn) { |
| 827 | ret = slapi_search_internal_get_entry(tmp_dn, NULL((void*)0), &e, getPluginID()); |
| 828 | slapi_sdn_free(&tmp_dn); |
| 829 | |
| 830 | if (ret == LDAP_REFERRAL0x0a) { |
| 831 | /* we have a referral so nothing for us to do, but return |
| 832 | * success so we allow the MOD to proceed. |
| 833 | */ |
| 834 | ret = LDAP_SUCCESS0x00; |
| 835 | free_entry = true1; |
| 836 | goto done; |
| 837 | } |
| 838 | |
| 839 | if (ret) { |
| 840 | /* ok a client tried to modify an entry that doesn't exist. |
| 841 | * Nothing to see here, move along ... */ |
| 842 | goto done; |
| 843 | } |
| 844 | |
| 845 | free_entry = true1; |
| 846 | } |
| 847 | |
| 848 | /* grab the mods - we'll put them back later with |
| 849 | * our modifications appended |
| 850 | */ |
| 851 | slapi_pblock_get(pb, SLAPI_MODIFY_MODS90, &mods); |
| 852 | smods = slapi_mods_new(); |
| 853 | slapi_mods_init_passin(smods, mods); |
| 854 | |
| 855 | /* We need the resulting entry after the mods are applied to |
| 856 | * see if the entry is within the scope. */ |
| 857 | if (e) { |
| 858 | resulting_e = slapi_entry_dup(e); |
| 859 | if (mods && (slapi_entry_apply_mods(resulting_e, mods) != LDAP_SUCCESS0x00)) { |
| 860 | /* The mods don't apply cleanly, so we just let this op go |
| 861 | * to let the main server handle it. */ |
| 862 | goto done; |
| 863 | } |
| 864 | } |
| 865 | } |
| 866 | |
| 867 | if (NULL((void*)0) == e) { |
| 868 | goto done; |
| 869 | } |
| 870 | |
| 871 | if (is_config_dn) { |
| 872 | /* Validate config changes, but don't apply them. |
| 873 | * This allows us to reject invalid config changes |
| 874 | * here at the pre-op stage. Applying the config |
| 875 | * needs to be done at the post-op stage. */ |
| 876 | Slapi_Entry *test_e = NULL((void*)0); |
| 877 | |
| 878 | /* For a MOD, we need to check the resulting entry */ |
| 879 | if (LDAP_CHANGETYPE_ADD1 == modtype) { |
| 880 | test_e = e; |
| 881 | } else { |
| 882 | test_e = resulting_e; |
| 883 | } |
| 884 | |
| 885 | if (ipauuid_parse_config_entry(test_e, false0) != EOK0) { |
| 886 | /* Refuse the operation if config parsing failed. */ |
| 887 | ret = LDAP_UNWILLING_TO_PERFORM0x35; |
| 888 | if (LDAP_CHANGETYPE_ADD1 == modtype) { |
| 889 | errstr = slapi_ch_smprintf("Not a valid IPA UUID " |
| 890 | "configuration entry."); |
| 891 | } else { |
| 892 | errstr = slapi_ch_smprintf("Changes result in an invalid " |
| 893 | "IPA UUID configuration."); |
| 894 | } |
| 895 | } |
| 896 | |
| 897 | /* We're done, so just bail. */ |
| 898 | goto done; |
| 899 | } |
| 900 | |
| 901 | ipauuid_read_lock(); |
| 902 | locked = true1; |
| 903 | |
| 904 | if (PR_CLIST_IS_EMPTY(ipauuid_global_config)((ipauuid_global_config)->next == (ipauuid_global_config))) { |
| 905 | goto done; |
| 906 | } |
| 907 | |
| 908 | list = PR_LIST_HEAD(ipauuid_global_config)(ipauuid_global_config)->next; |
Value stored to 'list' is never read | |
| 909 | |
| 910 | for(list = PR_LIST_HEAD(ipauuid_global_config)(ipauuid_global_config)->next; |
| 911 | list != ipauuid_global_config; |
| 912 | list = PR_NEXT_LINK(list)((list)->next)) { |
| 913 | cfgentry = (struct configEntry *) list; |
| 914 | char *current_dn = NULL((void*)0); |
| 915 | |
| 916 | generate = false0; |
| 917 | set_attr = false0; |
| 918 | |
| 919 | /* Did we already service this attr? */ |
| 920 | if (ipauuid_list_contains_attr(generated_attrs, |
| 921 | cfgentry->attr)) { |
| 922 | continue; |
| 923 | } |
| 924 | /* Current DN may have been reset by |
| 925 | * slapi_pblock_set(pb, SLAPI_ADD_TARGET,..) see below |
| 926 | * need to reread it |
| 927 | */ |
| 928 | current_dn = ipauuid_get_dn(pb); |
| 929 | |
| 930 | /* is the entry in scope? */ |
| 931 | if (cfgentry->scope) { |
| 932 | if (!slapi_dn_issuffix(current_dn, cfgentry->scope)) { |
| 933 | continue; |
| 934 | } |
| 935 | } |
| 936 | |
| 937 | if (cfgentry->exclude_subtree) { |
| 938 | if (slapi_dn_issuffix(current_dn, cfgentry->exclude_subtree)) { |
| 939 | continue; |
| 940 | } |
| 941 | } |
| 942 | |
| 943 | /* does the entry match the filter? */ |
| 944 | if (cfgentry->slapi_filter) { |
| 945 | Slapi_Entry *test_e = NULL((void*)0); |
| 946 | |
| 947 | /* For a MOD operation, we need to check the filter |
| 948 | * against the resulting entry. */ |
| 949 | if (LDAP_CHANGETYPE_ADD1 == modtype) { |
| 950 | test_e = e; |
| 951 | } else { |
| 952 | test_e = resulting_e; |
| 953 | } |
| 954 | |
| 955 | ret = slapi_vattr_filter_test(pb, test_e, |
| 956 | cfgentry->slapi_filter, 0); |
| 957 | if (ret != LDAP_SUCCESS0x00) { |
| 958 | continue; |
| 959 | } |
| 960 | } |
| 961 | |
| 962 | switch(modtype) { |
| 963 | case LDAP_CHANGETYPE_ADD1: |
| 964 | /* Generate the value if the magic value is set or if the |
| 965 | * attr is missing. */ |
| 966 | value = slapi_entry_attr_get_charptr(e, cfgentry->attr); |
| 967 | |
| 968 | if (!value || |
| 969 | !slapi_UTF8CASECMP(cfgentry->generate, value)) { |
| 970 | generate = true1; |
| 971 | } |
| 972 | |
| 973 | slapi_ch_free_string(&value); |
| 974 | |
| 975 | /* always true on add if we match the scope */ |
| 976 | set_attr = true1; |
| 977 | break; |
| 978 | |
| 979 | case LDAP_CHANGETYPE_MODIFY4: |
| 980 | /* check mods for magic value */ |
| 981 | next_mod = slapi_mod_new(); |
| 982 | smod = slapi_mods_get_first_smod(smods, next_mod); |
| 983 | while (smod) { |
| 984 | char *attr = (char *)slapi_mod_get_type(smod); |
| 985 | |
| 986 | /* See if the attr matches the configured attr. */ |
| 987 | if (!slapi_attr_types_equivalent(cfgentry->attr, attr)) { |
| 988 | slapi_mod_done(next_mod); |
| 989 | smod = slapi_mods_get_next_smod(smods, next_mod); |
| 990 | continue; |
| 991 | } |
| 992 | |
| 993 | /* ok we found the attr so that means we are going to set it */ |
| 994 | set_attr = true1; |
| 995 | |
| 996 | /* If all values are being deleted, we need to |
| 997 | * generate a new value. */ |
| 998 | if (SLAPI_IS_MOD_DELETE(slapi_mod_get_operation(smod))(((slapi_mod_get_operation(smod)) & ~(0x0080)) == (0x0001 ))) { |
| 999 | int numvals = slapi_mod_get_num_values(smod); |
| 1000 | |
| 1001 | if (numvals == 0) { |
| 1002 | generate = true1; |
| 1003 | } else { |
| 1004 | Slapi_Attr *sattr = NULL((void*)0); |
| 1005 | int e_numvals = 0; |
| 1006 | |
| 1007 | if ((!slapi_entry_attr_find(e, attr, &sattr)) && |
| 1008 | (NULL((void*)0) != sattr)) { |
| 1009 | slapi_attr_get_numvalues(sattr, &e_numvals); |
| 1010 | if (numvals >= e_numvals) { |
| 1011 | generate = true1; |
| 1012 | } |
| 1013 | } |
| 1014 | } |
| 1015 | } else { |
| 1016 | struct berval *bv; |
| 1017 | |
| 1018 | /* If this attr is already slated for generation, |
| 1019 | * a previous mod in this same modify operation |
| 1020 | * either removed all values or set the magic value. |
| 1021 | * It's possible that this mod is adding a valid value, |
| 1022 | * which means we would not want to generate a new one. |
| 1023 | * It is safe to reset the flag since it will be |
| 1024 | * re-added here if necessary. */ |
| 1025 | generate = false0; |
| 1026 | |
| 1027 | /* This is either adding or replacing a value */ |
| 1028 | bv = slapi_mod_get_first_value(smod); |
| 1029 | /* If we have a value, see if it's the magic value. */ |
| 1030 | if (bv) { |
| 1031 | if (!slapi_UTF8CASECMP(bv->bv_val, |
| 1032 | cfgentry->generate)) { |
| 1033 | generate = true1; |
| 1034 | |
| 1035 | /* also remove this mod, as we will add |
| 1036 | * it again later */ |
| 1037 | slapi_mod_remove_value(next_mod); |
| 1038 | } |
| 1039 | } else { |
| 1040 | /* This is a replace with no new values, so we need |
| 1041 | * to generate a new value */ |
| 1042 | generate = true1; |
| 1043 | } |
| 1044 | } |
| 1045 | |
| 1046 | slapi_mod_done(next_mod); |
| 1047 | smod = slapi_mods_get_next_smod(smods, next_mod); |
| 1048 | } |
| 1049 | |
| 1050 | slapi_mod_free(&next_mod); |
| 1051 | break; |
| 1052 | |
| 1053 | default: |
| 1054 | /* never reached, just silence compiler */ |
| 1055 | LOG_TRACE("File '%s' line %d: Got unexpected value of modtype:"slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "File '%s' line %d: Got unexpected value of modtype:" "%d\n", "ipa_uuid.c", 1056, modtype) |
| 1056 | "%d\n", __FILE__, __LINE__, modtype)slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "File '%s' line %d: Got unexpected value of modtype:" "%d\n", "ipa_uuid.c", 1056, modtype); |
| 1057 | break; |
| 1058 | } |
| 1059 | |
| 1060 | /* We need to perform one last check for modify operations. |
| 1061 | * If an entry within the scope has not triggered generation yet, |
| 1062 | * we need to see if a value exists for the managed attr in the |
| 1063 | * resulting entry. |
| 1064 | * This will catch a modify operation that brings an entry into |
| 1065 | * scope for a managed range, but doesn't supply a value for the |
| 1066 | * managed attr. */ |
| 1067 | if ((LDAP_CHANGETYPE_MODIFY4 == modtype) && !generate) { |
| 1068 | Slapi_Attr *attr = NULL((void*)0); |
| 1069 | if (slapi_entry_attr_find(resulting_e, |
| 1070 | cfgentry->attr, &attr) != 0) { |
| 1071 | generate = true1; |
| 1072 | set_attr = true1; |
| 1073 | } |
| 1074 | } |
| 1075 | |
| 1076 | /* nothing to do keep looping */ |
| 1077 | if (!set_attr) { |
| 1078 | continue; |
| 1079 | } |
| 1080 | |
| 1081 | if (generate) { |
| 1082 | char *new_value; |
| 1083 | |
| 1084 | /* create the value to add */ |
| 1085 | value = slapi_ch_calloc(1, IPAUUID_STR_SIZE36 + 1); |
| 1086 | if (!value) { |
| 1087 | LOG_OOM()slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "Out of Memory!\n", "ipa_uuid.c", 1087); |
| 1088 | ret = LDAP_OPERATIONS_ERROR0x01; |
| 1089 | goto done; |
| 1090 | } |
| 1091 | ipauuid_generate_uuid(value); |
| 1092 | |
| 1093 | if (cfgentry->prefix) { |
| 1094 | new_value = slapi_ch_smprintf("%s%s", |
| 1095 | cfgentry->prefix, value); |
| 1096 | } else { |
| 1097 | new_value = slapi_ch_smprintf("%s", value); |
| 1098 | } |
| 1099 | |
| 1100 | /* do the mod */ |
| 1101 | if (LDAP_CHANGETYPE_ADD1 == modtype) { |
| 1102 | Slapi_DN *sdn; |
| 1103 | Slapi_RDN *rdn; |
| 1104 | char *attr; |
| 1105 | char *nrdn; |
| 1106 | |
| 1107 | /* add - set in entry */ |
| 1108 | slapi_entry_attr_set_charptr(e, cfgentry->attr, new_value); |
| 1109 | |
| 1110 | /* check to see if we need to change the RDN too */ |
| 1111 | rdn = slapi_rdn_new(); |
| 1112 | if (!rdn) { |
| 1113 | LOG_OOM()slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "Out of Memory!\n", "ipa_uuid.c", 1113); |
| 1114 | ret = LDAP_OPERATIONS_ERROR0x01; |
| 1115 | goto done; |
| 1116 | } |
| 1117 | sdn = slapi_sdn_new_dn_byval(current_dn); |
| 1118 | if (!sdn) { |
| 1119 | LOG_OOM()slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "Out of Memory!\n", "ipa_uuid.c", 1119); |
| 1120 | ret = LDAP_OPERATIONS_ERROR0x01; |
| 1121 | slapi_rdn_free(&rdn); |
| 1122 | goto done; |
| 1123 | } |
| 1124 | slapi_rdn_set_sdn(rdn, sdn); |
| 1125 | ret = slapi_rdn_contains_attr(rdn, cfgentry->attr, &attr); |
| 1126 | slapi_rdn_done(rdn); |
| 1127 | if (ret == 1) { |
| 1128 | /* no need to recheck if it is valid, it will be handled |
| 1129 | * later by checking the value in the entry */ |
| 1130 | nrdn = slapi_ch_smprintf("%s=%s", |
| 1131 | cfgentry->attr, new_value); |
| 1132 | if (!nrdn) { |
| 1133 | LOG_OOM()slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "Out of Memory!\n", "ipa_uuid.c", 1133); |
| 1134 | ret = LDAP_OPERATIONS_ERROR0x01; |
| 1135 | slapi_rdn_free(&rdn); |
| 1136 | slapi_sdn_free(&sdn); |
| 1137 | goto done; |
| 1138 | } |
| 1139 | |
| 1140 | slapi_rdn_set_dn(rdn, nrdn); |
| 1141 | slapi_ch_free_string(&nrdn); |
| 1142 | slapi_sdn_set_rdn(sdn, rdn); |
| 1143 | slapi_entry_set_sdn(e, sdn); |
| 1144 | |
| 1145 | /* reset the target DN since we've changed it. */ |
| 1146 | if (slapi_pblock_set(pb, SLAPI_ADD_TARGET50, |
| 1147 | (char*)slapi_sdn_get_ndn(slapi_entry_get_sdn_const(e)))) { |
| 1148 | LOG_FATAL("slapi_block_set failed!\n")slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "slapi_block_set failed!\n", "ipa_uuid.c", 1148); |
| 1149 | ret = LDAP_OPERATIONS_ERROR0x01; |
| 1150 | slapi_rdn_free(&rdn); |
| 1151 | slapi_sdn_free(&sdn); |
| 1152 | goto done; |
| 1153 | } |
| 1154 | } |
| 1155 | slapi_rdn_free(&rdn); |
| 1156 | slapi_sdn_free(&sdn); |
| 1157 | |
| 1158 | } else { |
| 1159 | /* mod - add to mods */ |
| 1160 | slapi_mods_add_string(smods, LDAP_MOD_REPLACE(0x0002), |
| 1161 | cfgentry->attr, new_value); |
| 1162 | } |
| 1163 | |
| 1164 | /* Make sure we don't generate for this |
| 1165 | * attr again by keeping a list of attrs |
| 1166 | * we have generated for already. |
| 1167 | */ |
| 1168 | slapi_ch_array_add(&generated_attrs, |
| 1169 | slapi_ch_strdup(cfgentry->attr)); |
| 1170 | |
| 1171 | /* free up */ |
| 1172 | slapi_ch_free_string(&value); |
| 1173 | slapi_ch_free_string(&new_value); |
| 1174 | |
| 1175 | } else { |
| 1176 | char *bindDN = NULL((void*)0); |
| 1177 | int is_root; |
| 1178 | |
| 1179 | slapi_pblock_get(pb, SLAPI_CONN_DN143, &bindDN); |
| 1180 | is_root = slapi_dn_isroot(bindDN); |
| 1181 | |
| 1182 | /* If not set to the magic value, check enforcement */ |
| 1183 | if (cfgentry->enforce && is_root != 1) { |
| 1184 | /* only Directory Manager can set arbitrary values when |
| 1185 | * enforce is enabled. */ |
| 1186 | errstr = slapi_ch_smprintf("Only the Directory Manager " |
| 1187 | "can set arbitrary values " |
| 1188 | "for %s\n", cfgentry->attr); |
| 1189 | ret = LDAP_INSUFFICIENT_ACCESS0x32; |
| 1190 | goto done; |
| 1191 | } |
| 1192 | } |
| 1193 | } |
| 1194 | |
| 1195 | ret = LDAP_SUCCESS0x00; |
| 1196 | |
| 1197 | done: |
| 1198 | if (locked) { |
| 1199 | ipauuid_unlock(); |
| 1200 | } |
| 1201 | |
| 1202 | if (smods != NULL((void*)0)) { |
| 1203 | /* Put the updated mods back into place. */ |
| 1204 | mods = slapi_mods_get_ldapmods_passout(smods); |
| 1205 | if (slapi_pblock_set(pb, SLAPI_MODIFY_MODS90, mods)) { |
| 1206 | LOG_FATAL("slapi_pblock_set failed!\n")slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "slapi_pblock_set failed!\n", "ipa_uuid.c", 1206); |
| 1207 | ret = LDAP_OPERATIONS_ERROR0x01; |
| 1208 | } |
| 1209 | slapi_mods_free(&smods); |
| 1210 | } |
| 1211 | |
| 1212 | slapi_ch_array_free(generated_attrs); |
| 1213 | slapi_ch_free_string(&value); |
| 1214 | |
| 1215 | if (free_entry && e) { |
| 1216 | slapi_entry_free(e); |
| 1217 | } |
| 1218 | |
| 1219 | if (resulting_e) { |
| 1220 | slapi_entry_free(resulting_e); |
| 1221 | } |
| 1222 | |
| 1223 | if (ret) { |
| 1224 | LOG("operation failure [%d]\n", ret)slapi_log_error(14, "ipa-uuid-plugin", "operation failure [%d]\n" , ret); |
| 1225 | slapi_send_ldap_result(pb, ret, NULL((void*)0), errstr, 0, NULL((void*)0)); |
| 1226 | slapi_ch_free((void **)&errstr); |
| 1227 | ret = EFAIL-1; |
| 1228 | } |
| 1229 | |
| 1230 | LOG_TRACE("<--out--\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "<--out--\n" ); |
| 1231 | |
| 1232 | return ret; |
| 1233 | } |
| 1234 | |
| 1235 | static int ipauuid_add_pre_op(Slapi_PBlock * pb) |
| 1236 | { |
| 1237 | return ipauuid_pre_op(pb, LDAP_CHANGETYPE_ADD1); |
| 1238 | } |
| 1239 | |
| 1240 | static int ipauuid_mod_pre_op(Slapi_PBlock * pb) |
| 1241 | { |
| 1242 | return ipauuid_pre_op(pb, LDAP_CHANGETYPE_MODIFY4); |
| 1243 | } |
| 1244 | |
| 1245 | static int ipauuid_config_check_post_op(Slapi_PBlock * pb) |
| 1246 | { |
| 1247 | char *dn; |
| 1248 | |
| 1249 | LOG_TRACE("--in-->\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "--in-->\n" ); |
| 1250 | |
| 1251 | if ((dn = ipauuid_get_dn(pb))) { |
| 1252 | if (ipauuid_dn_is_config(dn)) |
| 1253 | ipauuid_load_plugin_config(); |
| 1254 | } |
| 1255 | |
| 1256 | LOG_TRACE("<--out--\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "<--out--\n" ); |
| 1257 | |
| 1258 | return 0; |
| 1259 | } |
| 1260 |