1 /* $NetBSD: rewrite-int.h,v 1.2 2020/08/11 13:15:39 christos Exp $ */ 2 3 /* $OpenLDAP$ */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 2000-2020 The OpenLDAP Foundation. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted only as authorized by the OpenLDAP 11 * Public License. 12 * 13 * A copy of this license is available in the file LICENSE in the 14 * top-level directory of the distribution or, alternatively, at 15 * <http://www.OpenLDAP.org/license.html>. 16 */ 17 /* ACKNOWLEDGEMENT: 18 * This work was initially developed by Pierangelo Masarati for 19 * inclusion in OpenLDAP Software. 20 */ 21 22 #ifndef REWRITE_INT_H 23 #define REWRITE_INT_H 24 25 /* 26 * These are required by every file of the library, so they're included here 27 */ 28 #include <ac/stdlib.h> 29 #include <ac/string.h> 30 #include <ac/syslog.h> 31 #include <ac/regex.h> 32 #include <ac/socket.h> 33 #include <ac/unistd.h> 34 #include <ac/ctype.h> 35 36 #include <lber.h> 37 #include <ldap.h> 38 #define LDAP_DEFINE_LDAP_DEBUG 39 #include <ldap_log.h> 40 #include <lutil.h> 41 #include <avl.h> 42 43 #include <rewrite.h> 44 45 #define malloc(x) ber_memalloc(x) 46 #define calloc(x,y) ber_memcalloc(x,y) 47 #define realloc(x,y) ber_memrealloc(x,y) 48 #define free(x) ber_memfree(x) 49 #undef strdup 50 #define strdup(x) ber_strdup(x) 51 52 /* Uncomment to use ldap pvt threads */ 53 #define USE_REWRITE_LDAP_PVT_THREADS 54 #include <ldap_pvt_thread.h> 55 56 /* 57 * For details, see RATIONALE. 58 */ 59 60 #define REWRITE_MAX_MATCH 11 /* 0: overall string; 1-9: submatches */ 61 #define REWRITE_MAX_PASSES 100 62 63 /* 64 * Submatch escape char 65 */ 66 /* the '\' conflicts with slapd.conf parsing */ 67 /* #define REWRITE_SUBMATCH_ESCAPE '\\' */ 68 #define REWRITE_SUBMATCH_ESCAPE_ORIG '%' 69 #define REWRITE_SUBMATCH_ESCAPE '$' 70 #define IS_REWRITE_SUBMATCH_ESCAPE(c) \ 71 ((c) == REWRITE_SUBMATCH_ESCAPE || (c) == REWRITE_SUBMATCH_ESCAPE_ORIG) 72 73 /* 74 * REGEX flags 75 */ 76 77 #define REWRITE_FLAG_HONORCASE 'C' 78 #define REWRITE_FLAG_BASICREGEX 'R' 79 80 /* 81 * Action flags 82 */ 83 #define REWRITE_FLAG_EXECONCE ':' 84 #define REWRITE_FLAG_STOP '@' 85 #define REWRITE_FLAG_UNWILLING '#' 86 #define REWRITE_FLAG_GOTO 'G' /* requires an arg */ 87 #define REWRITE_FLAG_USER 'U' /* requires an arg */ 88 #define REWRITE_FLAG_MAX_PASSES 'M' /* requires an arg */ 89 #define REWRITE_FLAG_IGNORE_ERR 'I' 90 91 /* 92 * Map operators 93 */ 94 #define REWRITE_OPERATOR_SUBCONTEXT '>' 95 #define REWRITE_OPERATOR_COMMAND '|' 96 #define REWRITE_OPERATOR_VARIABLE_SET '&' 97 #define REWRITE_OPERATOR_VARIABLE_GET '*' 98 #define REWRITE_OPERATOR_PARAM_GET '$' 99 100 101 /*********** 102 * PRIVATE * 103 ***********/ 104 105 /* 106 * Action 107 */ 108 struct rewrite_action { 109 struct rewrite_action *la_next; 110 111 #define REWRITE_ACTION_STOP 0x0001 112 #define REWRITE_ACTION_UNWILLING 0x0002 113 #define REWRITE_ACTION_GOTO 0x0003 114 #define REWRITE_ACTION_IGNORE_ERR 0x0004 115 #define REWRITE_ACTION_USER 0x0005 116 int la_type; 117 void *la_args; 118 }; 119 120 /* 121 * Map 122 */ 123 struct rewrite_map { 124 125 /* 126 * Legacy stuff 127 */ 128 #define REWRITE_MAP_XFILEMAP 0x0001 /* Rough implementation! */ 129 #define REWRITE_MAP_XPWDMAP 0x0002 /* uid -> gecos */ 130 #define REWRITE_MAP_XLDAPMAP 0x0003 /* Not implemented yet! */ 131 132 /* 133 * Maps with args 134 */ 135 #define REWRITE_MAP_SUBCONTEXT 0x0101 136 137 #define REWRITE_MAP_SET_OP_VAR 0x0102 138 #define REWRITE_MAP_SETW_OP_VAR 0x0103 139 #define REWRITE_MAP_GET_OP_VAR 0x0104 140 #define REWRITE_MAP_SET_SESN_VAR 0x0105 141 #define REWRITE_MAP_SETW_SESN_VAR 0x0106 142 #define REWRITE_MAP_GET_SESN_VAR 0x0107 143 #define REWRITE_MAP_GET_PARAM 0x0108 144 #define REWRITE_MAP_BUILTIN 0x0109 145 int lm_type; 146 147 char *lm_name; 148 void *lm_data; 149 150 /* 151 * Old maps store private data in _lm_args; 152 * new maps store the substitution pattern in _lm_subst 153 */ 154 union { 155 void *_lm_args; 156 struct rewrite_subst *_lm_subst; 157 } lm_union; 158 #define lm_args lm_union._lm_args 159 #define lm_subst lm_union._lm_subst 160 161 #ifdef USE_REWRITE_LDAP_PVT_THREADS 162 ldap_pvt_thread_mutex_t lm_mutex; 163 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 164 }; 165 166 /* 167 * Builtin maps 168 */ 169 struct rewrite_builtin_map { 170 #define REWRITE_BUILTIN_MAP 0x0200 171 int lb_type; 172 char *lb_name; 173 void *lb_private; 174 const rewrite_mapper *lb_mapper; 175 176 #ifdef USE_REWRITE_LDAP_PVT_THREADS 177 ldap_pvt_thread_mutex_t lb_mutex; 178 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 179 }; 180 181 /* 182 * Submatch substitution 183 */ 184 struct rewrite_submatch { 185 #define REWRITE_SUBMATCH_ASIS 0x0000 186 #define REWRITE_SUBMATCH_XMAP 0x0001 187 #define REWRITE_SUBMATCH_MAP_W_ARG 0x0002 188 int ls_type; 189 struct rewrite_map *ls_map; 190 int ls_submatch; 191 /* 192 * The first one represents the index of the submatch in case 193 * the map has single submatch as argument; 194 * the latter represents the map argument scheme in case 195 * the map has substitution string argument form 196 */ 197 }; 198 199 /* 200 * Pattern substitution 201 */ 202 struct rewrite_subst { 203 size_t lt_subs_len; 204 struct berval *lt_subs; 205 206 int lt_num_submatch; 207 struct rewrite_submatch *lt_submatch; 208 }; 209 210 /* 211 * Rule 212 */ 213 struct rewrite_rule { 214 struct rewrite_rule *lr_next; 215 struct rewrite_rule *lr_prev; 216 217 char *lr_pattern; 218 char *lr_subststring; 219 char *lr_flagstring; 220 regex_t lr_regex; 221 222 /* 223 * I was thinking about some kind of per-rule mutex, but there's 224 * probably no need, because rules after compilation are only read; 225 * however, I need to check whether regexec is reentrant ... 226 */ 227 228 struct rewrite_subst *lr_subst; 229 230 #define REWRITE_REGEX_ICASE REG_ICASE 231 #define REWRITE_REGEX_EXTENDED REG_EXTENDED 232 int lr_flags; 233 234 #define REWRITE_RECURSE 0x0001 235 #define REWRITE_EXEC_ONCE 0x0002 236 int lr_mode; 237 int lr_max_passes; 238 239 struct rewrite_action *lr_action; 240 }; 241 242 /* 243 * Rewrite Context (set of rules) 244 */ 245 struct rewrite_context { 246 char *lc_name; 247 struct rewrite_context *lc_alias; 248 struct rewrite_rule *lc_rule; 249 }; 250 251 /* 252 * Session 253 */ 254 struct rewrite_session { 255 void *ls_cookie; 256 Avlnode *ls_vars; 257 #ifdef USE_REWRITE_LDAP_PVT_THREADS 258 ldap_pvt_thread_rdwr_t ls_vars_mutex; 259 ldap_pvt_thread_mutex_t ls_mutex; 260 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 261 int ls_count; 262 }; 263 264 /* 265 * Variable 266 */ 267 struct rewrite_var { 268 char *lv_name; 269 int lv_flags; 270 struct berval lv_value; 271 }; 272 273 /* 274 * Operation 275 */ 276 struct rewrite_op { 277 int lo_num_passes; 278 int lo_depth; 279 #if 0 /* FIXME: not used anywhere! (debug? then, why strdup?) */ 280 char *lo_string; 281 #endif 282 char *lo_result; 283 Avlnode *lo_vars; 284 const void *lo_cookie; 285 }; 286 287 288 /********** 289 * PUBLIC * 290 **********/ 291 292 /* 293 * Rewrite info 294 */ 295 struct rewrite_info { 296 Avlnode *li_context; 297 Avlnode *li_maps; 298 /* 299 * No global mutex because maps are read only at 300 * config time 301 */ 302 Avlnode *li_params; 303 Avlnode *li_cookies; 304 int li_num_cookies; 305 306 #ifdef USE_REWRITE_LDAP_PVT_THREADS 307 ldap_pvt_thread_rdwr_t li_params_mutex; 308 ldap_pvt_thread_rdwr_t li_cookies_mutex; 309 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 310 311 /* 312 * Default to `off'; 313 * use `rewriteEngine {on|off}' directive to alter 314 */ 315 int li_state; 316 317 /* 318 * Defaults to REWRITE_MAXPASSES; 319 * use `rewriteMaxPasses numPasses' directive to alter 320 */ 321 #define REWRITE_MAXPASSES 100 322 int li_max_passes; 323 int li_max_passes_per_rule; 324 325 /* 326 * Behavior in case a NULL or non-existent context is required 327 */ 328 int li_rewrite_mode; 329 }; 330 331 /*********** 332 * PRIVATE * 333 ***********/ 334 335 LDAP_REWRITE_V (struct rewrite_context*) rewrite_int_curr_context; 336 337 /* 338 * Maps 339 */ 340 341 /* 342 * Parses a map (also in legacy 'x' version) 343 */ 344 LDAP_REWRITE_F (struct rewrite_map *) 345 rewrite_map_parse( 346 struct rewrite_info *info, 347 const char *s, 348 const char **end 349 ); 350 351 LDAP_REWRITE_F (struct rewrite_map *) 352 rewrite_xmap_parse( 353 struct rewrite_info *info, 354 const char *s, 355 const char **end 356 ); 357 358 /* 359 * Resolves key in val by means of map (also in legacy 'x' version) 360 */ 361 LDAP_REWRITE_F (int) 362 rewrite_map_apply( 363 struct rewrite_info *info, 364 struct rewrite_op *op, 365 struct rewrite_map *map, 366 struct berval *key, 367 struct berval *val 368 ); 369 370 LDAP_REWRITE_F (int) 371 rewrite_xmap_apply( 372 struct rewrite_info *info, 373 struct rewrite_op *op, 374 struct rewrite_map *map, 375 struct berval *key, 376 struct berval *val 377 ); 378 379 LDAP_REWRITE_F (int) 380 rewrite_map_destroy( 381 struct rewrite_map **map 382 ); 383 384 LDAP_REWRITE_F (int) 385 rewrite_xmap_destroy( 386 struct rewrite_map **map 387 ); 388 389 LDAP_REWRITE_F (void) 390 rewrite_builtin_map_free( 391 void *map 392 ); 393 /* 394 * Submatch substitution 395 */ 396 397 /* 398 * Compiles a substitution pattern 399 */ 400 LDAP_REWRITE_F (struct rewrite_subst *) 401 rewrite_subst_compile( 402 struct rewrite_info *info, 403 const char *result 404 ); 405 406 /* 407 * Substitutes a portion of rewritten string according to substitution 408 * pattern using submatches 409 */ 410 LDAP_REWRITE_F (int) 411 rewrite_subst_apply( 412 struct rewrite_info *info, 413 struct rewrite_op *op, 414 struct rewrite_subst *subst, 415 const char *string, 416 const regmatch_t *match, 417 struct berval *val 418 ); 419 420 LDAP_REWRITE_F (int) 421 rewrite_subst_destroy( 422 struct rewrite_subst **subst 423 ); 424 425 426 /* 427 * Rules 428 */ 429 430 /* 431 * Compiles the rule and appends it at the running context 432 */ 433 LDAP_REWRITE_F (int) 434 rewrite_rule_compile( 435 struct rewrite_info *info, 436 struct rewrite_context *context, 437 const char *pattern, 438 const char *result, 439 const char *flagstring 440 ); 441 442 /* 443 * Rewrites string according to rule; may return: 444 * REWRITE_REGEXEC_OK: fine; if *result != NULL rule matched 445 * and rewrite succeeded. 446 * REWRITE_REGEXEC_STOP: fine, rule matched; stop processing 447 * following rules 448 * REWRITE_REGEXEC_UNWILL: rule matched; force 'unwilling to perform' 449 * REWRITE_REGEXEC_ERR: an error occurred 450 */ 451 LDAP_REWRITE_F (int) 452 rewrite_rule_apply( 453 struct rewrite_info *info, 454 struct rewrite_op *op, 455 struct rewrite_rule *rule, 456 const char *string, 457 char **result 458 ); 459 460 LDAP_REWRITE_F (int) 461 rewrite_rule_destroy( 462 struct rewrite_rule **rule 463 ); 464 465 /* 466 * Sessions 467 */ 468 469 /* 470 * Fetches a struct rewrite_session 471 */ 472 LDAP_REWRITE_F (struct rewrite_session *) 473 rewrite_session_find( 474 struct rewrite_info *info, 475 const void *cookie 476 ); 477 478 /* 479 * Defines and inits a variable with session scope 480 */ 481 LDAP_REWRITE_F (int) 482 rewrite_session_var_set_f( 483 struct rewrite_info *info, 484 const void *cookie, 485 const char *name, 486 const char *value, 487 int flags 488 ); 489 490 /* 491 * Gets a var with session scope 492 */ 493 LDAP_REWRITE_F (int) 494 rewrite_session_var_get( 495 struct rewrite_info *info, 496 const void *cookie, 497 const char *name, 498 struct berval *val 499 ); 500 501 /* 502 * Deletes a session 503 */ 504 LDAP_REWRITE_F (int) 505 rewrite_session_delete( 506 struct rewrite_info *info, 507 const void *cookie 508 ); 509 510 /* 511 * Destroys the cookie tree 512 */ 513 LDAP_REWRITE_F (int) 514 rewrite_session_destroy( 515 struct rewrite_info *info 516 ); 517 518 519 /* 520 * Vars 521 */ 522 523 /* 524 * Finds a var 525 */ 526 LDAP_REWRITE_F (struct rewrite_var *) 527 rewrite_var_find( 528 Avlnode *tree, 529 const char *name 530 ); 531 532 /* 533 * Replaces the value of a variable 534 */ 535 LDAP_REWRITE_F (int) 536 rewrite_var_replace( 537 struct rewrite_var *var, 538 const char *value, 539 int flags 540 ); 541 542 /* 543 * Inserts a newly created var 544 */ 545 LDAP_REWRITE_F (struct rewrite_var *) 546 rewrite_var_insert_f( 547 Avlnode **tree, 548 const char *name, 549 const char *value, 550 int flags 551 ); 552 553 #define rewrite_var_insert(tree, name, value) \ 554 rewrite_var_insert_f((tree), (name), (value), \ 555 REWRITE_VAR_UPDATE|REWRITE_VAR_COPY_NAME|REWRITE_VAR_COPY_VALUE) 556 557 /* 558 * Sets/inserts a var 559 */ 560 LDAP_REWRITE_F (struct rewrite_var *) 561 rewrite_var_set_f( 562 Avlnode **tree, 563 const char *name, 564 const char *value, 565 int flags 566 ); 567 568 #define rewrite_var_set(tree, name, value, insert) \ 569 rewrite_var_set_f((tree), (name), (value), \ 570 REWRITE_VAR_UPDATE|REWRITE_VAR_COPY_NAME|REWRITE_VAR_COPY_VALUE|((insert)? REWRITE_VAR_INSERT : 0)) 571 572 /* 573 * Deletes a var tree 574 */ 575 LDAP_REWRITE_F (int) 576 rewrite_var_delete( 577 Avlnode *tree 578 ); 579 580 581 /* 582 * Contexts 583 */ 584 585 /* 586 * Finds the context named rewriteContext in the context tree 587 */ 588 LDAP_REWRITE_F (struct rewrite_context *) 589 rewrite_context_find( 590 struct rewrite_info *info, 591 const char *rewriteContext 592 ); 593 594 /* 595 * Creates a new context called rewriteContext and stores in into the tree 596 */ 597 LDAP_REWRITE_F (struct rewrite_context *) 598 rewrite_context_create( 599 struct rewrite_info *info, 600 const char *rewriteContext 601 ); 602 603 /* 604 * Rewrites string according to context; may return: 605 * OK: fine; if *result != NULL rule matched and rewrite succeeded. 606 * STOP: fine, rule matched; stop processing following rules 607 * UNWILL: rule matched; force 'unwilling to perform' 608 */ 609 LDAP_REWRITE_F (int) 610 rewrite_context_apply( 611 struct rewrite_info *info, 612 struct rewrite_op *op, 613 struct rewrite_context *context, 614 const char *string, 615 char **result 616 ); 617 618 LDAP_REWRITE_F (int) 619 rewrite_context_destroy( 620 struct rewrite_context **context 621 ); 622 623 LDAP_REWRITE_F (void) 624 rewrite_context_free( 625 void *tmp 626 ); 627 628 #endif /* REWRITE_INT_H */ 629 630