| File: | daemons/ipa-slapi-plugins/ipa-modrdn/ipa_modrdn.c |
| Warning: | line 733, column 9 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 MODRDN 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 <pthread.h> |
| 46 | |
| 47 | #include "util.h" |
| 48 | |
| 49 | #define IPA_PLUGIN_NAME"ipa-modrdn-plugin" "ipa-modrdn-plugin" |
| 50 | #define IPAMODRDN_PLUGIN_VERSION0x00010000 0x00010000 |
| 51 | |
| 52 | #define IPAMODRDN_DN"cn=IPA MODRDN,cn=plugins,cn=config" "cn=IPA MODRDN,cn=plugins,cn=config" /* temporary */ |
| 53 | |
| 54 | /** |
| 55 | * IPA MODRDN config types |
| 56 | */ |
| 57 | #define IPAMODRDN_SATTR"ipaModRDNsourceAttr" "ipaModRDNsourceAttr" |
| 58 | #define IPAMODRDN_TATTR"ipaModRDNtargetAttr" "ipaModRDNtargetAttr" |
| 59 | #define IPAMODRDN_PREFIX"ipaModRDNprefix" "ipaModRDNprefix" |
| 60 | #define IPAMODRDN_SUFFIX"ipaModRDNsuffix" "ipaModRDNsuffix" |
| 61 | #define IPAMODRDN_FILTER"ipaModRDNfilter" "ipaModRDNfilter" |
| 62 | #define IPAMODRDN_SCOPE"ipaModRDNscope" "ipaModRDNscope" |
| 63 | |
| 64 | #define IPAMODRDN_FEATURE_DESC"IPA MODRDN" "IPA MODRDN" |
| 65 | #define IPAMODRDN_PLUGIN_DESC"IPA MODRDN plugin" "IPA MODRDN plugin" |
| 66 | #define IPAMODRDN_POSTOP_DESC"IPA MODRDN postop plugin" "IPA MODRDN postop plugin" |
| 67 | |
| 68 | static Slapi_PluginDesc pdesc = { |
| 69 | IPAMODRDN_FEATURE_DESC"IPA MODRDN", |
| 70 | "Red Hat, Inc.", |
| 71 | "1.0", |
| 72 | IPAMODRDN_PLUGIN_DESC"IPA MODRDN plugin" |
| 73 | }; |
| 74 | |
| 75 | /** |
| 76 | * linked list of config entries |
| 77 | */ |
| 78 | |
| 79 | struct configEntry { |
| 80 | PRCList list; |
| 81 | char *dn; |
| 82 | char *sattr; |
| 83 | char *tattr; |
| 84 | char *prefix; |
| 85 | char *suffix; |
| 86 | char *filter; |
| 87 | Slapi_Filter *slapi_filter; |
| 88 | char *scope; |
| 89 | }; |
| 90 | |
| 91 | static PRCList *ipamodrdn_global_config = NULL((void*)0); |
| 92 | static pthread_rwlock_t g_ipamodrdn_cache_lock; |
| 93 | |
| 94 | static void *_PluginID = NULL((void*)0); |
| 95 | static char *_PluginDN = NULL((void*)0); |
| 96 | |
| 97 | static int g_plugin_started = 0; |
| 98 | |
| 99 | |
| 100 | /** |
| 101 | * |
| 102 | * management functions |
| 103 | * |
| 104 | */ |
| 105 | int ipamodrdn_init(Slapi_PBlock * pb); |
| 106 | static int ipamodrdn_start(Slapi_PBlock * pb); |
| 107 | static int ipamodrdn_close(Slapi_PBlock * pb); |
| 108 | |
| 109 | /** |
| 110 | * |
| 111 | * Local operation functions |
| 112 | * |
| 113 | */ |
| 114 | static int ipamodrdn_load_plugin_config(void); |
| 115 | static int ipamodrdn_parse_config_entry(Slapi_Entry * e, bool_Bool apply); |
| 116 | static void ipamodrdn_delete_config(void); |
| 117 | static void ipamodrdn_free_config_entry(struct configEntry ** entry); |
| 118 | |
| 119 | /** |
| 120 | * |
| 121 | * helpers |
| 122 | * |
| 123 | */ |
| 124 | static char *ipamodrdn_get_dn(Slapi_PBlock * pb); |
| 125 | static int ipamodrdn_dn_is_config(char *dn); |
| 126 | |
| 127 | /** |
| 128 | * |
| 129 | * the ops (where the real work is done) |
| 130 | * |
| 131 | */ |
| 132 | static int ipamodrdn_config_check_post_op(Slapi_PBlock * pb); |
| 133 | static int ipamodrdn_post_op(Slapi_PBlock * pb); |
| 134 | |
| 135 | /** |
| 136 | * debug functions - global, for the debugger |
| 137 | */ |
| 138 | void ipamodrdn_dump_config(void); |
| 139 | void ipamodrdn_dump_config_entry(struct configEntry *); |
| 140 | |
| 141 | /** |
| 142 | * |
| 143 | * Deal with cache locking |
| 144 | * |
| 145 | */ |
| 146 | void ipamodrdn_read_lock(void) |
| 147 | { |
| 148 | pthread_rwlock_rdlock(&g_ipamodrdn_cache_lock); |
| 149 | } |
| 150 | |
| 151 | void ipamodrdn_write_lock(void) |
| 152 | { |
| 153 | pthread_rwlock_wrlock(&g_ipamodrdn_cache_lock); |
| 154 | } |
| 155 | |
| 156 | void ipamodrdn_unlock(void) |
| 157 | { |
| 158 | pthread_rwlock_unlock(&g_ipamodrdn_cache_lock); |
| 159 | } |
| 160 | |
| 161 | /** |
| 162 | * |
| 163 | * Get the plug-in version |
| 164 | * |
| 165 | */ |
| 166 | int ipamodrdn_version(void) |
| 167 | { |
| 168 | return IPAMODRDN_PLUGIN_VERSION0x00010000; |
| 169 | } |
| 170 | |
| 171 | /** |
| 172 | * Plugin identity mgmt |
| 173 | */ |
| 174 | void setPluginID(void *pluginID) |
| 175 | { |
| 176 | _PluginID = pluginID; |
| 177 | } |
| 178 | |
| 179 | void *getPluginID(void) |
| 180 | { |
| 181 | return _PluginID; |
| 182 | } |
| 183 | |
| 184 | void setPluginDN(char *pluginDN) |
| 185 | { |
| 186 | _PluginDN = pluginDN; |
| 187 | } |
| 188 | |
| 189 | char *getPluginDN(void) |
| 190 | { |
| 191 | return _PluginDN; |
| 192 | } |
| 193 | |
| 194 | /* |
| 195 | ipamodrdn_init |
| 196 | ------------- |
| 197 | adds our callbacks to the list |
| 198 | */ |
| 199 | int |
| 200 | ipamodrdn_init(Slapi_PBlock *pb) |
| 201 | { |
| 202 | int status = EOK0; |
| 203 | char *plugin_identity = NULL((void*)0); |
| 204 | Slapi_Entry *plugin_entry = NULL((void*)0); |
| 205 | char *plugin_type = NULL((void*)0); |
| 206 | int delfn = SLAPI_PLUGIN_POST_DELETE_FN508; |
| 207 | int mdnfn = SLAPI_PLUGIN_POST_MODRDN_FN506; |
| 208 | int modfn = SLAPI_PLUGIN_POST_MODIFY_FN505; |
| 209 | int addfn = SLAPI_PLUGIN_POST_ADD_FN507; |
| 210 | |
| 211 | LOG_TRACE("--in-->\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "--in-->\n" ); |
| 212 | |
| 213 | /** |
| 214 | * Store the plugin identity for later use. |
| 215 | * Used for internal operations |
| 216 | */ |
| 217 | |
| 218 | slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY13, &plugin_identity); |
| 219 | PR_ASSERT(plugin_identity)((void) 0); |
| 220 | setPluginID(plugin_identity); |
| 221 | |
| 222 | if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY52, &plugin_entry) == 0) && |
| 223 | plugin_entry && |
| 224 | (plugin_type = slapi_entry_attr_get_charptr(plugin_entry, "nsslapd-plugintype")) && |
| 225 | plugin_type && strstr(plugin_type, "betxn")) |
| 226 | { |
| 227 | addfn = SLAPI_PLUGIN_BE_TXN_POST_ADD_FN560; |
| 228 | mdnfn = SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN562; |
| 229 | delfn = SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN563; |
| 230 | modfn = SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN561; |
| 231 | } |
| 232 | slapi_ch_free_string(&plugin_type); |
| 233 | |
| 234 | if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION8, |
| 235 | SLAPI_PLUGIN_VERSION_01"01") != 0 || |
| 236 | slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION12, |
| 237 | (void *) &pdesc) != 0 || |
| 238 | slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN212, |
| 239 | (void *) ipamodrdn_start) != 0 || |
| 240 | slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN210, |
| 241 | (void *) ipamodrdn_close) != 0 || |
| 242 | slapi_pblock_set(pb, addfn, |
| 243 | (void *) ipamodrdn_config_check_post_op) != 0 || |
| 244 | slapi_pblock_set(pb, mdnfn, |
| 245 | (void *) ipamodrdn_post_op) != 0 || |
| 246 | slapi_pblock_set(pb, delfn, |
| 247 | (void *) ipamodrdn_config_check_post_op) != 0 || |
| 248 | slapi_pblock_set(pb, modfn, |
| 249 | (void *) ipamodrdn_config_check_post_op) != 0) { |
| 250 | 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_modrdn.c", 250); |
| 251 | status = EFAIL-1; |
| 252 | } |
| 253 | |
| 254 | LOG_TRACE("<--out--\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "<--out--\n" ); |
| 255 | return status; |
| 256 | } |
| 257 | |
| 258 | |
| 259 | /* |
| 260 | ipamodrdn_start |
| 261 | -------------- |
| 262 | Kicks off the config cache. |
| 263 | It is called after ipamodrdn_init. |
| 264 | */ |
| 265 | static int |
| 266 | ipamodrdn_start(Slapi_PBlock * pb) |
| 267 | { |
| 268 | char *plugindn = NULL((void*)0); |
| 269 | |
| 270 | LOG_TRACE("--in-->\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "--in-->\n" ); |
| 271 | |
| 272 | /* Check if we're already started */ |
| 273 | if (g_plugin_started) { |
| 274 | goto done; |
| 275 | } |
| 276 | |
| 277 | if (pthread_rwlock_init(&g_ipamodrdn_cache_lock, NULL((void*)0)) != 0) { |
| 278 | LOG_FATAL("lock creation failed\n")slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "lock creation failed\n", "ipa_modrdn.c", 278); |
| 279 | |
| 280 | return EFAIL-1; |
| 281 | } |
| 282 | |
| 283 | /** |
| 284 | * Get the plug-in target dn from the system |
| 285 | * and store it for future use. This should avoid |
| 286 | * hardcoding of DN's in the code. |
| 287 | */ |
| 288 | slapi_pblock_get(pb, SLAPI_TARGET_DN50, &plugindn); |
| 289 | if (NULL((void*)0) == plugindn || 0 == strlen(plugindn)) { |
| 290 | LOG("had to use hard coded config dn\n")slapi_log_error(14, "ipa-modrdn-plugin", "had to use hard coded config dn\n" ); |
| 291 | plugindn = IPAMODRDN_DN"cn=IPA MODRDN,cn=plugins,cn=config"; |
| 292 | } else { |
| 293 | LOG("config at %s\n", plugindn)slapi_log_error(14, "ipa-modrdn-plugin", "config at %s\n", plugindn ); |
| 294 | |
| 295 | } |
| 296 | |
| 297 | setPluginDN(plugindn); |
| 298 | |
| 299 | /* |
| 300 | * Load the config for our plug-in |
| 301 | */ |
| 302 | ipamodrdn_global_config = (PRCList *) |
| 303 | slapi_ch_calloc(1, sizeof(struct configEntry)); |
| 304 | PR_INIT_CLIST(ipamodrdn_global_config)do { (ipamodrdn_global_config)->next = (ipamodrdn_global_config ); (ipamodrdn_global_config)->prev = (ipamodrdn_global_config ); } while (0); |
| 305 | |
| 306 | if (ipamodrdn_load_plugin_config() != EOK0) { |
| 307 | 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_modrdn.c", 307 ); |
| 308 | return EFAIL-1; |
| 309 | } |
| 310 | |
| 311 | g_plugin_started = 1; |
| 312 | LOG("ready for service\n")slapi_log_error(14, "ipa-modrdn-plugin", "ready for service\n" ); |
| 313 | LOG_TRACE("<--out--\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "<--out--\n" ); |
| 314 | |
| 315 | done: |
| 316 | return EOK0; |
| 317 | } |
| 318 | |
| 319 | /* |
| 320 | ipamodrdn_close |
| 321 | -------------- |
| 322 | closes down the cache |
| 323 | */ |
| 324 | static int |
| 325 | ipamodrdn_close(Slapi_PBlock * pb) |
| 326 | { |
| 327 | LOG_TRACE( "--in-->\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "--in-->\n" ); |
| 328 | |
| 329 | ipamodrdn_delete_config(); |
| 330 | |
| 331 | slapi_ch_free((void **)&ipamodrdn_global_config); |
| 332 | |
| 333 | LOG_TRACE("<--out--\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "<--out--\n" ); |
| 334 | |
| 335 | return EOK0; |
| 336 | } |
| 337 | |
| 338 | /* |
| 339 | * config looks like this |
| 340 | * - cn=myplugin |
| 341 | * --- cn=posix |
| 342 | * ------ cn=accounts |
| 343 | * ------ cn=groups |
| 344 | * --- cn=samba |
| 345 | * --- cn=etc |
| 346 | * ------ cn=etc etc |
| 347 | */ |
| 348 | static int |
| 349 | ipamodrdn_load_plugin_config(void) |
| 350 | { |
| 351 | int status = EOK0; |
| 352 | int result; |
| 353 | int i; |
| 354 | Slapi_PBlock *search_pb; |
| 355 | Slapi_Entry **entries = NULL((void*)0); |
| 356 | |
| 357 | LOG_TRACE("--in-->\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "--in-->\n" ); |
| 358 | |
| 359 | ipamodrdn_write_lock(); |
| 360 | ipamodrdn_delete_config(); |
| 361 | |
| 362 | search_pb = slapi_pblock_new(); |
| 363 | |
| 364 | slapi_search_internal_set_pb(search_pb, getPluginDN(), |
| 365 | LDAP_SCOPE_SUBTREE((ber_int_t) 0x0002), "objectclass=*", |
| 366 | NULL((void*)0), 0, NULL((void*)0), NULL((void*)0), getPluginID(), 0); |
| 367 | slapi_search_internal_pb(search_pb); |
| 368 | slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT15, &result); |
| 369 | |
| 370 | if (LDAP_SUCCESS0x00 != result) { |
| 371 | status = EFAIL-1; |
| 372 | goto cleanup; |
| 373 | } |
| 374 | |
| 375 | slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES16, |
| 376 | &entries); |
| 377 | if (NULL((void*)0) == entries || NULL((void*)0) == entries[0]) { |
| 378 | status = EOK0; |
| 379 | goto cleanup; |
| 380 | } |
| 381 | |
| 382 | for (i = 0; (entries[i] != NULL((void*)0)); i++) { |
| 383 | /* We don't care about the status here because we may have |
| 384 | * some invalid config entries, but we just want to continue |
| 385 | * looking for valid ones. */ |
| 386 | ipamodrdn_parse_config_entry(entries[i], true1); |
| 387 | } |
| 388 | |
| 389 | cleanup: |
| 390 | slapi_free_search_results_internal(search_pb); |
| 391 | slapi_pblock_destroy(search_pb); |
| 392 | ipamodrdn_unlock(); |
| 393 | LOG_TRACE("<--out--\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "<--out--\n" ); |
| 394 | |
| 395 | return status; |
| 396 | } |
| 397 | |
| 398 | /* |
| 399 | * ipamodrdn_parse_config_entry() |
| 400 | * |
| 401 | * Parses a single config entry. If apply is non-zero, then |
| 402 | * we will load and start using the new config. You can simply |
| 403 | * validate config without making any changes by setting apply |
| 404 | * to 0. |
| 405 | * |
| 406 | * Returns EOK if the entry is valid and EFAIL |
| 407 | * if it is invalid. |
| 408 | */ |
| 409 | static int |
| 410 | ipamodrdn_parse_config_entry(Slapi_Entry * e, bool_Bool apply) |
| 411 | { |
| 412 | char *value; |
| 413 | struct configEntry *entry = NULL((void*)0); |
| 414 | struct configEntry *config_entry; |
| 415 | PRCList *list; |
| 416 | int entry_added = 0; |
| 417 | int ret = EOK0; |
| 418 | |
| 419 | LOG_TRACE("--in-->\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "--in-->\n" ); |
| 420 | |
| 421 | /* If this is the main MODRDN plug-in config entry, just bail. */ |
| 422 | if (strcasecmp(getPluginDN(), slapi_entry_get_ndn(e)) == 0) { |
| 423 | ret = EFAIL-1; |
| 424 | goto bail; |
| 425 | } |
| 426 | |
| 427 | entry = (struct configEntry *) |
| 428 | slapi_ch_calloc(1, sizeof(struct configEntry)); |
| 429 | if (NULL((void*)0) == entry) { |
| 430 | ret = EFAIL-1; |
| 431 | goto bail; |
| 432 | } |
| 433 | |
| 434 | value = slapi_entry_get_ndn(e); |
| 435 | if (value) { |
| 436 | entry->dn = slapi_ch_strdup(value); |
| 437 | } |
| 438 | |
| 439 | LOG_CONFIG("----------> dn [%s]\n", entry->dn)slapi_log_error(7, "ipa-modrdn-plugin", "----------> dn [%s]\n" , entry->dn); |
| 440 | |
| 441 | entry->sattr = slapi_entry_attr_get_charptr(e, IPAMODRDN_SATTR"ipaModRDNsourceAttr"); |
| 442 | if (!entry->sattr) { |
| 443 | 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_modrdn.c" , 444, "ipaModRDNsourceAttr", entry->dn) |
| 444 | IPAMODRDN_SATTR, entry->dn)slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "The %s config setting is required for %s.\n", "ipa_modrdn.c" , 444, "ipaModRDNsourceAttr", entry->dn); |
| 445 | ret = EFAIL-1; |
| 446 | goto bail; |
| 447 | } |
| 448 | LOG_CONFIG("----------> %s [%s]\n", IPAMODRDN_SATTR, entry->sattr)slapi_log_error(7, "ipa-modrdn-plugin", "----------> %s [%s]\n" , "ipaModRDNsourceAttr", entry->sattr); |
| 449 | |
| 450 | entry->tattr = slapi_entry_attr_get_charptr(e, IPAMODRDN_TATTR"ipaModRDNtargetAttr"); |
| 451 | if (!entry->tattr) { |
| 452 | 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_modrdn.c" , 453, "ipaModRDNtargetAttr", entry->dn) |
| 453 | IPAMODRDN_TATTR, entry->dn)slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "The %s config setting is required for %s.\n", "ipa_modrdn.c" , 453, "ipaModRDNtargetAttr", entry->dn); |
| 454 | ret = EFAIL-1; |
| 455 | goto bail; |
| 456 | } |
| 457 | LOG_CONFIG("----------> %s [%s]\n", IPAMODRDN_TATTR, entry->tattr)slapi_log_error(7, "ipa-modrdn-plugin", "----------> %s [%s]\n" , "ipaModRDNtargetAttr", entry->tattr); |
| 458 | |
| 459 | value = slapi_entry_attr_get_charptr(e, IPAMODRDN_PREFIX"ipaModRDNprefix"); |
| 460 | if (value && value[0]) { |
| 461 | entry->prefix = value; |
| 462 | } else { |
| 463 | entry->prefix = slapi_ch_strdup(""); |
| 464 | } |
| 465 | LOG_CONFIG("----------> %s [%s]\n", IPAMODRDN_PREFIX, entry->prefix)slapi_log_error(7, "ipa-modrdn-plugin", "----------> %s [%s]\n" , "ipaModRDNprefix", entry->prefix); |
| 466 | |
| 467 | value = slapi_entry_attr_get_charptr(e, IPAMODRDN_SUFFIX"ipaModRDNsuffix"); |
| 468 | if (value && value[0]) { |
| 469 | entry->suffix = value; |
| 470 | } else { |
| 471 | entry->suffix = slapi_ch_strdup(""); |
| 472 | } |
| 473 | LOG_CONFIG("----------> %s [%s]\n", IPAMODRDN_SUFFIX, entry->suffix)slapi_log_error(7, "ipa-modrdn-plugin", "----------> %s [%s]\n" , "ipaModRDNsuffix", entry->suffix); |
| 474 | |
| 475 | value = slapi_entry_attr_get_charptr(e, IPAMODRDN_FILTER"ipaModRDNfilter"); |
| 476 | if (value) { |
| 477 | entry->filter = value; |
| 478 | if (NULL((void*)0) == (entry->slapi_filter = slapi_str2filter(value))) { |
| 479 | 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_modrdn.c" , 480, entry->dn, value) |
| 480 | 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_modrdn.c" , 480, entry->dn, value); |
| 481 | ret = EFAIL-1; |
| 482 | goto bail; |
| 483 | } |
| 484 | } else { |
| 485 | 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_modrdn.c" , 486, "ipaModRDNfilter", entry->dn) |
| 486 | IPAMODRDN_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_modrdn.c" , 486, "ipaModRDNfilter", entry->dn); |
| 487 | ret = EFAIL-1; |
| 488 | goto bail; |
| 489 | } |
| 490 | LOG_CONFIG("----------> %s [%s]\n", IPAMODRDN_FILTER, value)slapi_log_error(7, "ipa-modrdn-plugin", "----------> %s [%s]\n" , "ipaModRDNfilter", value); |
| 491 | |
| 492 | value = slapi_entry_attr_get_charptr(e, IPAMODRDN_SCOPE"ipaModRDNscope"); |
| 493 | if (value) { |
| 494 | entry->scope = value; |
| 495 | } else { |
| 496 | 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_modrdn.c" , 497, "ipaModRDNscope", entry->dn) |
| 497 | IPAMODRDN_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_modrdn.c" , 497, "ipaModRDNscope", entry->dn); |
| 498 | ret = EFAIL-1; |
| 499 | goto bail; |
| 500 | } |
| 501 | LOG_CONFIG("----------> %s [%s]\n", IPAMODRDN_SCOPE, entry->scope)slapi_log_error(7, "ipa-modrdn-plugin", "----------> %s [%s]\n" , "ipaModRDNscope", entry->scope); |
| 502 | |
| 503 | /* If we were only called to validate config, we can |
| 504 | * just bail out before applying the config changes */ |
| 505 | if (!apply) { |
| 506 | goto bail; |
| 507 | } |
| 508 | |
| 509 | /** |
| 510 | * Finally add the entry to the list. |
| 511 | * We sort by scope dn length with longer |
| 512 | * dn's first - this allows the scope |
| 513 | * checking code to be simple and quick and |
| 514 | * cunningly linear. |
| 515 | */ |
| 516 | if (!PR_CLIST_IS_EMPTY(ipamodrdn_global_config)((ipamodrdn_global_config)->next == (ipamodrdn_global_config ))) { |
| 517 | list = PR_LIST_HEAD(ipamodrdn_global_config)(ipamodrdn_global_config)->next; |
| 518 | while (list != ipamodrdn_global_config) { |
| 519 | config_entry = (struct configEntry *) list; |
| 520 | |
| 521 | if (slapi_dn_issuffix(entry->scope, config_entry->scope)) { |
| 522 | 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); |
| 523 | LOG_CONFIG("store [%s] before [%s] \n",slapi_log_error(7, "ipa-modrdn-plugin", "store [%s] before [%s] \n" , entry->scope, config_entry->scope) |
| 524 | entry->scope, config_entry->scope)slapi_log_error(7, "ipa-modrdn-plugin", "store [%s] before [%s] \n" , entry->scope, config_entry->scope); |
| 525 | entry_added = 1; |
| 526 | break; |
| 527 | } |
| 528 | |
| 529 | list = PR_NEXT_LINK(list)((list)->next); |
| 530 | |
| 531 | if (ipamodrdn_global_config == list) { |
| 532 | /* add to tail */ |
| 533 | 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); |
| 534 | LOG_CONFIG("store [%s] at tail\n", entry->scope)slapi_log_error(7, "ipa-modrdn-plugin", "store [%s] at tail\n" , entry->scope); |
| 535 | entry_added = 1; |
| 536 | break; |
| 537 | } |
| 538 | } |
| 539 | } else { |
| 540 | /* first entry */ |
| 541 | PR_INSERT_LINK(&(entry->list), ipamodrdn_global_config)do { (&(entry->list))->next = (ipamodrdn_global_config )->next; (&(entry->list))->prev = (ipamodrdn_global_config ); (ipamodrdn_global_config)->next->prev = (&(entry ->list)); (ipamodrdn_global_config)->next = (&(entry ->list)); } while (0); |
| 542 | LOG_CONFIG("store [%s] at head \n", entry->scope)slapi_log_error(7, "ipa-modrdn-plugin", "store [%s] at head \n" , entry->scope); |
| 543 | entry_added = 1; |
| 544 | } |
| 545 | |
| 546 | bail: |
| 547 | if (0 == entry_added) { |
| 548 | /* Don't log error if we weren't asked to apply config */ |
| 549 | if (apply && (entry != NULL((void*)0))) { |
| 550 | 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_modrdn.c", 550, entry ->dn); |
| 551 | } |
| 552 | ipamodrdn_free_config_entry(&entry); |
| 553 | } else { |
| 554 | ret = EOK0; |
| 555 | } |
| 556 | |
| 557 | LOG_TRACE("<--out--\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "<--out--\n" ); |
| 558 | |
| 559 | return ret; |
| 560 | } |
| 561 | |
| 562 | static void |
| 563 | ipamodrdn_free_config_entry(struct configEntry **entry) |
| 564 | { |
| 565 | struct configEntry *e; |
| 566 | |
| 567 | if (!entry || !*entry) { |
| 568 | return; |
| 569 | } |
| 570 | |
| 571 | e = *entry; |
| 572 | |
| 573 | if (e->dn) { |
| 574 | LOG_CONFIG("freeing config entry [%s]\n", e->dn)slapi_log_error(7, "ipa-modrdn-plugin", "freeing config entry [%s]\n" , e->dn); |
| 575 | } |
| 576 | slapi_ch_free_string(&e->dn); |
| 577 | slapi_ch_free_string(&e->sattr); |
| 578 | slapi_ch_free_string(&e->tattr); |
| 579 | slapi_ch_free_string(&e->prefix); |
| 580 | slapi_ch_free_string(&e->suffix); |
| 581 | slapi_ch_free_string(&e->filter); |
| 582 | slapi_filter_free(e->slapi_filter, 1); |
| 583 | slapi_ch_free_string(&e->scope); |
| 584 | slapi_ch_free((void **)entry); |
| 585 | } |
| 586 | |
| 587 | static void |
| 588 | ipamodrdn_delete_configEntry(PRCList *entry) |
| 589 | { |
| 590 | PR_REMOVE_LINK(entry)do { (entry)->prev->next = (entry)->next; (entry)-> next->prev = (entry)->prev; } while (0); |
| 591 | ipamodrdn_free_config_entry((struct configEntry **) &entry); |
| 592 | } |
| 593 | |
| 594 | static void |
| 595 | ipamodrdn_delete_config(void) |
| 596 | { |
| 597 | PRCList *list; |
| 598 | |
| 599 | while (!PR_CLIST_IS_EMPTY(ipamodrdn_global_config)((ipamodrdn_global_config)->next == (ipamodrdn_global_config ))) { |
| 600 | list = PR_LIST_HEAD(ipamodrdn_global_config)(ipamodrdn_global_config)->next; |
| 601 | ipamodrdn_delete_configEntry(list); |
| 602 | } |
| 603 | |
| 604 | return; |
| 605 | } |
| 606 | |
| 607 | /**************************************************** |
| 608 | Helpers |
| 609 | ****************************************************/ |
| 610 | |
| 611 | static char *ipamodrdn_get_dn(Slapi_PBlock * pb) |
| 612 | { |
| 613 | char *dn = NULL((void*)0); |
| 614 | |
| 615 | LOG_TRACE("--in-->\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "--in-->\n" ); |
| 616 | |
| 617 | if (slapi_pblock_get(pb, SLAPI_TARGET_DN50, &dn)) { |
| 618 | 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_modrdn.c", 618); |
| 619 | } |
| 620 | |
| 621 | LOG_TRACE("<--out--\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "<--out--\n" ); |
| 622 | |
| 623 | return dn; |
| 624 | } |
| 625 | |
| 626 | /* config check |
| 627 | matching config dn or a descendent reloads config |
| 628 | */ |
| 629 | static int ipamodrdn_dn_is_config(char *dn) |
| 630 | { |
| 631 | int ret = 0; |
| 632 | |
| 633 | LOG_TRACE("--in-->\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "--in-->\n" ); |
| 634 | |
| 635 | if (slapi_dn_issuffix(dn, getPluginDN())) { |
| 636 | ret = 1; |
| 637 | } |
| 638 | |
| 639 | LOG_TRACE("<--out--\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "<--out--\n" ); |
| 640 | |
| 641 | return ret; |
| 642 | } |
| 643 | |
| 644 | /**************************************************** |
| 645 | Functions that actually do things other |
| 646 | than config and startup |
| 647 | ****************************************************/ |
| 648 | |
| 649 | static int |
| 650 | ipamodrdn_change_attr(struct configEntry *cfgentry, |
| 651 | char *targetdn, const char *value) |
| 652 | { |
| 653 | Slapi_PBlock *mod_pb = slapi_pblock_new(); |
| 654 | LDAPMod mod; |
| 655 | LDAPMod *mods[2]; |
| 656 | char *val[2] = { NULL((void*)0) }; |
| 657 | int ret; |
| 658 | |
| 659 | val[0] = slapi_ch_smprintf("%s%s%s", |
| 660 | cfgentry->prefix, value, cfgentry->suffix); |
| 661 | if (!val[0]) { |
| 662 | LOG_OOM()slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "Out of Memory!\n", "ipa_modrdn.c", 662); |
| 663 | ret = EFAIL-1; |
| 664 | goto done; |
| 665 | } |
| 666 | val[1] = 0; |
| 667 | |
| 668 | mod.mod_op = LDAP_MOD_REPLACE(0x0002); |
| 669 | mod.mod_type = cfgentry->tattr; |
| 670 | mod.mod_valuesmod_vals.modv_strvals = val; |
| 671 | |
| 672 | mods[0] = &mod; |
| 673 | mods[1] = 0; |
| 674 | |
| 675 | LOG("Setting %s to %s in entry (%s)\n", cfgentry->tattr, value, targetdn)slapi_log_error(14, "ipa-modrdn-plugin", "Setting %s to %s in entry (%s)\n" , cfgentry->tattr, value, targetdn); |
| 676 | |
| 677 | /* Perform the modify operation. */ |
| 678 | slapi_modify_internal_set_pb(mod_pb, targetdn, mods, |
| 679 | 0, 0, getPluginID(), 0); |
| 680 | slapi_modify_internal_pb(mod_pb); |
| 681 | slapi_pblock_get(mod_pb, SLAPI_PLUGIN_INTOP_RESULT15, &ret); |
| 682 | if (ret != LDAP_SUCCESS0x00) { |
| 683 | LOG_FATAL("Failed to change attribute with error %d\n", ret)slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "Failed to change attribute with error %d\n", "ipa_modrdn.c" , 683, ret); |
| 684 | ret = EFAIL-1; |
| 685 | } |
| 686 | ret = EOK0; |
| 687 | |
| 688 | done: |
| 689 | if (val[0]) slapi_ch_free_string(&(val[0])); |
| 690 | slapi_pblock_destroy(mod_pb); |
| 691 | return ret; |
| 692 | } |
| 693 | |
| 694 | |
| 695 | |
| 696 | |
| 697 | /* for mods and adds: |
| 698 | where dn's are supplied, the closest in scope |
| 699 | is used as long as the type filter matches |
| 700 | and the attr value has not been generated yet. |
| 701 | */ |
| 702 | |
| 703 | static int ipamodrdn_post_op(Slapi_PBlock *pb) |
| 704 | { |
| 705 | char *dn = NULL((void*)0); |
| 706 | PRCList *list = NULL((void*)0); |
| 707 | struct configEntry *cfgentry = NULL((void*)0); |
| 708 | struct slapi_entry *e = NULL((void*)0); |
| 709 | Slapi_Attr *sattr = NULL((void*)0); |
| 710 | Slapi_Attr *tattr = NULL((void*)0); |
| 711 | int ret = LDAP_SUCCESS0x00; |
| 712 | |
| 713 | LOG_TRACE("--in-->\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "--in-->\n" ); |
| 714 | |
| 715 | /* Just bail if we aren't ready to service requests yet. */ |
| 716 | if (!g_plugin_started) { |
| 717 | goto done; |
| 718 | } |
| 719 | |
| 720 | slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP53, &e); |
| 721 | if (NULL((void*)0) == e) { |
| 722 | goto done; |
| 723 | } |
| 724 | |
| 725 | dn = slapi_entry_get_ndn(e); |
| 726 | if (NULL((void*)0) == dn) { |
| 727 | goto done; |
| 728 | } |
| 729 | |
| 730 | ipamodrdn_read_lock(); |
| 731 | |
| 732 | if (!PR_CLIST_IS_EMPTY(ipamodrdn_global_config)((ipamodrdn_global_config)->next == (ipamodrdn_global_config ))) { |
| 733 | list = PR_LIST_HEAD(ipamodrdn_global_config)(ipamodrdn_global_config)->next; |
Value stored to 'list' is never read | |
| 734 | |
| 735 | for(list = PR_LIST_HEAD(ipamodrdn_global_config)(ipamodrdn_global_config)->next; |
| 736 | list != ipamodrdn_global_config; |
| 737 | list = PR_NEXT_LINK(list)((list)->next)) { |
| 738 | cfgentry = (struct configEntry *) list; |
| 739 | |
| 740 | /* is the entry in scope? */ |
| 741 | if (cfgentry->scope) { |
| 742 | if (!slapi_dn_issuffix(dn, cfgentry->scope)) { |
| 743 | continue; |
| 744 | } |
| 745 | } |
| 746 | |
| 747 | /* does the entry match the filter? */ |
| 748 | if (cfgentry->slapi_filter) { |
| 749 | ret = slapi_vattr_filter_test(pb, e, |
| 750 | cfgentry->slapi_filter, 0); |
| 751 | if (ret != LDAP_SUCCESS0x00) { |
| 752 | continue; |
| 753 | } |
| 754 | } |
| 755 | |
| 756 | if (slapi_entry_attr_find(e, cfgentry->sattr, &sattr) != 0) { |
| 757 | LOG_TRACE("Source attr %s not found for %s\n",slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "Source attr %s not found for %s\n" , cfgentry->sattr, dn) |
| 758 | cfgentry->sattr, dn)slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "Source attr %s not found for %s\n" , cfgentry->sattr, dn); |
| 759 | continue; |
| 760 | } |
| 761 | if (slapi_entry_attr_find(e, cfgentry->tattr, &tattr) != 0) { |
| 762 | LOG_TRACE("Target attr %s not found for %s\n",slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "Target attr %s not found for %s\n" , cfgentry->tattr, dn) |
| 763 | cfgentry->tattr, dn)slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "Target attr %s not found for %s\n" , cfgentry->tattr, dn); |
| 764 | } else { |
| 765 | Slapi_Value *val; |
| 766 | const char *strval; |
| 767 | |
| 768 | ret = slapi_attr_first_value(sattr, &val); |
| 769 | if (ret == -1 || !val) { |
| 770 | LOG_FATAL("Source attr %s is empty\n", cfgentry->sattr)slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "Source attr %s is empty\n", "ipa_modrdn.c", 770, cfgentry-> sattr); |
| 771 | continue; |
| 772 | } |
| 773 | strval = slapi_value_get_string(val); |
| 774 | |
| 775 | ret = ipamodrdn_change_attr(cfgentry, dn, strval); |
| 776 | if (ret != EOK0) { |
| 777 | LOG_FATAL("Failed to set target attr %s for %s\n",slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "Failed to set target attr %s for %s\n", "ipa_modrdn.c", 778 , cfgentry->tattr, dn) |
| 778 | cfgentry->tattr, dn)slapi_log_error(0, ((void *)((uintptr_t)(__func__))), "[file %s, line %d]: " "Failed to set target attr %s for %s\n", "ipa_modrdn.c", 778 , cfgentry->tattr, dn); |
| 779 | } |
| 780 | } |
| 781 | } |
| 782 | } |
| 783 | |
| 784 | ipamodrdn_unlock(); |
| 785 | |
| 786 | ret = LDAP_SUCCESS0x00; |
| 787 | |
| 788 | done: |
| 789 | if (ret) { |
| 790 | LOG("operation failure [%d]\n", ret)slapi_log_error(14, "ipa-modrdn-plugin", "operation failure [%d]\n" , ret); |
| 791 | ret = EFAIL-1; |
| 792 | } |
| 793 | |
| 794 | LOG_TRACE("<--out--\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "<--out--\n" ); |
| 795 | |
| 796 | return ret; |
| 797 | } |
| 798 | |
| 799 | static int ipamodrdn_config_check_post_op(Slapi_PBlock * pb) |
| 800 | { |
| 801 | char *dn; |
| 802 | |
| 803 | LOG_TRACE("--in-->\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "--in-->\n" ); |
| 804 | |
| 805 | if ((dn = ipamodrdn_get_dn(pb))) { |
| 806 | if (ipamodrdn_dn_is_config(dn)) { |
| 807 | ipamodrdn_load_plugin_config(); |
| 808 | } |
| 809 | } |
| 810 | |
| 811 | LOG_TRACE("<--out--\n")slapi_log_error(1, ((void *)((uintptr_t)(__func__))), "<--out--\n" ); |
| 812 | |
| 813 | return 0; |
| 814 | } |