commit be2c81dc86d82cd1729ffc8c062e618d622fb40e Author: Dominic Grimm Date: Sat Feb 5 09:27:02 2022 +0100 init diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..163eb75 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*.cr] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0bbd4a9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +/docs/ +/lib/ +/bin/ +/.shards/ +*.dwarf + +# Libraries don't need dependency lock +# Dependencies will be locked in applications that use them +/shard.lock diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d380e85 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Dominic Grimm + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..17a595d --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +# ldap_escape + +Based on https://github.com/tcort/ldap-escape. + +## Installation + +1. Add the dependency to your `shard.yml`: + + ```yaml + dependencies: + ldap_escape: + github: your-github-user/ldap_escape + ``` + +2. Run `shards install` + +## Usage + +```crystal +require "ldap_escape" +``` + +TODO: Write usage instructions here + +## Development + +TODO: Write development instructions here + +## Contributing + +1. Fork it () +2. Create your feature branch (`git checkout -b my-new-feature`) +3. Commit your changes (`git commit -am 'Add some feature'`) +4. Push to the branch (`git push origin my-new-feature`) +5. Create a new Pull Request + +## Contributors + +- [Dominic Grimm](https://github.com/your-github-user) - creator and maintainer diff --git a/shard.yml b/shard.yml new file mode 100644 index 0000000..7557dfb --- /dev/null +++ b/shard.yml @@ -0,0 +1,13 @@ +name: ldap_escape +version: 0.1.0 + +authors: + - Dominic Grimm + +crystal: 1.3.2 + +license: MIT + +dependencies: + version_from_shard: + github: hugopl/version_from_shard diff --git a/spec/ldap_escape_spec.cr b/spec/ldap_escape_spec.cr new file mode 100644 index 0000000..5952787 --- /dev/null +++ b/spec/ldap_escape_spec.cr @@ -0,0 +1,15 @@ +require "./spec_helper" + +describe LdapEscape do + describe "#filter" do + it "filters out malicious filter characters" do + LdapEscape.filter("\u0000\u0028\u0029\u002a\u005c").should eq "\\00\\28\\29\\2a\\5c" + end + end + + describe "#dn" do + it "filters out malicious dn characters" do + LdapEscape.dn("\u0020\u0022\u0023\u002b\u002c\u003b\u003c\u003d\u003e\u005c").should eq "\\\\ \\\"\\#\\+\\,\\;\\<\\=\\>\\\\" + end + end +end diff --git a/spec/spec_helper.cr b/spec/spec_helper.cr new file mode 100644 index 0000000..eb65d91 --- /dev/null +++ b/spec/spec_helper.cr @@ -0,0 +1,2 @@ +require "spec" +require "../src/ldap_escape" diff --git a/src/ldap_escape.cr b/src/ldap_escape.cr new file mode 100644 index 0000000..024e038 --- /dev/null +++ b/src/ldap_escape.cr @@ -0,0 +1,46 @@ +module LdapEscape + extend self + + FILTER = { + "\u0000" => "\\00", # null + "\u0028" => "\\28", # ( + "\u0029" => "\\29", # ) + "\u002a" => "\\2a", # * + "\u005c" => "\\5c", # \ + } + FILTER_REGEX = /(\0|\x28|\x29|\x2a|\x5c)/ + + DN_BEGIN = { + "\u0020" => "\\ ", # space + } + DN_BEGIN_REGEX = /^(\x20)/ + + DN = { + "\u0022" => "\\\"", # " + "\u0023" => "\\#", # # + "\u002b" => "\\+", # + + "\u002c" => "\\,", # , + "\u003b" => "\\;", # ; + "\u003c" => "\\<", # < + "\u003d" => "\\=", # = + "\u003e" => "\\>", # > + "\u005c" => "\\\\", # \ + } + DN_REGEX = /(\x22|\x23|\x2b|\x2c|\x3b|\x3c|\x3d|\x3e|\x5c)/ + + DN_END = { + '\u0020' => "\\ ", # space + } + DN_END_REGEX = /(\x20)$/ + + def filter(input : String) : String + input.gsub(FILTER_REGEX) { |match| FILTER[match] } + end + + def dn(input : String) : String + input + .gsub(DN_BEGIN_REGEX) { |match| DN_BEGIN[match] } + .gsub(DN_REGEX) { |match| DN[match] } + .gsub(DN_END_REGEX) { |match| DN_END[match] } + end +end diff --git a/src/ldap_escape/version.cr b/src/ldap_escape/version.cr new file mode 100644 index 0000000..46f4158 --- /dev/null +++ b/src/ldap_escape/version.cr @@ -0,0 +1,5 @@ +require "version_from_shard" + +module LdapEscape + VersionFromShard.declare +end diff --git a/test.cr b/test.cr new file mode 100644 index 0000000..324ff3e --- /dev/null +++ b/test.cr @@ -0,0 +1,3 @@ +require "./src/ldap_escape" + +p! LdapEscape.dn("\u0020\u0022\u0023\u002b\u002c\u003b\u003c\u003d\u003e\u005c")