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