1package ldap_test 2 3import ( 4 "strings" 5 "testing" 6 7 "gopkg.in/asn1-ber.v1" 8 "gopkg.in/ldap.v2" 9) 10 11type compileTest struct { 12 filterStr string 13 14 expectedFilter string 15 expectedType int 16 expectedErr string 17} 18 19var testFilters = []compileTest{ 20 compileTest{ 21 filterStr: "(&(sn=Miller)(givenName=Bob))", 22 expectedFilter: "(&(sn=Miller)(givenName=Bob))", 23 expectedType: ldap.FilterAnd, 24 }, 25 compileTest{ 26 filterStr: "(|(sn=Miller)(givenName=Bob))", 27 expectedFilter: "(|(sn=Miller)(givenName=Bob))", 28 expectedType: ldap.FilterOr, 29 }, 30 compileTest{ 31 filterStr: "(!(sn=Miller))", 32 expectedFilter: "(!(sn=Miller))", 33 expectedType: ldap.FilterNot, 34 }, 35 compileTest{ 36 filterStr: "(sn=Miller)", 37 expectedFilter: "(sn=Miller)", 38 expectedType: ldap.FilterEqualityMatch, 39 }, 40 compileTest{ 41 filterStr: "(sn=Mill*)", 42 expectedFilter: "(sn=Mill*)", 43 expectedType: ldap.FilterSubstrings, 44 }, 45 compileTest{ 46 filterStr: "(sn=*Mill)", 47 expectedFilter: "(sn=*Mill)", 48 expectedType: ldap.FilterSubstrings, 49 }, 50 compileTest{ 51 filterStr: "(sn=*Mill*)", 52 expectedFilter: "(sn=*Mill*)", 53 expectedType: ldap.FilterSubstrings, 54 }, 55 compileTest{ 56 filterStr: "(sn=*i*le*)", 57 expectedFilter: "(sn=*i*le*)", 58 expectedType: ldap.FilterSubstrings, 59 }, 60 compileTest{ 61 filterStr: "(sn=Mi*l*r)", 62 expectedFilter: "(sn=Mi*l*r)", 63 expectedType: ldap.FilterSubstrings, 64 }, 65 // substring filters escape properly 66 compileTest{ 67 filterStr: `(sn=Mi*함*r)`, 68 expectedFilter: `(sn=Mi*\ed\95\a8*r)`, 69 expectedType: ldap.FilterSubstrings, 70 }, 71 // already escaped substring filters don't get double-escaped 72 compileTest{ 73 filterStr: `(sn=Mi*\ed\95\a8*r)`, 74 expectedFilter: `(sn=Mi*\ed\95\a8*r)`, 75 expectedType: ldap.FilterSubstrings, 76 }, 77 compileTest{ 78 filterStr: "(sn=Mi*le*)", 79 expectedFilter: "(sn=Mi*le*)", 80 expectedType: ldap.FilterSubstrings, 81 }, 82 compileTest{ 83 filterStr: "(sn=*i*ler)", 84 expectedFilter: "(sn=*i*ler)", 85 expectedType: ldap.FilterSubstrings, 86 }, 87 compileTest{ 88 filterStr: "(sn>=Miller)", 89 expectedFilter: "(sn>=Miller)", 90 expectedType: ldap.FilterGreaterOrEqual, 91 }, 92 compileTest{ 93 filterStr: "(sn<=Miller)", 94 expectedFilter: "(sn<=Miller)", 95 expectedType: ldap.FilterLessOrEqual, 96 }, 97 compileTest{ 98 filterStr: "(sn=*)", 99 expectedFilter: "(sn=*)", 100 expectedType: ldap.FilterPresent, 101 }, 102 compileTest{ 103 filterStr: "(sn~=Miller)", 104 expectedFilter: "(sn~=Miller)", 105 expectedType: ldap.FilterApproxMatch, 106 }, 107 compileTest{ 108 filterStr: `(objectGUID='\fc\fe\a3\ab\f9\90N\aaGm\d5I~\d12)`, 109 expectedFilter: `(objectGUID='\fc\fe\a3\ab\f9\90N\aaGm\d5I~\d12)`, 110 expectedType: ldap.FilterEqualityMatch, 111 }, 112 compileTest{ 113 filterStr: `(objectGUID=абвгдеёжзийклмнопрстуфхцчшщъыьэюя)`, 114 expectedFilter: `(objectGUID=\d0\b0\d0\b1\d0\b2\d0\b3\d0\b4\d0\b5\d1\91\d0\b6\d0\b7\d0\b8\d0\b9\d0\ba\d0\bb\d0\bc\d0\bd\d0\be\d0\bf\d1\80\d1\81\d1\82\d1\83\d1\84\d1\85\d1\86\d1\87\d1\88\d1\89\d1\8a\d1\8b\d1\8c\d1\8d\d1\8e\d1\8f)`, 115 expectedType: ldap.FilterEqualityMatch, 116 }, 117 compileTest{ 118 filterStr: `(objectGUID=함수목록)`, 119 expectedFilter: `(objectGUID=\ed\95\a8\ec\88\98\eb\aa\a9\eb\a1\9d)`, 120 expectedType: ldap.FilterEqualityMatch, 121 }, 122 compileTest{ 123 filterStr: `(objectGUID=`, 124 expectedFilter: ``, 125 expectedType: 0, 126 expectedErr: "unexpected end of filter", 127 }, 128 compileTest{ 129 filterStr: `(objectGUID=함수목록`, 130 expectedFilter: ``, 131 expectedType: 0, 132 expectedErr: "unexpected end of filter", 133 }, 134 compileTest{ 135 filterStr: `((cn=)`, 136 expectedFilter: ``, 137 expectedType: 0, 138 expectedErr: "unexpected end of filter", 139 }, 140 compileTest{ 141 filterStr: `(&(objectclass=inetorgperson)(cn=中文))`, 142 expectedFilter: `(&(objectclass=inetorgperson)(cn=\e4\b8\ad\e6\96\87))`, 143 expectedType: 0, 144 }, 145 // attr extension 146 compileTest{ 147 filterStr: `(memberOf:=foo)`, 148 expectedFilter: `(memberOf:=foo)`, 149 expectedType: ldap.FilterExtensibleMatch, 150 }, 151 // attr+named matching rule extension 152 compileTest{ 153 filterStr: `(memberOf:test:=foo)`, 154 expectedFilter: `(memberOf:test:=foo)`, 155 expectedType: ldap.FilterExtensibleMatch, 156 }, 157 // attr+oid matching rule extension 158 compileTest{ 159 filterStr: `(cn:1.2.3.4.5:=Fred Flintstone)`, 160 expectedFilter: `(cn:1.2.3.4.5:=Fred Flintstone)`, 161 expectedType: ldap.FilterExtensibleMatch, 162 }, 163 // attr+dn+oid matching rule extension 164 compileTest{ 165 filterStr: `(sn:dn:2.4.6.8.10:=Barney Rubble)`, 166 expectedFilter: `(sn:dn:2.4.6.8.10:=Barney Rubble)`, 167 expectedType: ldap.FilterExtensibleMatch, 168 }, 169 // attr+dn extension 170 compileTest{ 171 filterStr: `(o:dn:=Ace Industry)`, 172 expectedFilter: `(o:dn:=Ace Industry)`, 173 expectedType: ldap.FilterExtensibleMatch, 174 }, 175 // dn extension 176 compileTest{ 177 filterStr: `(:dn:2.4.6.8.10:=Dino)`, 178 expectedFilter: `(:dn:2.4.6.8.10:=Dino)`, 179 expectedType: ldap.FilterExtensibleMatch, 180 }, 181 compileTest{ 182 filterStr: `(memberOf:1.2.840.113556.1.4.1941:=CN=User1,OU=blah,DC=mydomain,DC=net)`, 183 expectedFilter: `(memberOf:1.2.840.113556.1.4.1941:=CN=User1,OU=blah,DC=mydomain,DC=net)`, 184 expectedType: ldap.FilterExtensibleMatch, 185 }, 186 187 // compileTest{ filterStr: "()", filterType: FilterExtensibleMatch }, 188} 189 190var testInvalidFilters = []string{ 191 `(objectGUID=\zz)`, 192 `(objectGUID=\a)`, 193} 194 195func TestFilter(t *testing.T) { 196 // Test Compiler and Decompiler 197 for _, i := range testFilters { 198 filter, err := ldap.CompileFilter(i.filterStr) 199 if err != nil { 200 if i.expectedErr == "" || !strings.Contains(err.Error(), i.expectedErr) { 201 t.Errorf("Problem compiling '%s' - '%v' (expected error to contain '%v')", i.filterStr, err, i.expectedErr) 202 } 203 } else if filter.Tag != ber.Tag(i.expectedType) { 204 t.Errorf("%q Expected %q got %q", i.filterStr, ldap.FilterMap[uint64(i.expectedType)], ldap.FilterMap[uint64(filter.Tag)]) 205 } else { 206 o, err := ldap.DecompileFilter(filter) 207 if err != nil { 208 t.Errorf("Problem compiling %s - %s", i.filterStr, err.Error()) 209 } else if i.expectedFilter != o { 210 t.Errorf("%q expected, got %q", i.expectedFilter, o) 211 } 212 } 213 } 214} 215 216func TestInvalidFilter(t *testing.T) { 217 for _, filterStr := range testInvalidFilters { 218 if _, err := ldap.CompileFilter(filterStr); err == nil { 219 t.Errorf("Problem compiling %s - expected err", filterStr) 220 } 221 } 222} 223 224func BenchmarkFilterCompile(b *testing.B) { 225 b.StopTimer() 226 filters := make([]string, len(testFilters)) 227 228 // Test Compiler and Decompiler 229 for idx, i := range testFilters { 230 filters[idx] = i.filterStr 231 } 232 233 maxIdx := len(filters) 234 b.StartTimer() 235 for i := 0; i < b.N; i++ { 236 ldap.CompileFilter(filters[i%maxIdx]) 237 } 238} 239 240func BenchmarkFilterDecompile(b *testing.B) { 241 b.StopTimer() 242 filters := make([]*ber.Packet, len(testFilters)) 243 244 // Test Compiler and Decompiler 245 for idx, i := range testFilters { 246 filters[idx], _ = ldap.CompileFilter(i.filterStr) 247 } 248 249 maxIdx := len(filters) 250 b.StartTimer() 251 for i := 0; i < b.N; i++ { 252 ldap.DecompileFilter(filters[i%maxIdx]) 253 } 254} 255