github.com/DataDog/datadog-agent/pkg/security/secl@v0.55.0-devel.0.20240517055856-10c4965fea94/compiler/eval/operators.go (about) 1 // Unless explicitly stated otherwise all files in this repository are licensed 2 // under the Apache License Version 2.0. 3 // This product includes software developed at Datadog (https://www.datadoghq.com/). 4 // Copyright 2016-present Datadog, Inc. 5 6 // Package eval holds eval related files 7 package eval 8 9 import ( 10 "net" 11 "strings" 12 ) 13 14 // OpOverrides defines operator override functions 15 type OpOverrides struct { 16 StringEquals func(a *StringEvaluator, b *StringEvaluator, state *State) (*BoolEvaluator, error) 17 StringValuesContains func(a *StringEvaluator, b *StringValuesEvaluator, state *State) (*BoolEvaluator, error) 18 StringArrayContains func(a *StringEvaluator, b *StringArrayEvaluator, state *State) (*BoolEvaluator, error) 19 StringArrayMatches func(a *StringArrayEvaluator, b *StringValuesEvaluator, state *State) (*BoolEvaluator, error) 20 } 21 22 // return whether a arithmetic operation is deterministic 23 func isArithmDeterministic(a Evaluator, b Evaluator, state *State) bool { 24 isDc := a.IsDeterministicFor(state.field) || b.IsDeterministicFor(state.field) 25 26 if aField := a.GetField(); aField != "" && state.field != "" && aField != state.field { 27 isDc = false 28 } 29 if bField := b.GetField(); bField != "" && state.field != "" && bField != state.field { 30 isDc = false 31 } 32 33 return isDc 34 } 35 36 // Or operator 37 func Or(a *BoolEvaluator, b *BoolEvaluator, state *State) (*BoolEvaluator, error) { 38 39 isDc := a.IsDeterministicFor(state.field) || b.IsDeterministicFor(state.field) 40 41 if a.EvalFnc != nil && b.EvalFnc != nil { 42 ea, eb := a.EvalFnc, b.EvalFnc 43 44 if state.field != "" { 45 if !a.IsDeterministicFor(state.field) && !a.IsStatic() { 46 ea = func(ctx *Context) bool { 47 return true 48 } 49 } 50 if !b.IsDeterministicFor(state.field) && !b.IsStatic() { 51 eb = func(ctx *Context) bool { 52 return true 53 } 54 } 55 } 56 57 if a.Weight > b.Weight { 58 tmp := ea 59 ea = eb 60 eb = tmp 61 } 62 63 evalFnc := func(ctx *Context) bool { 64 return ea(ctx) || eb(ctx) 65 } 66 67 return &BoolEvaluator{ 68 EvalFnc: evalFnc, 69 Weight: a.Weight + b.Weight, 70 isDeterministic: isDc, 71 }, nil 72 } 73 74 if a.EvalFnc == nil && b.EvalFnc == nil { 75 ea, eb := a.Value, b.Value 76 77 ctx := NewContext(nil) 78 _ = ctx 79 80 return &BoolEvaluator{ 81 Value: ea || eb, 82 isDeterministic: isDc, 83 }, nil 84 } 85 86 if a.EvalFnc != nil { 87 ea, eb := a.EvalFnc, b.Value 88 89 if a.Field != "" { 90 if err := state.UpdateFieldValues(a.Field, FieldValue{Value: eb, Type: ScalarValueType}); err != nil { 91 return nil, err 92 } 93 } 94 95 if state.field != "" { 96 if !a.IsDeterministicFor(state.field) && !a.IsStatic() { 97 ea = func(ctx *Context) bool { 98 return true 99 } 100 } 101 if !b.IsDeterministicFor(state.field) && !b.IsStatic() { 102 eb = true 103 } 104 } 105 106 evalFnc := func(ctx *Context) bool { 107 return ea(ctx) || eb 108 } 109 110 return &BoolEvaluator{ 111 EvalFnc: evalFnc, 112 Field: a.Field, 113 Weight: a.Weight, 114 isDeterministic: isDc, 115 }, nil 116 } 117 118 ea, eb := a.Value, b.EvalFnc 119 120 if b.Field != "" { 121 if err := state.UpdateFieldValues(b.Field, FieldValue{Value: ea, Type: ScalarValueType}); err != nil { 122 return nil, err 123 } 124 } 125 126 if state.field != "" { 127 if !a.IsDeterministicFor(state.field) && !a.IsStatic() { 128 ea = true 129 } 130 if !b.IsDeterministicFor(state.field) && !b.IsStatic() { 131 eb = func(ctx *Context) bool { 132 return true 133 } 134 } 135 } 136 137 evalFnc := func(ctx *Context) bool { 138 return ea || eb(ctx) 139 } 140 141 return &BoolEvaluator{ 142 EvalFnc: evalFnc, 143 Field: b.Field, 144 Weight: b.Weight, 145 isDeterministic: isDc, 146 }, nil 147 } 148 149 // And operator 150 func And(a *BoolEvaluator, b *BoolEvaluator, state *State) (*BoolEvaluator, error) { 151 152 isDc := a.IsDeterministicFor(state.field) || b.IsDeterministicFor(state.field) 153 154 if a.EvalFnc != nil && b.EvalFnc != nil { 155 ea, eb := a.EvalFnc, b.EvalFnc 156 157 if state.field != "" { 158 if !a.IsDeterministicFor(state.field) && !a.IsStatic() { 159 ea = func(ctx *Context) bool { 160 return true 161 } 162 } 163 if !b.IsDeterministicFor(state.field) && !b.IsStatic() { 164 eb = func(ctx *Context) bool { 165 return true 166 } 167 } 168 } 169 170 if a.Weight > b.Weight { 171 tmp := ea 172 ea = eb 173 eb = tmp 174 } 175 176 evalFnc := func(ctx *Context) bool { 177 return ea(ctx) && eb(ctx) 178 } 179 180 return &BoolEvaluator{ 181 EvalFnc: evalFnc, 182 Weight: a.Weight + b.Weight, 183 isDeterministic: isDc, 184 }, nil 185 } 186 187 if a.EvalFnc == nil && b.EvalFnc == nil { 188 ea, eb := a.Value, b.Value 189 190 ctx := NewContext(nil) 191 _ = ctx 192 193 return &BoolEvaluator{ 194 Value: ea && eb, 195 isDeterministic: isDc, 196 }, nil 197 } 198 199 if a.EvalFnc != nil { 200 ea, eb := a.EvalFnc, b.Value 201 202 if a.Field != "" { 203 if err := state.UpdateFieldValues(a.Field, FieldValue{Value: eb, Type: ScalarValueType}); err != nil { 204 return nil, err 205 } 206 } 207 208 if state.field != "" { 209 if !a.IsDeterministicFor(state.field) && !a.IsStatic() { 210 ea = func(ctx *Context) bool { 211 return true 212 } 213 } 214 if !b.IsDeterministicFor(state.field) && !b.IsStatic() { 215 eb = true 216 } 217 } 218 219 evalFnc := func(ctx *Context) bool { 220 return ea(ctx) && eb 221 } 222 223 return &BoolEvaluator{ 224 EvalFnc: evalFnc, 225 Field: a.Field, 226 Weight: a.Weight, 227 isDeterministic: isDc, 228 }, nil 229 } 230 231 ea, eb := a.Value, b.EvalFnc 232 233 if b.Field != "" { 234 if err := state.UpdateFieldValues(b.Field, FieldValue{Value: ea, Type: ScalarValueType}); err != nil { 235 return nil, err 236 } 237 } 238 239 if state.field != "" { 240 if !a.IsDeterministicFor(state.field) && !a.IsStatic() { 241 ea = true 242 } 243 if !b.IsDeterministicFor(state.field) && !b.IsStatic() { 244 eb = func(ctx *Context) bool { 245 return true 246 } 247 } 248 } 249 250 evalFnc := func(ctx *Context) bool { 251 return ea && eb(ctx) 252 } 253 254 return &BoolEvaluator{ 255 EvalFnc: evalFnc, 256 Field: b.Field, 257 Weight: b.Weight, 258 isDeterministic: isDc, 259 }, nil 260 } 261 262 // IntNot ^int operator 263 func IntNot(a *IntEvaluator, state *State) *IntEvaluator { 264 isDc := a.IsDeterministicFor(state.field) 265 266 if a.EvalFnc != nil { 267 ea := a.EvalFnc 268 269 evalFnc := func(ctx *Context) int { 270 return ^ea(ctx) 271 } 272 273 return &IntEvaluator{ 274 EvalFnc: evalFnc, 275 Weight: a.Weight, 276 isDeterministic: isDc, 277 } 278 } 279 280 return &IntEvaluator{ 281 Value: ^a.Value, 282 Weight: a.Weight, 283 isDeterministic: isDc, 284 } 285 } 286 287 // StringEquals evaluates string 288 func StringEquals(a *StringEvaluator, b *StringEvaluator, state *State) (*BoolEvaluator, error) { 289 isDc := isArithmDeterministic(a, b, state) 290 291 if a.Field != "" { 292 if err := state.UpdateFieldValues(a.Field, FieldValue{Value: b.Value, Type: b.ValueType}); err != nil { 293 return nil, err 294 } 295 } 296 297 if b.Field != "" { 298 if err := state.UpdateFieldValues(b.Field, FieldValue{Value: a.Value, Type: a.ValueType}); err != nil { 299 return nil, err 300 } 301 } 302 303 // default comparison 304 op := func(as string, bs string) bool { 305 return as == bs 306 } 307 308 if a.Field != "" && b.Field != "" { 309 if a.StringCmpOpts.CaseInsensitive || b.StringCmpOpts.CaseInsensitive { 310 op = strings.EqualFold 311 } 312 } else if a.Field != "" { 313 matcher, err := b.ToStringMatcher(a.StringCmpOpts) 314 if err != nil { 315 return nil, err 316 } 317 318 if matcher != nil { 319 op = func(as string, bs string) bool { 320 return matcher.Matches(as) 321 } 322 } 323 } else if b.Field != "" { 324 matcher, err := a.ToStringMatcher(b.StringCmpOpts) 325 if err != nil { 326 return nil, err 327 } 328 329 if matcher != nil { 330 op = func(as string, bs string) bool { 331 return matcher.Matches(bs) 332 } 333 } 334 } 335 336 if a.EvalFnc != nil && b.EvalFnc != nil { 337 ea, eb := a.EvalFnc, b.EvalFnc 338 339 evalFnc := func(ctx *Context) bool { 340 return op(ea(ctx), eb(ctx)) 341 } 342 343 return &BoolEvaluator{ 344 EvalFnc: evalFnc, 345 Weight: a.Weight + b.Weight, 346 isDeterministic: isDc, 347 }, nil 348 } 349 350 if a.EvalFnc == nil && b.EvalFnc == nil { 351 ea, eb := a.Value, b.Value 352 353 return &BoolEvaluator{ 354 Value: op(ea, eb), 355 Weight: a.Weight + InArrayWeight*len(eb), 356 isDeterministic: isDc, 357 }, nil 358 } 359 360 if a.EvalFnc != nil { 361 ea, eb := a.EvalFnc, b.Value 362 363 evalFnc := func(ctx *Context) bool { 364 return op(ea(ctx), eb) 365 } 366 367 return &BoolEvaluator{ 368 EvalFnc: evalFnc, 369 Weight: a.Weight + InArrayWeight*len(eb), 370 isDeterministic: isDc, 371 }, nil 372 } 373 374 ea, eb := a.Value, b.EvalFnc 375 376 evalFnc := func(ctx *Context) bool { 377 return op(ea, eb(ctx)) 378 } 379 380 return &BoolEvaluator{ 381 EvalFnc: evalFnc, 382 Weight: b.Weight, 383 isDeterministic: isDc, 384 }, nil 385 } 386 387 // Not !true operator 388 func Not(a *BoolEvaluator, state *State) *BoolEvaluator { 389 isDc := a.IsDeterministicFor(state.field) 390 391 if a.EvalFnc != nil { 392 ea := func(ctx *Context) bool { 393 return !a.EvalFnc(ctx) 394 } 395 396 if state.field != "" && !a.IsDeterministicFor(state.field) { 397 ea = func(ctx *Context) bool { 398 return true 399 } 400 } 401 402 return &BoolEvaluator{ 403 EvalFnc: ea, 404 Weight: a.Weight, 405 isDeterministic: isDc, 406 } 407 } 408 409 return &BoolEvaluator{ 410 Value: !a.Value, 411 Weight: a.Weight, 412 isDeterministic: isDc, 413 } 414 } 415 416 // Minus -int operator 417 func Minus(a *IntEvaluator, state *State) *IntEvaluator { 418 isDc := a.IsDeterministicFor(state.field) 419 420 if a.EvalFnc != nil { 421 ea := a.EvalFnc 422 423 evalFnc := func(ctx *Context) int { 424 return -ea(ctx) 425 } 426 427 return &IntEvaluator{ 428 EvalFnc: evalFnc, 429 Weight: a.Weight, 430 isDeterministic: isDc, 431 } 432 } 433 434 return &IntEvaluator{ 435 Value: -a.Value, 436 Weight: a.Weight, 437 isDeterministic: isDc, 438 } 439 } 440 441 // StringArrayContains evaluates array of strings against a value 442 func StringArrayContains(a *StringEvaluator, b *StringArrayEvaluator, state *State) (*BoolEvaluator, error) { 443 isDc := isArithmDeterministic(a, b, state) 444 445 if a.Field != "" { 446 for _, value := range b.Values { 447 if err := state.UpdateFieldValues(a.Field, FieldValue{Value: value, Type: ScalarValueType}); err != nil { 448 return nil, err 449 } 450 } 451 } 452 453 if b.Field != "" { 454 if err := state.UpdateFieldValues(b.Field, FieldValue{Value: a.Value, Type: a.ValueType}); err != nil { 455 return nil, err 456 } 457 } 458 459 op := func(a string, b []string, cmp func(a, b string) bool) bool { 460 for _, bs := range b { 461 if cmp(a, bs) { 462 return true 463 } 464 } 465 return false 466 } 467 468 cmp := func(a, b string) bool { 469 return a == b 470 } 471 472 if a.Field != "" && b.Field != "" { 473 if a.StringCmpOpts.CaseInsensitive || b.StringCmpOpts.CaseInsensitive { 474 cmp = strings.EqualFold 475 } 476 } else if a.Field != "" && a.StringCmpOpts.CaseInsensitive { 477 cmp = strings.EqualFold 478 } else if b.Field != "" { 479 matcher, err := a.ToStringMatcher(b.StringCmpOpts) 480 if err != nil { 481 return nil, err 482 } 483 484 if matcher != nil { 485 cmp = func(a, b string) bool { 486 return matcher.Matches(b) 487 } 488 } 489 } 490 491 if a.EvalFnc != nil && b.EvalFnc != nil { 492 ea, eb := a.EvalFnc, b.EvalFnc 493 494 evalFnc := func(ctx *Context) bool { 495 return op(ea(ctx), eb(ctx), cmp) 496 } 497 498 return &BoolEvaluator{ 499 EvalFnc: evalFnc, 500 Weight: a.Weight + b.Weight, 501 isDeterministic: isDc, 502 }, nil 503 } 504 505 if a.EvalFnc == nil && b.EvalFnc == nil { 506 ea, eb := a.Value, b.Values 507 508 return &BoolEvaluator{ 509 Value: op(ea, eb, cmp), 510 Weight: a.Weight + InArrayWeight*len(eb), 511 isDeterministic: isDc, 512 }, nil 513 } 514 515 if a.EvalFnc != nil { 516 ea, eb := a.EvalFnc, b.Values 517 518 evalFnc := func(ctx *Context) bool { 519 return op(ea(ctx), eb, cmp) 520 } 521 522 return &BoolEvaluator{ 523 EvalFnc: evalFnc, 524 Weight: a.Weight + InArrayWeight*len(eb), 525 isDeterministic: isDc, 526 }, nil 527 } 528 529 ea, eb := a.Value, b.EvalFnc 530 531 evalFnc := func(ctx *Context) bool { 532 return op(ea, eb(ctx), cmp) 533 } 534 535 return &BoolEvaluator{ 536 EvalFnc: evalFnc, 537 Weight: b.Weight, 538 isDeterministic: isDc, 539 }, nil 540 } 541 542 // StringValuesContains evaluates a string against values 543 func StringValuesContains(a *StringEvaluator, b *StringValuesEvaluator, state *State) (*BoolEvaluator, error) { 544 isDc := isArithmDeterministic(a, b, state) 545 546 if a.Field != "" { 547 for _, value := range b.Values.fieldValues { 548 if err := state.UpdateFieldValues(a.Field, value); err != nil { 549 return nil, err 550 } 551 } 552 } 553 554 if err := b.Compile(a.StringCmpOpts); err != nil { 555 return nil, err 556 } 557 558 if a.EvalFnc != nil && b.EvalFnc != nil { 559 ea, eb := a.EvalFnc, b.EvalFnc 560 561 evalFnc := func(ctx *Context) bool { 562 values := eb(ctx) 563 return values.Matches(ea(ctx)) 564 } 565 566 return &BoolEvaluator{ 567 EvalFnc: evalFnc, 568 Weight: a.Weight + b.Weight, 569 isDeterministic: isDc, 570 }, nil 571 } 572 573 if a.EvalFnc == nil && b.EvalFnc == nil { 574 ea, eb := a.Value, b.Values 575 576 return &BoolEvaluator{ 577 Value: eb.Matches(ea), 578 Weight: a.Weight + InArrayWeight*len(eb.fieldValues), 579 isDeterministic: isDc, 580 }, nil 581 } 582 583 if a.EvalFnc != nil { 584 ea, eb := a.EvalFnc, b.Values 585 586 evalFnc := func(ctx *Context) bool { 587 return eb.Matches(ea(ctx)) 588 } 589 590 return &BoolEvaluator{ 591 EvalFnc: evalFnc, 592 Weight: a.Weight + InArrayWeight*len(eb.fieldValues), 593 isDeterministic: isDc, 594 }, nil 595 } 596 597 ea, eb := a.Value, b.EvalFnc 598 599 evalFnc := func(ctx *Context) bool { 600 values := eb(ctx) 601 return values.Matches(ea) 602 } 603 604 return &BoolEvaluator{ 605 EvalFnc: evalFnc, 606 Weight: b.Weight, 607 isDeterministic: isDc, 608 }, nil 609 } 610 611 // StringArrayMatches weak comparison, a least one element of a should be in b. a can't contain regexp 612 func StringArrayMatches(a *StringArrayEvaluator, b *StringValuesEvaluator, state *State) (*BoolEvaluator, error) { 613 isDc := isArithmDeterministic(a, b, state) 614 615 if a.Field != "" { 616 for _, value := range b.Values.fieldValues { 617 if err := state.UpdateFieldValues(a.Field, value); err != nil { 618 return nil, err 619 } 620 } 621 } 622 623 if err := b.Compile(a.StringCmpOpts); err != nil { 624 return nil, err 625 } 626 627 arrayOp := func(a []string, b *StringValues) bool { 628 for _, as := range a { 629 if b.Matches(as) { 630 return true 631 } 632 } 633 return false 634 } 635 636 if a.EvalFnc != nil && b.EvalFnc != nil { 637 ea, eb := a.EvalFnc, b.EvalFnc 638 639 evalFnc := func(ctx *Context) bool { 640 return arrayOp(ea(ctx), eb(ctx)) 641 } 642 643 return &BoolEvaluator{ 644 EvalFnc: evalFnc, 645 Weight: a.Weight + b.Weight, 646 isDeterministic: isDc, 647 }, nil 648 } 649 650 if a.EvalFnc == nil && b.EvalFnc == nil { 651 ea, eb := a.Values, b.Values 652 653 return &BoolEvaluator{ 654 Value: arrayOp(ea, &eb), 655 Weight: a.Weight + InArrayWeight*len(eb.fieldValues), 656 isDeterministic: isDc, 657 }, nil 658 } 659 660 if a.EvalFnc != nil { 661 ea, eb := a.EvalFnc, b.Values 662 663 evalFnc := func(ctx *Context) bool { 664 return arrayOp(ea(ctx), &eb) 665 } 666 667 return &BoolEvaluator{ 668 EvalFnc: evalFnc, 669 Weight: a.Weight + InArrayWeight*len(eb.fieldValues), 670 isDeterministic: isDc, 671 }, nil 672 } 673 674 ea, eb := a.Values, b.EvalFnc 675 676 evalFnc := func(ctx *Context) bool { 677 return arrayOp(ea, eb(ctx)) 678 } 679 680 return &BoolEvaluator{ 681 EvalFnc: evalFnc, 682 Weight: b.Weight, 683 isDeterministic: isDc, 684 }, nil 685 } 686 687 // IntArrayMatches weak comparison, a least one element of a should be in b 688 func IntArrayMatches(a *IntArrayEvaluator, b *IntArrayEvaluator, state *State) (*BoolEvaluator, error) { 689 isDc := isArithmDeterministic(a, b, state) 690 691 if a.Field != "" { 692 for _, value := range b.Values { 693 if err := state.UpdateFieldValues(a.Field, FieldValue{Value: value}); err != nil { 694 return nil, err 695 } 696 } 697 } 698 699 arrayOp := func(a []int, b []int) bool { 700 for _, va := range a { 701 for _, vb := range b { 702 if va == vb { 703 return true 704 } 705 } 706 } 707 return false 708 } 709 710 if a.EvalFnc != nil && b.EvalFnc != nil { 711 ea, eb := a.EvalFnc, b.EvalFnc 712 713 evalFnc := func(ctx *Context) bool { 714 return arrayOp(ea(ctx), eb(ctx)) 715 } 716 717 return &BoolEvaluator{ 718 EvalFnc: evalFnc, 719 Weight: a.Weight + b.Weight, 720 isDeterministic: isDc, 721 }, nil 722 } 723 724 if a.EvalFnc == nil && b.EvalFnc == nil { 725 ea, eb := a.Values, b.Values 726 727 return &BoolEvaluator{ 728 Value: arrayOp(ea, eb), 729 Weight: a.Weight + InArrayWeight*len(eb), 730 isDeterministic: isDc, 731 }, nil 732 } 733 734 if a.EvalFnc != nil { 735 ea, eb := a.EvalFnc, b.Values 736 737 evalFnc := func(ctx *Context) bool { 738 return arrayOp(ea(ctx), eb) 739 } 740 741 return &BoolEvaluator{ 742 EvalFnc: evalFnc, 743 Weight: a.Weight + InArrayWeight*len(eb), 744 isDeterministic: isDc, 745 }, nil 746 } 747 748 ea, eb := a.Values, b.EvalFnc 749 750 evalFnc := func(ctx *Context) bool { 751 return arrayOp(ea, eb(ctx)) 752 } 753 754 return &BoolEvaluator{ 755 EvalFnc: evalFnc, 756 Weight: b.Weight, 757 isDeterministic: isDc, 758 }, nil 759 } 760 761 // ArrayBoolContains evaluates array of bool against a value 762 func ArrayBoolContains(a *BoolEvaluator, b *BoolArrayEvaluator, state *State) (*BoolEvaluator, error) { 763 isDc := isArithmDeterministic(a, b, state) 764 765 if a.Field != "" { 766 for _, value := range b.Values { 767 if err := state.UpdateFieldValues(a.Field, FieldValue{Value: value}); err != nil { 768 return nil, err 769 } 770 } 771 } 772 773 if b.Field != "" { 774 if err := state.UpdateFieldValues(b.Field, FieldValue{Value: a.Value}); err != nil { 775 return nil, err 776 } 777 } 778 779 arrayOp := func(a bool, b []bool) bool { 780 for _, v := range b { 781 if v == a { 782 return true 783 } 784 } 785 return false 786 } 787 if a.EvalFnc != nil && b.EvalFnc != nil { 788 ea, eb := a.EvalFnc, b.EvalFnc 789 790 evalFnc := func(ctx *Context) bool { 791 return arrayOp(ea(ctx), eb(ctx)) 792 } 793 794 return &BoolEvaluator{ 795 EvalFnc: evalFnc, 796 Weight: a.Weight + b.Weight, 797 isDeterministic: isDc, 798 }, nil 799 } 800 801 if a.EvalFnc == nil && b.EvalFnc == nil { 802 ea, eb := a.Value, b.Values 803 804 return &BoolEvaluator{ 805 Value: arrayOp(ea, eb), 806 Weight: a.Weight + InArrayWeight*len(eb), 807 isDeterministic: isDc, 808 }, nil 809 } 810 811 if a.EvalFnc != nil { 812 ea, eb := a.EvalFnc, b.Values 813 814 evalFnc := func(ctx *Context) bool { 815 return arrayOp(ea(ctx), eb) 816 } 817 818 return &BoolEvaluator{ 819 EvalFnc: evalFnc, 820 Weight: a.Weight + InArrayWeight*len(eb), 821 isDeterministic: isDc, 822 }, nil 823 } 824 825 ea, eb := a.Value, b.EvalFnc 826 827 evalFnc := func(ctx *Context) bool { 828 return arrayOp(ea, eb(ctx)) 829 } 830 831 return &BoolEvaluator{ 832 EvalFnc: evalFnc, 833 Weight: b.Weight, 834 isDeterministic: isDc, 835 }, nil 836 } 837 838 // CIDREquals evaluates CIDR ranges 839 func CIDREquals(a *CIDREvaluator, b *CIDREvaluator, state *State) (*BoolEvaluator, error) { 840 isDc := isArithmDeterministic(a, b, state) 841 842 if a.Field != "" { 843 if err := state.UpdateFieldValues(a.Field, FieldValue{Value: b.Value, Type: b.ValueType}); err != nil { 844 return nil, err 845 } 846 } 847 848 if b.Field != "" { 849 if err := state.UpdateFieldValues(b.Field, FieldValue{Value: a.Value, Type: a.ValueType}); err != nil { 850 return nil, err 851 } 852 } 853 854 if a.EvalFnc != nil && b.EvalFnc != nil { 855 ea, eb := a.EvalFnc, b.EvalFnc 856 857 evalFnc := func(ctx *Context) bool { 858 a, b := ea(ctx), eb(ctx) 859 return IPNetsMatch(&a, &b) 860 } 861 862 return &BoolEvaluator{ 863 EvalFnc: evalFnc, 864 Weight: a.Weight + b.Weight, 865 isDeterministic: isDc, 866 }, nil 867 } 868 869 if a.EvalFnc == nil && b.EvalFnc == nil { 870 ea, eb := a.Value, b.Value 871 872 return &BoolEvaluator{ 873 Value: IPNetsMatch(&ea, &eb), 874 Weight: a.Weight + b.Weight, 875 isDeterministic: isDc, 876 }, nil 877 } 878 879 if a.EvalFnc != nil { 880 ea, eb := a.EvalFnc, b.Value 881 882 evalFnc := func(ctx *Context) bool { 883 a := ea(ctx) 884 return IPNetsMatch(&a, &eb) 885 } 886 887 return &BoolEvaluator{ 888 EvalFnc: evalFnc, 889 Weight: a.Weight + b.Weight, 890 isDeterministic: isDc, 891 }, nil 892 } 893 894 ea, eb := a.Value, b.EvalFnc 895 896 evalFnc := func(ctx *Context) bool { 897 b := eb(ctx) 898 return IPNetsMatch(&ea, &b) 899 } 900 901 return &BoolEvaluator{ 902 EvalFnc: evalFnc, 903 Weight: b.Weight, 904 isDeterministic: isDc, 905 }, nil 906 } 907 908 // CIDRValuesContains evaluates a CIDR against a list of CIDRs 909 func CIDRValuesContains(a *CIDREvaluator, b *CIDRValuesEvaluator, state *State) (*BoolEvaluator, error) { 910 isDc := isArithmDeterministic(a, b, state) 911 912 if a.Field != "" { 913 for _, value := range b.Value.fieldValues { 914 if err := state.UpdateFieldValues(a.Field, value); err != nil { 915 return nil, err 916 } 917 } 918 } 919 920 if a.EvalFnc != nil && b.EvalFnc != nil { 921 ea, eb := a.EvalFnc, b.EvalFnc 922 923 evalFnc := func(ctx *Context) bool { 924 a := ea(ctx) 925 return eb(ctx).Contains(&a) 926 } 927 928 return &BoolEvaluator{ 929 EvalFnc: evalFnc, 930 Weight: a.Weight + b.Weight, 931 isDeterministic: isDc, 932 }, nil 933 } 934 935 if a.EvalFnc == nil && b.EvalFnc == nil { 936 ea, eb := a.Value, b.Value 937 938 return &BoolEvaluator{ 939 Value: eb.Contains(&ea), 940 Weight: a.Weight + InArrayWeight*len(eb.ipnets), 941 isDeterministic: isDc, 942 }, nil 943 } 944 945 if a.EvalFnc != nil { 946 ea, eb := a.EvalFnc, b.Value 947 948 evalFnc := func(ctx *Context) bool { 949 ipnet := ea(ctx) 950 return eb.Contains(&ipnet) 951 } 952 953 return &BoolEvaluator{ 954 EvalFnc: evalFnc, 955 Weight: a.Weight + InArrayWeight*len(eb.fieldValues), 956 isDeterministic: isDc, 957 }, nil 958 } 959 960 ea, eb := a.Value, b.EvalFnc 961 962 evalFnc := func(ctx *Context) bool { 963 return eb(ctx).Contains(&ea) 964 } 965 966 return &BoolEvaluator{ 967 EvalFnc: evalFnc, 968 Weight: b.Weight, 969 isDeterministic: isDc, 970 }, nil 971 } 972 973 func cidrArrayMatches(a *CIDRArrayEvaluator, b *CIDRValuesEvaluator, state *State, arrayOp func(a *CIDRValues, b []net.IPNet) bool) (*BoolEvaluator, error) { 974 isDc := isArithmDeterministic(a, b, state) 975 976 if a.Field != "" { 977 for _, value := range b.Value.fieldValues { 978 if err := state.UpdateFieldValues(a.Field, value); err != nil { 979 return nil, err 980 } 981 } 982 } 983 984 if a.EvalFnc != nil && b.EvalFnc != nil { 985 ea, eb := a.EvalFnc, b.EvalFnc 986 987 evalFnc := func(ctx *Context) bool { 988 return arrayOp(eb(ctx), ea(ctx)) 989 } 990 991 return &BoolEvaluator{ 992 EvalFnc: evalFnc, 993 Weight: a.Weight + b.Weight, 994 isDeterministic: isDc, 995 }, nil 996 } 997 998 if a.EvalFnc == nil && b.EvalFnc == nil { 999 ea, eb := a.Value, b.Value 1000 1001 return &BoolEvaluator{ 1002 Value: arrayOp(&eb, ea), 1003 Weight: a.Weight + InArrayWeight*len(eb.fieldValues), 1004 isDeterministic: isDc, 1005 }, nil 1006 } 1007 1008 if a.EvalFnc != nil { 1009 ea, eb := a.EvalFnc, b.Value 1010 1011 evalFnc := func(ctx *Context) bool { 1012 return arrayOp(&eb, ea(ctx)) 1013 } 1014 1015 return &BoolEvaluator{ 1016 EvalFnc: evalFnc, 1017 Weight: a.Weight + InArrayWeight*len(eb.fieldValues), 1018 isDeterministic: isDc, 1019 }, nil 1020 } 1021 1022 ea, eb := a.Value, b.EvalFnc 1023 1024 evalFnc := func(ctx *Context) bool { 1025 return arrayOp(eb(ctx), ea) 1026 } 1027 1028 return &BoolEvaluator{ 1029 EvalFnc: evalFnc, 1030 Weight: b.Weight, 1031 isDeterministic: isDc, 1032 }, nil 1033 } 1034 1035 // CIDRArrayMatches weak comparison, at least one element of a should be in b. 1036 func CIDRArrayMatches(a *CIDRArrayEvaluator, b *CIDRValuesEvaluator, state *State) (*BoolEvaluator, error) { 1037 op := func(values *CIDRValues, ipnets []net.IPNet) bool { 1038 return values.Match(ipnets) 1039 } 1040 return cidrArrayMatches(a, b, state, op) 1041 } 1042 1043 // CIDRArrayMatchesAll ensures that all values from a and b match. 1044 func CIDRArrayMatchesAll(a *CIDRArrayEvaluator, b *CIDRValuesEvaluator, state *State) (*BoolEvaluator, error) { 1045 op := func(values *CIDRValues, ipnets []net.IPNet) bool { 1046 return values.MatchAll(ipnets) 1047 } 1048 return cidrArrayMatches(a, b, state, op) 1049 } 1050 1051 // CIDRArrayContains evaluates a CIDR against a list of CIDRs 1052 func CIDRArrayContains(a *CIDREvaluator, b *CIDRArrayEvaluator, state *State) (*BoolEvaluator, error) { 1053 isDc := isArithmDeterministic(a, b, state) 1054 1055 if a.Field != "" { 1056 for _, value := range b.Value { 1057 if err := state.UpdateFieldValues(a.Field, FieldValue{Type: IPNetValueType, Value: value}); err != nil { 1058 return nil, err 1059 } 1060 } 1061 } 1062 1063 arrayOp := func(a *net.IPNet, b []net.IPNet) bool { 1064 for _, n := range b { 1065 if IPNetsMatch(a, &n) { 1066 return true 1067 } 1068 } 1069 return false 1070 } 1071 1072 if a.EvalFnc != nil && b.EvalFnc != nil { 1073 ea, eb := a.EvalFnc, b.EvalFnc 1074 1075 evalFnc := func(ctx *Context) bool { 1076 a := ea(ctx) 1077 return arrayOp(&a, eb(ctx)) 1078 } 1079 1080 return &BoolEvaluator{ 1081 EvalFnc: evalFnc, 1082 Weight: a.Weight + b.Weight, 1083 isDeterministic: isDc, 1084 }, nil 1085 } 1086 1087 if a.EvalFnc == nil && b.EvalFnc == nil { 1088 ea, eb := a.Value, b.Value 1089 1090 return &BoolEvaluator{ 1091 Value: arrayOp(&ea, eb), 1092 Weight: a.Weight + InArrayWeight*len(eb), 1093 isDeterministic: isDc, 1094 }, nil 1095 } 1096 1097 if a.EvalFnc != nil { 1098 ea, eb := a.EvalFnc, b.Value 1099 1100 evalFnc := func(ctx *Context) bool { 1101 ipnet := ea(ctx) 1102 return arrayOp(&ipnet, eb) 1103 } 1104 1105 return &BoolEvaluator{ 1106 EvalFnc: evalFnc, 1107 Weight: a.Weight + InArrayWeight*len(eb), 1108 isDeterministic: isDc, 1109 }, nil 1110 } 1111 1112 ea, eb := a.Value, b.EvalFnc 1113 1114 evalFnc := func(ctx *Context) bool { 1115 return arrayOp(&ea, eb(ctx)) 1116 } 1117 1118 return &BoolEvaluator{ 1119 EvalFnc: evalFnc, 1120 Weight: b.Weight, 1121 isDeterministic: isDc, 1122 }, nil 1123 }