diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..7cc5019d --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,31 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake +# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby + +name: Test + +on: + pull_request: + push: + branches: + - master + +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + ruby: + - "3.0" + - "3.1" + - "3.2" + - "3.3" + - "jruby-9.4" + - "truffleruby" + steps: + - uses: actions/checkout@v2 + - name: Run tests with Ruby ${{ matrix.ruby }} + run: docker compose run ci-${{ matrix.ruby }} diff --git a/.gitignore b/.gitignore index 9c2842d9..e7d58b8f 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ publish/ Gemfile.lock .bundle bin/ +.idea +*.gem diff --git a/.rubocop.yml b/.rubocop.yml index 7bdfa631..b2f78bb0 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -4,7 +4,7 @@ AllCops: Exclude: - 'pkg/**/*' -Style/ExtraSpacing: +Layout/ExtraSpacing: Enabled: false Lint/AssignmentInCondition: @@ -13,7 +13,7 @@ Lint/AssignmentInCondition: Style/ParallelAssignment: Enabled: false -Style/TrailingCommaInLiteral: +Style/TrailingCommaInArrayLiteral: EnforcedStyleForMultiline: comma Style/TrailingCommaInArguments: diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 50c86e74..426a2aed 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,19 +1,231 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2016-08-17 14:58:12 -0700 using RuboCop version 0.42.0. +# on 2023-03-29 17:13:45 UTC using RuboCop version 1.48.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. # Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: AlignWith, SupportedStyles, AutoCorrect. -# SupportedStyles: keyword, variable, start_of_line -Lint/EndAlignment: +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include. +# Include: **/*.gemspec +Gemspec/OrderedDependencies: + Exclude: + - 'net-ldap.gemspec' + +# Offense count: 1 +# Configuration parameters: Severity, Include. +# Include: **/*.gemspec +Gemspec/RequiredRubyVersion: + Exclude: + - 'net-ldap.gemspec' + +# Offense count: 3 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: with_first_element, with_fixed_indentation +Layout/ArrayAlignment: + Exclude: + - 'lib/net/ldap.rb' + - 'lib/net/ldap/connection.rb' + +# Offense count: 4 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, IndentOneStep, IndentationWidth. +# SupportedStyles: case, end +Layout/CaseIndentation: + Exclude: + - 'lib/net/ldap/filter.rb' + +# Offense count: 24 +# This cop supports safe autocorrection (--autocorrect). +Layout/EmptyLineAfterGuardClause: + Exclude: + - 'lib/net/ber.rb' + - 'lib/net/ber/core_ext/array.rb' + - 'lib/net/ldap.rb' + - 'lib/net/ldap/auth_adapter.rb' + - 'lib/net/ldap/connection.rb' + - 'lib/net/ldap/dataset.rb' + - 'lib/net/ldap/entry.rb' + - 'lib/net/ldap/filter.rb' + - 'lib/net/snmp.rb' + - 'test/integration/test_ber.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +Layout/EmptyLineAfterMagicComment: + Exclude: + - 'net-ldap.gemspec' + +# Offense count: 6 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EmptyLineBetweenMethodDefs, EmptyLineBetweenClassDefs, EmptyLineBetweenModuleDefs, AllowAdjacentOneLineDefs, NumberOfEmptyLines. +Layout/EmptyLineBetweenDefs: + Exclude: + - 'lib/net/ldap/dataset.rb' + - 'lib/net/ldap/error.rb' + - 'lib/net/snmp.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +Layout/EmptyLines: + Exclude: + - 'lib/net/snmp.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowAliasSyntax, AllowedMethods. +# AllowedMethods: alias_method, public, protected, private +Layout/EmptyLinesAroundAttributeAccessor: + Exclude: + - 'lib/net/ber.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines, beginning_only, ending_only +Layout/EmptyLinesAroundClassBody: + Exclude: + - 'lib/net/ldap.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +Layout/EmptyLinesAroundExceptionHandlingKeywords: + Exclude: + - 'lib/net/ldap/connection.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyleAlignWith, Severity. +# SupportedStylesAlignWith: keyword, variable, start_of_line +Layout/EndAlignment: Exclude: - 'testserver/ldapserver.rb' +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: IndentationWidth. +# SupportedStyles: special_inside_parentheses, consistent, align_brackets +Layout/FirstArrayElementIndentation: + EnforcedStyle: consistent + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: IndentationWidth. +# SupportedStyles: special_inside_parentheses, consistent, align_braces +Layout/FirstHashElementIndentation: + EnforcedStyle: consistent + +# Offense count: 124 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle. +# SupportedHashRocketStyles: key, separator, table +# SupportedColonStyles: key, separator, table +# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit +Layout/HashAlignment: + Exclude: + - 'lib/net/ber.rb' + - 'lib/net/ldap.rb' + - 'lib/net/ldap/auth_adapter/gss_spnego.rb' + - 'lib/net/ldap/connection.rb' + - 'lib/net/ldap/filter.rb' + - 'test/ber/test_ber.rb' + - 'test/integration/test_add.rb' + - 'test/integration/test_bind.rb' + - 'test/integration/test_delete.rb' + - 'test/integration/test_open.rb' + - 'test/test_helper.rb' + - 'test/test_ldap_connection.rb' + +# Offense count: 6 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: Width, AllowedPatterns. +Layout/IndentationWidth: + Exclude: + - 'lib/net/ber.rb' + - 'lib/net/ldap/password.rb' + - 'lib/net/snmp.rb' + +# Offense count: 15 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowDoxygenCommentStyle, AllowGemfileRubyComment. +Layout/LeadingCommentSpace: + Exclude: + - 'lib/net/ber/core_ext/array.rb' + - 'lib/net/ldap.rb' + - 'lib/net/ldap/connection.rb' + - 'lib/net/ldap/entry.rb' + - 'lib/net/ldap/filter.rb' + - 'lib/net/ldap/pdu.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: symmetrical, new_line, same_line +Layout/MultilineMethodCallBraceLayout: + Exclude: + - 'lib/net/ldap/filter.rb' + +# Offense count: 7 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: space, no_space +Layout/SpaceAroundEqualsInParameterDefault: + Exclude: + - 'lib/net/ldap/connection.rb' + - 'lib/net/snmp.rb' + +# Offense count: 4 +# This cop supports safe autocorrection (--autocorrect). +Layout/SpaceAroundKeyword: + Exclude: + - 'lib/net/ldap/entry.rb' + - 'lib/net/snmp.rb' + +# Offense count: 7 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowForAlignment, EnforcedStyleForExponentOperator. +# SupportedStylesForExponentOperator: space, no_space +Layout/SpaceAroundOperators: + Exclude: + - 'lib/net/ber/ber_parser.rb' + - 'lib/net/ldap/connection.rb' + - 'lib/net/ldap/entry.rb' + - 'lib/net/ldap/filter.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters. +# SupportedStyles: space, no_space +# SupportedStylesForEmptyBraces: space, no_space +Layout/SpaceInsideBlockBraces: + Exclude: + - 'lib/net/ldap/dataset.rb' + +# Offense count: 8 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: space, compact, no_space +Layout/SpaceInsideParens: + Exclude: + - 'lib/net/ldap/entry.rb' + - 'lib/net/snmp.rb' + +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: AllowComments. +Lint/EmptyConditionalBody: + Exclude: + - 'lib/net/ldap/filter.rb' + +# Offense count: 1 +# Configuration parameters: AllowComments. +Lint/EmptyWhen: + Exclude: + - 'lib/net/ldap/pdu.rb' + # Offense count: 30 Lint/ImplicitStringConcatenation: Exclude: @@ -29,23 +241,17 @@ Lint/RescueException: Exclude: - 'lib/net/ldap/pdu.rb' -# Offense count: 1 -Lint/ShadowingOuterLocalVariable: - Exclude: - - 'lib/net/ldap/instrumentation.rb' - -# Offense count: 10 -# Cop supports --auto-correct. +# Offense count: 9 +# This cop supports safe autocorrection (--autocorrect). # Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments. Lint/UnusedBlockArgument: Exclude: - 'lib/net/ldap.rb' - 'lib/net/snmp.rb' - - 'test/support/vm/openldap/Vagrantfile' # Offense count: 7 -# Cop supports --auto-correct. -# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods. +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods. Lint/UnusedMethodArgument: Exclude: - 'lib/net/ldap/entry.rb' @@ -55,207 +261,224 @@ Lint/UnusedMethodArgument: - 'test/test_search.rb' # Offense count: 1 -# Configuration parameters: ContextCreatingMethods. +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: ContextCreatingMethods, MethodCreatingMethods. Lint/UselessAccessModifier: Exclude: - 'lib/net/ldap/connection.rb' -# Offense count: 9 +# Offense count: 5 Lint/UselessAssignment: Exclude: - - 'lib/net/ldap/connection.rb' - - 'lib/net/ldap/password.rb' - 'test/integration/test_add.rb' - 'test/test_ldap_connection.rb' - 'test/test_search.rb' - - 'test/test_snmp.rb' -# Offense count: 47 +# Offense count: 38 +# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. Metrics/AbcSize: - Max: 114 + Max: 124 + +# Offense count: 3 +# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. +# AllowedMethods: refine +Metrics/BlockLength: + Max: 119 # Offense count: 11 +# Configuration parameters: CountBlocks. Metrics/BlockNesting: Max: 4 -# Offense count: 10 -# Configuration parameters: CountComments. +# Offense count: 11 +# Configuration parameters: CountComments, CountAsOne. Metrics/ClassLength: - Max: 431 + Max: 451 -# Offense count: 22 +# Offense count: 20 +# Configuration parameters: AllowedMethods, AllowedPatterns. Metrics/CyclomaticComplexity: - Max: 41 + Max: 45 -# Offense count: 225 -# Configuration parameters: AllowHeredoc, AllowURI, URISchemes. -# URISchemes: http, https -Metrics/LineLength: - Max: 360 - -# Offense count: 70 -# Configuration parameters: CountComments. +# Offense count: 74 +# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. Metrics/MethodLength: Max: 130 # Offense count: 1 -# Configuration parameters: CountComments. +# Configuration parameters: CountComments, CountAsOne. Metrics/ModuleLength: - Max: 104 + Max: 103 -# Offense count: 14 +# Offense count: 12 +# Configuration parameters: AllowedMethods, AllowedPatterns. Metrics/PerceivedComplexity: - Max: 37 + Max: 46 # Offense count: 1 -Style/AccessorMethodName: +Naming/AccessorMethodName: Exclude: - 'lib/net/ldap.rb' -# Offense count: 10 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: prefer_alias, prefer_alias_method -Style/Alias: +# Offense count: 3 +# This cop supports safe autocorrection (--autocorrect). +Naming/BinaryOperatorParameterName: + Exclude: + - 'lib/net/ldap/filter.rb' + +# Offense count: 1 +# Configuration parameters: AllowedNames. +# AllowedNames: module_parent +Naming/ClassAndModuleCamelCase: + Exclude: + - 'lib/net/ldap/auth_adapter/gss_spnego.rb' + +# Offense count: 87 +Naming/ConstantName: + Exclude: + - 'lib/net/ldap.rb' + - 'lib/net/ldap/connection.rb' + - 'lib/net/ldap/filter.rb' + - 'lib/net/ldap/pdu.rb' + - 'lib/net/snmp.rb' + - 'test/test_ldif.rb' + - 'testserver/ldapserver.rb' + +# Offense count: 1 +# Configuration parameters: ExpectMatchingDefinition, CheckDefinitionPathHierarchy, CheckDefinitionPathHierarchyRoots, Regex, IgnoreExecutableScripts, AllowedAcronyms. +# CheckDefinitionPathHierarchyRoots: lib, spec, test, src +# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS +Naming/FileName: + Exclude: + - 'lib/net-ldap.rb' + +# Offense count: 11 +# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames. +# AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to +Naming/MethodParameterName: Exclude: - - 'lib/net/ber/core_ext/array.rb' - 'lib/net/ldap.rb' - 'lib/net/ldap/entry.rb' - 'lib/net/ldap/filter.rb' + - 'lib/net/snmp.rb' + - 'test/test_snmp.rb' + - 'testserver/ldapserver.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: PreferredName. +Naming/RescuedExceptionsVariableName: + Exclude: - 'lib/net/ldap/pdu.rb' -# Offense count: 4 -# Cop supports --auto-correct. -Style/AlignArray: +# Offense count: 9 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: separated, grouped +Style/AccessorGrouping: Exclude: - 'lib/net/ldap.rb' - - 'lib/net/ldap/auth_adapter/sasl.rb' - - 'lib/net/ldap/connection.rb' + - 'lib/net/ldap/pdu.rb' # Offense count: 10 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth. -# SupportedStyles: with_first_parameter, with_fixed_indentation -Style/AlignParameters: +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: prefer_alias, prefer_alias_method +Style/Alias: Exclude: - - 'test/ber/test_ber.rb' - - 'test/integration/test_ber.rb' - - 'test/integration/test_bind.rb' - - 'test/integration/test_password_modify.rb' + - 'lib/net/ber/core_ext/array.rb' + - 'lib/net/ldap.rb' + - 'lib/net/ldap/entry.rb' + - 'lib/net/ldap/filter.rb' + - 'lib/net/ldap/pdu.rb' -# Offense count: 37 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. +# Offense count: 12 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle. # SupportedStyles: always, conditionals Style/AndOr: Exclude: - - 'lib/net/ber/ber_parser.rb' - 'lib/net/ldap.rb' - 'lib/net/ldap/connection.rb' - 'lib/net/ldap/dataset.rb' - 'lib/net/ldap/filter.rb' - 'lib/net/ldap/pdu.rb' - - 'testserver/ldapserver.rb' # Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. # SupportedStyles: percent_q, bare_percent Style/BarePercentLiterals: Exclude: - 'test/test_entry.rb' # Offense count: 1 -# Cop supports --auto-correct. +# This cop supports safe autocorrection (--autocorrect). Style/BlockComments: Exclude: - 'test/test_rename.rb' -# Offense count: 6 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: braces, no_braces, context_dependent -Style/BracesAroundHashParameters: - Exclude: - - 'lib/net/ldap/auth_adapter/gss_spnego.rb' - - 'lib/net/snmp.rb' - - 'test/test_ldap.rb' - -# Offense count: 4 -# Cop supports --auto-correct. -# Configuration parameters: IndentWhenRelativeTo, SupportedStyles, IndentOneStep, IndentationWidth. -# SupportedStyles: case, end -Style/CaseIndentation: +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: MinBranchesCount. +Style/CaseLikeIf: Exclude: - - 'lib/net/ldap/filter.rb' + - 'lib/net/ber/ber_parser.rb' # Offense count: 4 -# Cop supports --auto-correct. +# This cop supports safe autocorrection (--autocorrect). Style/CharacterLiteral: Exclude: - 'lib/net/ldap/dataset.rb' - 'lib/net/ldap/entry.rb' -# Offense count: 1 -Style/ClassAndModuleCamelCase: - Exclude: - - 'lib/net/ldap/auth_adapter/gss_spnego.rb' - # Offense count: 23 -# Configuration parameters: EnforcedStyle, SupportedStyles. +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle. # SupportedStyles: nested, compact Style/ClassAndModuleChildren: Enabled: false -# Offense count: 2 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. # SupportedStyles: is_a?, kind_of? Style/ClassCheck: Exclude: - 'lib/net/ber/core_ext/array.rb' - - 'lib/net/ldap/error.rb' - -# Offense count: 13 -# Cop supports --auto-correct. -Style/ColonMethodCall: - Exclude: - - 'test/test_ldif.rb' - - 'test/test_ssl_ber.rb' # Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: Keywords. -# Keywords: TODO, FIXME, OPTIMIZE, HACK, REVIEW +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: Keywords, RequireColon. +# Keywords: TODO, FIXME, OPTIMIZE, HACK, REVIEW, NOTE Style/CommentAnnotation: Exclude: - 'lib/net/ber.rb' -# Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles, SingleLineConditionsOnly. -# SupportedStyles: assign_to_condition, assign_inside_condition -Style/ConditionalAssignment: - Exclude: - - 'lib/net/ldap/dn.rb' - -# Offense count: 88 -Style/ConstantName: +# Offense count: 8 +# This cop supports unsafe autocorrection (--autocorrect-all). +Style/CommentedKeyword: Exclude: - 'lib/net/ldap.rb' - 'lib/net/ldap/connection.rb' + - 'lib/net/ldap/entry.rb' - 'lib/net/ldap/filter.rb' - 'lib/net/ldap/pdu.rb' - - 'lib/net/snmp.rb' - - 'test/test_ldif.rb' - - 'testserver/ldapserver.rb' -# Offense count: 17 +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, SingleLineConditionsOnly, IncludeTernaryExpressions. +# SupportedStyles: assign_to_condition, assign_inside_condition +Style/ConditionalAssignment: + Exclude: + - 'lib/net/ldap/dn.rb' + +# Offense count: 12 +# Configuration parameters: AllowedConstants. Style/Documentation: Exclude: - 'spec/**/*' - 'test/**/*' - - 'lib/net/ber/core_ext.rb' - 'lib/net/ldap.rb' - 'lib/net/ldap/auth_adapter.rb' - 'lib/net/ldap/auth_adapter/sasl.rb' @@ -268,65 +491,46 @@ Style/Documentation: - 'lib/net/snmp.rb' - 'testserver/ldapserver.rb' -# Offense count: 19 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: leading, trailing -Style/DotPosition: - Exclude: - - 'test/test_ldap_connection.rb' - - 'test/test_ssl_ber.rb' - # Offense count: 1 -# Cop supports --auto-correct. -Style/ElseAlignment: - Exclude: - - 'testserver/ldapserver.rb' - -# Offense count: 5 -# Cop supports --auto-correct. -# Configuration parameters: AllowAdjacentOneLineDefs. -Style/EmptyLineBetweenDefs: - Exclude: - - 'lib/net/ldap.rb' - - 'lib/net/ldap/dataset.rb' - - 'lib/net/snmp.rb' - -# Offense count: 8 -# Cop supports --auto-correct. -Style/EmptyLines: - Exclude: - - 'lib/net/snmp.rb' - - 'testserver/ldapserver.rb' - -# Offense count: 2 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: empty_lines, no_empty_lines -Style/EmptyLinesAroundClassBody: +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: compact, expanded +Style/EmptyMethod: Exclude: - - 'lib/net/ldap.rb' - - 'test/test_snmp.rb' + - 'test/test_auth_adapter.rb' # Offense count: 2 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: empty_lines, no_empty_lines -Style/EmptyLinesAroundModuleBody: +# This cop supports safe autocorrection (--autocorrect). +Style/Encoding: Exclude: - - 'testserver/ldapserver.rb' + - 'net-ldap.gemspec' + - 'test/test_filter_parser.rb' # Offense count: 3 -# Cop supports --auto-correct. +# This cop supports safe autocorrection (--autocorrect). Style/EvenOdd: Exclude: - 'lib/net/ldap/dn.rb' # Offense count: 1 -# Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts. -Style/FileName: +# This cop supports safe autocorrection (--autocorrect). +Style/ExpandPathArguments: Exclude: - - 'lib/net-ldap.rb' + - 'net-ldap.gemspec' + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +Style/ExplicitBlockArgument: + Exclude: + - 'lib/net/ldap.rb' + - 'lib/net/ldap/dataset.rb' + +# Offense count: 54 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: always, always_true, never +Style/FrozenStringLiteralComment: + Enabled: false # Offense count: 9 # Configuration parameters: AllowedVariables. @@ -334,10 +538,18 @@ Style/GlobalVars: Exclude: - 'testserver/ldapserver.rb' -# Offense count: 161 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols. -# SupportedStyles: ruby19, ruby19_no_mixed_keys, hash_rockets +# Offense count: 5 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: MinBodyLength, AllowConsecutiveConditionals. +Style/GuardClause: + Exclude: + - 'lib/net/ldap/filter.rb' + +# Offense count: 159 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, EnforcedShorthandSyntax, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols. +# SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys +# SupportedShorthandSyntax: always, never, either, consistent Style/HashSyntax: Exclude: - 'lib/net/ber.rb' @@ -347,7 +559,6 @@ Style/HashSyntax: - 'lib/net/ldap/connection.rb' - 'lib/net/ldap/pdu.rb' - 'lib/net/snmp.rb' - - 'test/integration/test_bind.rb' - 'test/test_auth_adapter.rb' - 'test/test_ldap.rb' - 'test/test_ldap_connection.rb' @@ -356,58 +567,31 @@ Style/HashSyntax: - 'testserver/ldapserver.rb' # Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowIfModifier. Style/IfInsideElse: Exclude: - 'lib/net/ldap/instrumentation.rb' -# Offense count: 7 -# Cop supports --auto-correct. -# Configuration parameters: MaxLineLength. +# Offense count: 25 +# This cop supports safe autocorrection (--autocorrect). Style/IfUnlessModifier: Exclude: - 'lib/net/ber.rb' - 'lib/net/ber/core_ext/integer.rb' - 'lib/net/ldap.rb' + - 'lib/net/ldap/auth_adapter.rb' + - 'lib/net/ldap/auth_adapter/sasl.rb' + - 'lib/net/ldap/auth_adapter/simple.rb' + - 'lib/net/ldap/connection.rb' - 'lib/net/ldap/filter.rb' - 'lib/net/snmp.rb' - - 'test/test_ldap_connection.rb' - -# Offense count: 2 -# Cop supports --auto-correct. -# Configuration parameters: SupportedStyles, IndentationWidth. -# SupportedStyles: special_inside_parentheses, consistent, align_brackets -Style/IndentArray: - EnforcedStyle: consistent - -# Offense count: 2 -# Cop supports --auto-correct. -# Configuration parameters: SupportedStyles, IndentationWidth. -# SupportedStyles: special_inside_parentheses, consistent, align_braces -Style/IndentHash: - EnforcedStyle: consistent - -# Offense count: 10 -# Cop supports --auto-correct. -# Configuration parameters: Width. -Style/IndentationWidth: - Exclude: - - 'lib/net/ber.rb' - - 'lib/net/ldap/password.rb' - - 'lib/net/snmp.rb' - - 'test/test_snmp.rb' - - 'testserver/ldapserver.rb' - -# Offense count: 3 -# Cop supports --auto-correct. -Style/LeadingCommentSpace: - Exclude: - - 'lib/net/ber/core_ext/array.rb' - - 'lib/net/ldap.rb' - - 'lib/net/ldap/connection.rb' + - 'test/integration/test_delete.rb' + - 'test/integration/test_password_modify.rb' # Offense count: 21 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. # SupportedStyles: require_parentheses, require_no_parentheses, require_no_parentheses_except_multiline Style/MethodDefParentheses: Exclude: @@ -417,43 +601,27 @@ Style/MethodDefParentheses: - 'testserver/ldapserver.rb' # Offense count: 2 -Style/MethodMissing: +Style/MissingRespondToMissing: Exclude: - 'lib/net/ldap/dn.rb' - 'lib/net/ldap/entry.rb' -# Offense count: 1 -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: snake_case, camelCase -Style/MethodName: - Exclude: - - 'lib/net/ldap/filter.rb' - -# Offense count: 4 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: symmetrical, new_line, same_line -Style/MultilineMethodCallBraceLayout: - Exclude: - - 'lib/net/ldap/filter.rb' - - 'test/test_entry.rb' - - 'test/test_ldap_connection.rb' - -# Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth. -# SupportedStyles: aligned, indented, indented_relative_to_receiver -Style/MultilineMethodCallIndentation: - Exclude: - - 'test/test_ldap_connection.rb' - -# Offense count: 1 -Style/MultilineTernaryOperator: +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +Style/MultilineIfModifier: Exclude: - 'lib/net/ldap/connection.rb' # Offense count: 26 -# Cop supports --auto-correct. +# This cop supports safe autocorrection (--autocorrect). +Style/MultilineWhenThen: + Exclude: + - 'lib/net/ldap/dn.rb' + +# Offense count: 25 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: literals, strict Style/MutableConstant: Exclude: - 'lib/net/ber.rb' @@ -463,25 +631,26 @@ Style/MutableConstant: - 'lib/net/ldap/filter.rb' - 'lib/net/ldap/version.rb' - 'lib/net/snmp.rb' - - 'test/support/vm/openldap/Vagrantfile' - 'test/test_ldif.rb' - 'testserver/ldapserver.rb' # Offense count: 1 -# Cop supports --auto-correct. +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: both, prefix, postfix Style/NegatedIf: Exclude: - 'test/test_helper.rb' # Offense count: 1 -# Cop supports --auto-correct. +# This cop supports safe autocorrection (--autocorrect). Style/NegatedWhile: Exclude: - 'lib/net/ldap/filter.rb' # Offense count: 3 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, MinBodyLength, SupportedStyles. +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, MinBodyLength. # SupportedStyles: skip_modifier_ifs, always Style/Next: Exclude: @@ -489,47 +658,55 @@ Style/Next: - 'testserver/ldapserver.rb' # Offense count: 1 -# Cop supports --auto-correct. +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: predicate, comparison Style/NilComparison: Exclude: - 'lib/net/ldap/connection.rb' # Offense count: 1 -# Cop supports --auto-correct. +# This cop supports safe autocorrection (--autocorrect). # Configuration parameters: IncludeSemanticChanges. Style/NonNilCheck: Exclude: - 'lib/net/ber/ber_parser.rb' # Offense count: 1 -# Cop supports --auto-correct. +# This cop supports safe autocorrection (--autocorrect). Style/Not: Exclude: - 'lib/net/ldap/filter.rb' # Offense count: 11 -# Cop supports --auto-correct. +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: Strict, AllowedNumbers, AllowedPatterns. Style/NumericLiterals: MinDigits: 8 -# Offense count: 4 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. +# Offense count: 14 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle, AllowedMethods, AllowedPatterns. # SupportedStyles: predicate, comparison Style/NumericPredicate: Exclude: + - 'spec/**/*' - 'lib/net/ber/core_ext/integer.rb' + - 'lib/net/ldap/connection.rb' - 'lib/net/ldap/dn.rb' + - 'lib/net/ldap/filter.rb' - 'testserver/ldapserver.rb' -# Offense count: 3 -Style/OpMethod: +# Offense count: 1 +# Configuration parameters: AllowedMethods. +# AllowedMethods: respond_to_missing? +Style/OptionalBooleanParameter: Exclude: - - 'lib/net/ldap/filter.rb' + - 'lib/net/ldap/entry.rb' # Offense count: 6 -# Cop supports --auto-correct. -# Configuration parameters: AllowSafeAssignment. +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowSafeAssignment, AllowInMultilineConditions. Style/ParenthesesAroundCondition: Exclude: - 'lib/net/ldap.rb' @@ -537,25 +714,31 @@ Style/ParenthesesAroundCondition: - 'lib/net/ldap/auth_adapter/sasl.rb' - 'lib/net/ldap/auth_adapter/simple.rb' -# Offense count: 3 -# Cop supports --auto-correct. +# Offense count: 13 +# This cop supports safe autocorrection (--autocorrect). # Configuration parameters: PreferredDelimiters. Style/PercentLiteralDelimiters: Exclude: - 'net-ldap.gemspec' + - 'test/integration/test_add.rb' + - 'test/integration/test_delete.rb' + - 'test/integration/test_open.rb' + - 'test/integration/test_password_modify.rb' - 'test/test_entry.rb' + - 'test/test_helper.rb' -# Offense count: 11 -# Cop supports --auto-correct. +# Offense count: 20 +# This cop supports safe autocorrection (--autocorrect). Style/PerlBackrefs: Exclude: - 'lib/net/ldap/dataset.rb' - 'lib/net/ldap/filter.rb' + - 'test/test_ldif.rb' - 'testserver/ldapserver.rb' # Offense count: 10 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, AllowedCompactTypes. # SupportedStyles: compact, exploded Style/RaiseArgs: Exclude: @@ -563,31 +746,55 @@ Style/RaiseArgs: - 'lib/net/ldap/pdu.rb' - 'lib/net/snmp.rb' -# Offense count: 1 -# Cop supports --auto-correct. +# Offense count: 3 +# This cop supports safe autocorrection (--autocorrect). Style/RedundantBegin: Exclude: + - 'lib/net/ldap.rb' + - 'lib/net/ldap/connection.rb' - 'lib/net/snmp.rb' # Offense count: 4 -# Cop supports --auto-correct. +# This cop supports safe autocorrection (--autocorrect). Style/RedundantParentheses: Exclude: - 'lib/net/ldap/filter.rb' - 'test/test_filter.rb' -# Offense count: 4 -# Cop supports --auto-correct. +# Offense count: 5 +# This cop supports safe autocorrection (--autocorrect). +Style/RedundantPercentQ: + Exclude: + - 'net-ldap.gemspec' + - 'test/test_entry.rb' + +# Offense count: 11 +# This cop supports safe autocorrection (--autocorrect). +Style/RedundantRegexpCharacterClass: + Exclude: + - 'lib/net/ber/core_ext/integer.rb' + - 'lib/net/ldap/dataset.rb' + - 'lib/net/ldap/filter.rb' + - 'testserver/ldapserver.rb' + +# Offense count: 5 +# This cop supports safe autocorrection (--autocorrect). +Style/RedundantRegexpEscape: + Exclude: + - 'lib/net/ldap/dataset.rb' + - 'lib/net/ldap/filter.rb' + +# Offense count: 3 +# This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowMultipleReturnValues. Style/RedundantReturn: Exclude: - 'lib/net/ber/core_ext/string.rb' - 'lib/net/ldap/auth_adapter.rb' - 'lib/net/ldap/entry.rb' - - 'lib/net/ldap/password.rb' # Offense count: 8 -# Cop supports --auto-correct. +# This cop supports safe autocorrection (--autocorrect). Style/RedundantSelf: Exclude: - 'lib/net/ber/core_ext/array.rb' @@ -596,8 +803,8 @@ Style/RedundantSelf: - 'lib/net/ldap/filter.rb' # Offense count: 2 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles, AllowInnerSlashes. +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, AllowInnerSlashes. # SupportedStyles: slashes, percent_r, mixed Style/RegexpLiteral: Exclude: @@ -605,149 +812,152 @@ Style/RegexpLiteral: - 'net-ldap.gemspec' # Offense count: 1 -# Cop supports --auto-correct. +# This cop supports safe autocorrection (--autocorrect). Style/RescueModifier: Exclude: - 'test/ber/core_ext/test_string.rb' -# Offense count: 8 -# Cop supports --auto-correct. -# Configuration parameters: AllowAsExpressionSeparator. -Style/Semicolon: - Exclude: - - 'lib/net/ldap/dn.rb' - - 'lib/net/ldap/error.rb' - - 'testserver/ldapserver.rb' - # Offense count: 2 -# Configuration parameters: Methods. -# Methods: {"reduce"=>["a", "e"]}, {"inject"=>["a", "e"]} -Style/SingleLineBlockParams: - Exclude: - - 'lib/net/ldap/filter.rb' - -# Offense count: 5 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: space, no_space -Style/SpaceAroundEqualsInParameterDefault: - Exclude: - - 'lib/net/ldap/connection.rb' - - 'lib/net/snmp.rb' - -# Offense count: 4 -# Cop supports --auto-correct. -Style/SpaceAroundKeyword: +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: implicit, explicit +Style/RescueStandardError: Exclude: - - 'lib/net/ldap/entry.rb' - 'lib/net/snmp.rb' + - 'testserver/ldapserver.rb' -# Offense count: 9 -# Cop supports --auto-correct. -# Configuration parameters: AllowForAlignment. -Style/SpaceAroundOperators: +# Offense count: 13 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength. +# AllowedMethods: present?, blank?, presence, try, try! +Style/SafeNavigation: Exclude: - - 'lib/net/ber/ber_parser.rb' + - 'lib/net/ldap.rb' - 'lib/net/ldap/connection.rb' - - 'lib/net/ldap/entry.rb' - - 'lib/net/ldap/filter.rb' - - 'test/test_entry.rb' - - 'test/test_ldap_connection.rb' + - 'lib/net/ldap/dataset.rb' + - 'lib/net/ldap/pdu.rb' -# Offense count: 5 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters. -# SupportedStyles: space, no_space -Style/SpaceInsideBlockBraces: +# Offense count: 7 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowAsExpressionSeparator. +Style/Semicolon: Exclude: - - 'lib/net/ldap/dataset.rb' - - 'test/test_snmp.rb' + - 'lib/net/ldap/dn.rb' - 'testserver/ldapserver.rb' -# Offense count: 13 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SupportedStyles. -# SupportedStyles: space, no_space, compact -Style/SpaceInsideHashLiteralBraces: +# Offense count: 3 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowModifier. +Style/SoleNestedConditional: Exclude: - - 'lib/net/ldap/dataset.rb' - - 'test/test_ldap.rb' + - 'lib/net/ldap.rb' + - 'lib/net/ldap/connection.rb' -# Offense count: 20 -# Cop supports --auto-correct. -Style/SpaceInsideParens: +# Offense count: 4 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: RequireEnglish, EnforcedStyle. +# SupportedStyles: use_perl_names, use_english_names, use_builtin_english_names +Style/SpecialGlobalVars: Exclude: - - 'lib/net/ldap/entry.rb' - 'lib/net/snmp.rb' - - 'test/test_password.rb' - 'testserver/ldapserver.rb' -# Offense count: 5 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: use_perl_names, use_english_names -Style/SpecialGlobalVars: +# Offense count: 15 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: Mode. +Style/StringConcatenation: Exclude: - - 'lib/net/snmp.rb' - - 'net-ldap.gemspec' - - 'testserver/ldapserver.rb' + - 'lib/net/ldap/dn.rb' + - 'lib/net/ldap/filter.rb' + - 'lib/net/ldap/password.rb' + - 'test/ber/test_ber.rb' + - 'test/test_ldif.rb' + - 'test/test_snmp.rb' -# Offense count: 679 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles, ConsistentQuotesInMultiline. +# Offense count: 683 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. # SupportedStyles: single_quotes, double_quotes Style/StringLiterals: Enabled: false # Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). Style/StructInheritance: Exclude: - 'test/test_ldap.rb' +# Offense count: 11 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: MinSize. +# SupportedStyles: percent, brackets +Style/SymbolArray: + EnforcedStyle: brackets + # Offense count: 4 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles, AllowSafeAssignment. -# SupportedStyles: require_parentheses, require_no_parentheses +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, AllowSafeAssignment. +# SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex Style/TernaryParentheses: Exclude: - 'lib/net/ber/core_ext/integer.rb' - 'lib/net/ldap/connection.rb' - 'lib/net/ldap/dataset.rb' +# Offense count: 38 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyleForMultiline. +# SupportedStylesForMultiline: comma, consistent_comma, no_comma +Style/TrailingCommaInHashLiteral: + Enabled: false + # Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: ExactNameMatch, AllowPredicates, AllowDSLWriters, IgnoreClassMethods, Whitelist. -# Whitelist: to_ary, to_a, to_c, to_enum, to_h, to_hash, to_i, to_int, to_io, to_open, to_path, to_proc, to_r, to_regexp, to_str, to_s, to_sym +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: ExactNameMatch, AllowPredicates, AllowDSLWriters, IgnoreClassMethods, AllowedMethods. +# AllowedMethods: to_ary, to_a, to_c, to_enum, to_h, to_hash, to_i, to_int, to_io, to_open, to_path, to_proc, to_r, to_regexp, to_str, to_s, to_sym Style/TrivialAccessors: Exclude: - 'lib/net/ldap/connection.rb' -# Offense count: 5 -# Cop supports --auto-correct. -Style/UnneededPercentQ: +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +Style/UnpackFirst: Exclude: - - 'net-ldap.gemspec' - - 'test/test_entry.rb' + - 'lib/net/ber/ber_parser.rb' # Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: MaxLineLength. +# This cop supports safe autocorrection (--autocorrect). Style/WhileUntilModifier: Exclude: - 'lib/net/ldap/filter.rb' # Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: SupportedStyles, WordRegex. +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: WordRegex. # SupportedStyles: percent, brackets Style/WordArray: EnforcedStyle: percent MinSize: 3 +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: forbid_for_all_comparison_operators, forbid_for_equality_operators_only, require_for_all_comparison_operators, require_for_equality_operators_only +Style/YodaCondition: + Exclude: + - 'lib/net/ber/ber_parser.rb' + # Offense count: 6 -# Cop supports --auto-correct. +# This cop supports unsafe autocorrection (--autocorrect-all). Style/ZeroLengthPredicate: Exclude: - 'lib/net/ldap/connection.rb' - 'lib/net/ldap/filter.rb' - 'testserver/ldapserver.rb' + +# Offense count: 24 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns. +# URISchemes: http, https +Layout/LineLength: + Max: 360 diff --git a/.travis.yml b/.travis.yml index fc764963..8956efb8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,20 +3,47 @@ rvm: - 2.0.0 - 2.1 - 2.2 + - 2.3 + - 2.4 + - 2.5 + - 2.6 + - 2.7 + - jruby-9.2 # optional - ruby-head - jruby-19mode + - jruby-9.2 - jruby-head - - rbx-2 + +addons: + hosts: + - ldap.example.org # needed for TLS verification + - cert.mismatch.example.org + +services: + - docker env: - INTEGRATION=openldap +cache: bundler + before_install: - gem update bundler install: - - if [ "$INTEGRATION" = "openldap" ]; then sudo script/install-openldap; fi + - > + docker run \ + --hostname ldap.example.org \ + --env LDAP_TLS_VERIFY_CLIENT=try \ + -p 389:389 \ + -p 636:636 \ + -v "$(pwd)"/test/fixtures/ldif:/container/service/slapd/assets/config/bootstrap/ldif/custom \ + --name openldap \ + --detach \ + osixia/openldap:1.3.0 \ + --copy-service \ + --loglevel debug \ - bundle install script: bundle exec rake ci @@ -25,8 +52,8 @@ matrix: allow_failures: - rvm: ruby-head - rvm: jruby-19mode + - rvm: jruby-9.2 - rvm: jruby-head - - rvm: rbx-2 fast_finish: true notifications: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0247a3d4..ee5335b7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -49,6 +49,6 @@ MyClass.new \ baz: 'garply' ``` -[issues]: https://github.com/ruby-net-ldap/ruby-net-ldap/issues +[issues]: https://github.com/ruby-ldap/ruby-net-ldap/issues [pr]: https://help.github.com/articles/using-pull-requests [travis]: https://travis-ci.org/ruby-ldap/ruby-net-ldap diff --git a/History.rdoc b/History.rdoc index 3fcc291b..3f6248ee 100644 --- a/History.rdoc +++ b/History.rdoc @@ -1,3 +1,69 @@ +=== Net::LDAP 0.19.0 +* Net::LDAP::DN - Retain trailing spaces in RDN values in DNs #412 +* Add in ability for users to specify LDAP controls when conducting searches #411 +* Document connect_timeout in Constructor Details #415 +* Fix openssl error when using multiple hosts #417 + +=== Net::LDAP 0.18.0 +* Fix escaping of # and space in attrs #408 +* Add support to use SNI #406 +* Drop Ruby 2.5 and JRuby 9.2 from CI tests +* Bump rubocop to 1.48.1 +* Update CI for TruffleRuby 22 + +=== Net::LDAP 0.17.1 +* Fixed shebang of bash #385 +* Omit some tests for now until we update our CA cert #386 +* Add Ruby 3.0 support #388 +* Add TruffleRuby 21.0.0 to CI #389 +* Correct a typo in an error message #391 +* Enable bundler caching for travis #390 +* Fix circular require while loading lib/net/ldap/entry.rb and lib/net/ldap/dataset.rb #392 +* Handle nil value in GetbyteForSSLSocket::getbyte #306 + +=== Net::LDAP 0.17.0 +* Added private recursive_delete as alternative to DELETE_TREE #268 +* Test suite updates #373 #376 #377 +* Use Base64.strict_encode64 and SSHA256 #303 +* Remove deprecated ConnectionRefusedError #366 +* Added method to get a duplicate of the internal Hash #286 +* remove a circular require #380 +* fix LdapServerAsnSyntax compile #379 +* Implement '==' operator for entries #381 +* fix for undefined method for write exception #383 + +=== Net::LDAP 0.16.3 + +* Add Net::LDAP::InvalidDNError #371 +* Use require_relative instead of require #360 +* Address some warnings and fix JRuby test omissions #365 +* Bump rake dev dependency to 12.3 #359 +* Enable rubocop in ci #251 +* Enhance rubocop configuration and test syntax #344 +* CI: Drop rbx-2, uninstallable #364 +* Fix RuboCop warnings #312 +* Fix wrong error class #305 +* CONTRIBUTING.md: Repair link to Issues #309 +* Make the generate() method more idiomatic... #326 +* Make encode_sort_controls() more idiomatic... #327 +* Make the instrument() method more idiomatic... #328 +* Fix uninitialised Net::LDAP::LdapPduError #338 +* README.rdoc: Use SVG build badge #310 +* Update TravisCI config to inclue Ruby 2.7 #346 +* add explicit ** to silence Ruby 2.7 warning #342 +* Support parsing filters with attribute tags #345 +* Bump rubocop development dependency version #336 +* Add link to generated and hosted documentation on rubydoc #319 +* Fix 'uninitialized constant Net::LDAP::PDU::LdapPduError' error #317 +* simplify encoding logic: no more chomping required #362 + +=== Net::LDAP 0.16.2 + +* Net::LDAP#open does not cache bind result {#334}[https://github.com/ruby-ldap/ruby-net-ldap/pull/334] +* Fix CI build {#333}[https://github.com/ruby-ldap/ruby-net-ldap/pull/333] +* Fix to "undefined method 'result_code'" {#308}[https://github.com/ruby-ldap/ruby-net-ldap/pull/308] +* Fixed Exception: incompatible character encodings: ASCII-8BIT and UTF-8 in filter.rb {#285}[https://github.com/ruby-ldap/ruby-net-ldap/pull/285] + === Net::LDAP 0.16.1 * Send DN and newPassword with password_modify request {#271}[https://github.com/ruby-ldap/ruby-net-ldap/pull/271] diff --git a/README.rdoc b/README.rdoc index f1b1ea36..88bdba61 100644 --- a/README.rdoc +++ b/README.rdoc @@ -1,4 +1,6 @@ -= Net::LDAP for Ruby {}[https://travis-ci.org/ruby-ldap/ruby-net-ldap] += Net::LDAP for Ruby +{Gem Version}[https://badge.fury.io/rb/net-ldap] +{}[https://travis-ci.org/ruby-ldap/ruby-net-ldap] == Description @@ -21,7 +23,7 @@ the most recent LDAP RFCs (4510–4519, plus portions of 4520–4532). == Synopsis -See Net::LDAP for documentation and usage samples. +See {Net::LDAP on rubydoc.info}[https://www.rubydoc.info/github/ruby-ldap/ruby-net-ldap/Net/LDAP] for documentation and usage samples. == Requirements @@ -53,16 +55,26 @@ This task will run the test suite and the rake rubotest CI takes too long? If your local box supports -{Vagrant}[https://www.vagrantup.com/], you can run most of the tests -in a VM on your local box. For more details and setup instructions, see -{test/support/vm/openldap/README.md}[https://github.com/ruby-ldap/ruby-net-ldap/tree/master/test/support/vm/openldap/README.md] +{Docker}[https://www.docker.com/], you can also run integration tests locally. +Simply run: + + script/ldap-docker + INTEGRATION=openldap rake test + +Or, use {Docker Compose}[https://docs.docker.com/compose/]. See docker-compose.yml for available Ruby versions. + + docker-compose run ci-2.7 + +CAVEAT: you need to add the following line to /etc/hosts + 127.0.0.1 ldap.example.org + 127.0.0.1 cert.mismatch.example.org == Release This section is for gem maintainers to cut a new version of the gem. * Check out a new branch `release-VERSION` -* Update lib/net/ldap/version.rb to next version number X.X.X following {semver}(http://semver.org/). +* Update lib/net/ldap/version.rb to next version number X.X.X following {semver}[http://semver.org/]. * Update `History.rdoc`. Get latest changes with `script/changelog` * Open a pull request with these changes for review * After merging, on the master branch, run `script/release` diff --git a/Rakefile b/Rakefile index 51ab55dc..da4cf8e7 100644 --- a/Rakefile +++ b/Rakefile @@ -15,7 +15,7 @@ Rake::TestTask.new do |t| end desc 'Run tests and RuboCop (RuboCop runs on mri only)' -task ci: [:test] +task ci: Bundler.current_ruby.mri? ? [:test, :rubocop] : [:test] desc 'Run tests and RuboCop' task rubotest: [:test, :rubocop] diff --git a/ci-run.sh b/ci-run.sh new file mode 100755 index 00000000..27024a77 --- /dev/null +++ b/ci-run.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +set -e + +gem install bundler +bundle check || bundle install +bundle exec rake ci diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..11f93ba2 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,122 @@ +networks: + integration_test_network: + +services: + openldap: + image: osixia/openldap:1.4.0 + networks: + integration_test_network: + aliases: + - ldap.example.org + - cert.mismatch.example.org + environment: + LDAP_TLS_VERIFY_CLIENT: "try" + LDAP_SEED_INTERNAL_LDIF_PATH: "/ldif" + healthcheck: + test: ["CMD", "ldapsearch", "-x", "-s", "base"] + interval: 60s + start_period: 30s + timeout: 5s + retries: 1 + hostname: "ldap.example.org" + volumes: + - ./test/fixtures/ldif:/ldif:ro + + ci-3.0: + image: ruby:3.0 + entrypoint: /code/ci-run.sh + environment: + INTEGRATION: openldap + INTEGRATION_HOST: ldap.example.org + depends_on: + - openldap + networks: + integration_test_network: + volumes: + - .:/code + working_dir: /code + + ci-3.1: + image: ruby:3.1 + entrypoint: /code/ci-run.sh + environment: + INTEGRATION: openldap + INTEGRATION_HOST: ldap.example.org + depends_on: + - openldap + networks: + integration_test_network: + volumes: + - .:/code + working_dir: /code + + ci-3.2: + image: ruby:3.2 + entrypoint: /code/ci-run.sh + environment: + INTEGRATION: openldap + INTEGRATION_HOST: ldap.example.org + depends_on: + - openldap + networks: + integration_test_network: + volumes: + - .:/code + working_dir: /code + + ci-3.3: + image: ruby:3.3 + entrypoint: /code/ci-run.sh + environment: + INTEGRATION: openldap + INTEGRATION_HOST: ldap.example.org + depends_on: + - openldap + networks: + integration_test_network: + volumes: + - .:/code + working_dir: /code + + # https://github.com/flavorjones/truffleruby/pkgs/container/truffleruby + ci-truffleruby: + image: ghcr.io/flavorjones/truffleruby:stable + entrypoint: /code/ci-run.sh + environment: + INTEGRATION: openldap + INTEGRATION_HOST: ldap.example.org + depends_on: + - openldap + networks: + integration_test_network: + volumes: + - .:/code + working_dir: /code + + ci-jruby-9.3: + image: jruby:9.3 + entrypoint: /code/ci-run.sh + environment: + INTEGRATION: openldap + INTEGRATION_HOST: ldap.example.org + depends_on: + - openldap + networks: + integration_test_network: + volumes: + - .:/code + working_dir: /code + + ci-jruby-9.4: + image: jruby:9.4 + entrypoint: /code/ci-run.sh + environment: + INTEGRATION: openldap + INTEGRATION_HOST: ldap.example.org + depends_on: + - openldap + networks: + integration_test_network: + volumes: + - .:/code + working_dir: /code diff --git a/lib/net-ldap.rb b/lib/net-ldap.rb index 879851eb..717878ca 100644 --- a/lib/net-ldap.rb +++ b/lib/net-ldap.rb @@ -1,2 +1,2 @@ # -*- ruby encoding: utf-8 -*- -require 'net/ldap' +require_relative 'net/ldap' diff --git a/lib/net/ber.rb b/lib/net/ber.rb index eb6f04b3..34696cc3 100644 --- a/lib/net/ber.rb +++ b/lib/net/ber.rb @@ -1,5 +1,5 @@ # -*- ruby encoding: utf-8 -*- -require 'net/ldap/version' +require_relative 'ldap/version' module Net # :nodoc: ## @@ -349,4 +349,4 @@ def to_ber Null = Net::BER::BerIdentifiedNull.new end -require 'net/ber/core_ext' +require_relative 'ber/core_ext' diff --git a/lib/net/ber/core_ext.rb b/lib/net/ber/core_ext.rb index b1939844..37e0993b 100644 --- a/lib/net/ber/core_ext.rb +++ b/lib/net/ber/core_ext.rb @@ -1,5 +1,5 @@ # -*- ruby encoding: utf-8 -*- -require 'net/ber/ber_parser' +require_relative 'ber_parser' # :stopdoc: class IO include Net::BER::BERParser @@ -19,35 +19,35 @@ class OpenSSL::SSL::SSLSocket module Net::BER::Extensions # :nodoc: end -require 'net/ber/core_ext/string' +require_relative 'core_ext/string' # :stopdoc: class String include Net::BER::BERParser include Net::BER::Extensions::String end -require 'net/ber/core_ext/array' +require_relative 'core_ext/array' # :stopdoc: class Array include Net::BER::Extensions::Array end # :startdoc: -require 'net/ber/core_ext/integer' +require_relative 'core_ext/integer' # :stopdoc: class Integer include Net::BER::Extensions::Integer end # :startdoc: -require 'net/ber/core_ext/true_class' +require_relative 'core_ext/true_class' # :stopdoc: class TrueClass include Net::BER::Extensions::TrueClass end # :startdoc: -require 'net/ber/core_ext/false_class' +require_relative 'core_ext/false_class' # :stopdoc: class FalseClass include Net::BER::Extensions::FalseClass diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index f7a98ef5..8dca73c0 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -17,19 +17,19 @@ class LDAP end require 'socket' -require 'net/ber' -require 'net/ldap/pdu' -require 'net/ldap/filter' -require 'net/ldap/dataset' -require 'net/ldap/password' -require 'net/ldap/entry' -require 'net/ldap/instrumentation' -require 'net/ldap/connection' -require 'net/ldap/version' -require 'net/ldap/error' -require 'net/ldap/auth_adapter' -require 'net/ldap/auth_adapter/simple' -require 'net/ldap/auth_adapter/sasl' +require_relative 'ber' +require_relative 'ldap/pdu' +require_relative 'ldap/filter' +require_relative 'ldap/dataset' +require_relative 'ldap/password' +require_relative 'ldap/entry' +require_relative 'ldap/instrumentation' +require_relative 'ldap/connection' +require_relative 'ldap/version' +require_relative 'ldap/error' +require_relative 'ldap/auth_adapter' +require_relative 'ldap/auth_adapter/simple' +require_relative 'ldap/auth_adapter/sasl' Net::LDAP::AuthAdapter.register([:simple, :anon, :anonymous], Net::LDAP::AuthAdapter::Simple) Net::LDAP::AuthAdapter.register(:sasl, Net::LDAP::AuthAdapter::Sasl) @@ -311,7 +311,7 @@ class Net::LDAP 0 => :array, # RFC-2251 Control and Filter-AND 1 => :array, # SearchFilter-OR 2 => :array, # SearchFilter-NOT - 3 => :array, # Seach referral + 3 => :array, # Search referral 4 => :array, # unknown use in Microsoft Outlook 5 => :array, # SearchFilter-GE 6 => :array, # SearchFilter-LE @@ -325,7 +325,7 @@ class Net::LDAP universal = { constructed: { - 107 => :array, #ExtendedResponse (PasswdModifyResponseValue) + 107 => :string, # ExtendedResponse }, } @@ -341,6 +341,7 @@ class Net::LDAP StartTlsOid = '1.3.6.1.4.1.1466.20037' PasswdModifyOid = '1.3.6.1.4.1.4203.1.11.1' + WhoamiOid = '1.3.6.1.4.1.4203.1.11.3' # https://tools.ietf.org/html/rfc4511#section-4.1.9 # https://tools.ietf.org/html/rfc4511#appendix-A @@ -412,7 +413,7 @@ class Net::LDAP ResultCodeStrongerAuthRequired => "Stronger Auth Needed", ResultCodeReferral => "Referral", ResultCodeAdminLimitExceeded => "Admin Limit Exceeded", - ResultCodeUnavailableCriticalExtension => "Unavailable crtical extension", + ResultCodeUnavailableCriticalExtension => "Unavailable critical extension", ResultCodeConfidentialityRequired => "Confidentiality Required", ResultCodeSaslBindInProgress => "saslBindInProgress", ResultCodeNoSuchAttribute => "No Such Attribute", @@ -480,6 +481,8 @@ def self.result2string(code) #:nodoc: # server says it supports them. This is a fix for MS Active Directory # * :instrumentation_service => An object responsible for instrumenting # operations, compatible with ActiveSupport::Notifications' public API. + # * :connect_timeout => The TCP socket timeout (in seconds) to use when + # connecting to the LDAP server (default 5 seconds). # * :encryption => specifies the encryption to be used in communicating # with the LDAP server. The value must be a Hash containing additional # parameters, which consists of two keys: @@ -712,7 +715,7 @@ def open begin @open_connection = new_connection payload[:connection] = @open_connection - payload[:bind] = @open_connection.bind(@auth) + payload[:bind] = @result = @open_connection.bind(@auth) yield self ensure @open_connection.close if @open_connection @@ -1182,14 +1185,39 @@ def delete(args) # entries. This method sends an extra control code to tell the LDAP server # to do a tree delete. ('1.2.840.113556.1.4.805') # + # If the LDAP server does not support the DELETE_TREE control code, subordinate + # entries are deleted recursively instead. + # # Returns True or False to indicate whether the delete succeeded. Extended # status information is available by calling #get_operation_result. # # dn = "mail=deleteme@example.com, ou=people, dc=example, dc=com" # ldap.delete_tree :dn => dn def delete_tree(args) - delete(args.merge(:control_codes => [[Net::LDAP::LDAPControls::DELETE_TREE, true]])) + if search_root_dse[:supportedcontrol].include? Net::LDAP::LDAPControls::DELETE_TREE + delete(args.merge(:control_codes => [[Net::LDAP::LDAPControls::DELETE_TREE, true]])) + else + recursive_delete(args) + end + end + + # Return the authorization identity of the client that issues the + # ldapwhoami request. The method does not support any arguments. + # + # Returns True or False to indicate whether the request was successfull. + # The result is available in the extended status information when calling + # #get_operation_result. + # + # ldap.ldapwhoami + # puts ldap.get_operation_result.extended_response + def ldapwhoami(args = {}) + instrument "ldapwhoami.net_ldap", args do |payload| + @result = use_connection(args, &:ldapwhoami) + @result.success? ? @result.extended_response : nil + end end + alias_method :whoami, :ldapwhoami + # This method is experimental and subject to change. Return the rootDSE # record from the LDAP server as a Net::LDAP::Entry, or an empty Entry if # the server doesn't return the record. @@ -1247,10 +1275,10 @@ def search_subschema_entry rs = search(:ignore_server_caps => true, :base => "", :scope => SearchScope_BaseObject, :attributes => [:subschemaSubentry]) - return Net::LDAP::Entry.new unless (rs and rs.first) + return Net::LDAP::Entry.new unless rs and rs.first subschema_name = rs.first.subschemasubentry - return Net::LDAP::Entry.new unless (subschema_name and subschema_name.first) + return Net::LDAP::Entry.new unless subschema_name and subschema_name.first rs = search(:ignore_server_caps => true, :base => subschema_name.first, :scope => SearchScope_BaseObject, @@ -1320,7 +1348,7 @@ def new_connection # Force connect to see if there's a connection error connection.socket connection - rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT, Net::LDAP::ConnectionRefusedError => e + rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT => e @result = { :resultCode => 52, :errorMessage => ResultStrings[ResultCodeUnavailable], @@ -1340,4 +1368,19 @@ def normalize_encryption(args) end end + # Recursively delete a dn and it's subordinate children. + # This is useful when a server does not support the DELETE_TREE control code. + def recursive_delete(args) + raise EmptyDNError unless args.is_a?(Hash) && args.key?(:dn) + # Delete Children + search(base: args[:dn], scope: Net::LDAP::SearchScope_SingleLevel) do |entry| + recursive_delete(dn: entry.dn) + end + # Delete Self + unless delete(dn: args[:dn]) + raise Net::LDAP::Error, get_operation_result[:error_message].to_s + end + true + end + end # class LDAP diff --git a/lib/net/ldap/auth_adapter/gss_spnego.rb b/lib/net/ldap/auth_adapter/gss_spnego.rb index 9f773454..b4c3e519 100644 --- a/lib/net/ldap/auth_adapter/gss_spnego.rb +++ b/lib/net/ldap/auth_adapter/gss_spnego.rb @@ -1,5 +1,5 @@ -require 'net/ldap/auth_adapter' -require 'net/ldap/auth_adapter/sasl' +require_relative '../auth_adapter' +require_relative 'sasl' module Net class LDAP @@ -20,7 +20,7 @@ def bind(auth) require 'ntlm' user, psw = [auth[:username] || auth[:dn], auth[:password]] - raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless (user && psw) + raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless user && psw nego = proc do |challenge| t2_msg = NTLM::Message.parse(challenge) diff --git a/lib/net/ldap/auth_adapter/sasl.rb b/lib/net/ldap/auth_adapter/sasl.rb index 139e8593..bfebfc94 100644 --- a/lib/net/ldap/auth_adapter/sasl.rb +++ b/lib/net/ldap/auth_adapter/sasl.rb @@ -1,4 +1,4 @@ -require 'net/ldap/auth_adapter' +require_relative '../auth_adapter' module Net class LDAP @@ -30,7 +30,7 @@ class Sasl < Net::LDAP::AuthAdapter def bind(auth) mech, cred, chall = auth[:mechanism], auth[:initial_credential], auth[:challenge_response] - raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless (mech && cred && chall) + raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless mech && cred && chall message_id = @connection.next_msgid diff --git a/lib/net/ldap/auth_adapter/simple.rb b/lib/net/ldap/auth_adapter/simple.rb index d01b57ae..8a753ea6 100644 --- a/lib/net/ldap/auth_adapter/simple.rb +++ b/lib/net/ldap/auth_adapter/simple.rb @@ -1,4 +1,4 @@ -require 'net/ldap/auth_adapter' +require_relative '../auth_adapter' module Net class LDAP @@ -11,7 +11,7 @@ def bind(auth) ["", ""] end - raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless (user && psw) + raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless user && psw message_id = @connection.next_msgid request = [ diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 61aacb53..f1a70b18 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -30,12 +30,12 @@ def socket_class=(socket_class) @socket_class = socket_class end - def prepare_socket(server, timeout=nil) + def prepare_socket(server, timeout=nil, hostname='127.0.0.1') socket = server[:socket] encryption = server[:encryption] @conn = socket - setup_encryption(encryption, timeout) if encryption + setup_encryption(encryption, timeout, hostname) if encryption end def open_connection(server) @@ -50,7 +50,7 @@ def open_connection(server) errors = [] hosts.each do |host, port| begin - prepare_socket(server.merge(socket: @socket_class.new(host, port, socket_opts)), timeout) + prepare_socket(server.merge(socket: @socket_class.new(host, port, socket_opts)), timeout, host) if encryption if encryption[:tls_options] && encryption[:tls_options][:verify_mode] && @@ -74,7 +74,8 @@ def open_connection(server) module GetbyteForSSLSocket def getbyte - getc.ord + c = getc + c && c.ord end end @@ -85,7 +86,7 @@ def close end end - def self.wrap_with_ssl(io, tls_options = {}, timeout=nil) + def self.wrap_with_ssl(io, tls_options = {}, timeout=nil, hostname=nil) raise Net::LDAP::NoOpenSSLError, "OpenSSL is unavailable" unless Net::LDAP::HasOpenSSL ctx = OpenSSL::SSL::SSLContext.new @@ -95,6 +96,7 @@ def self.wrap_with_ssl(io, tls_options = {}, timeout=nil) ctx.set_params(tls_options) unless tls_options.empty? conn = OpenSSL::SSL::SSLSocket.new(io, ctx) + conn.hostname = hostname begin if timeout @@ -147,11 +149,11 @@ def self.wrap_with_ssl(io, tls_options = {}, timeout=nil) # communications, as with simple_tls. Thanks for Kouhei Sutou for # generously contributing the :start_tls path. #++ - def setup_encryption(args, timeout=nil) + def setup_encryption(args, timeout=nil, hostname=nil) args[:tls_options] ||= {} case args[:method] when :simple_tls - @conn = self.class.wrap_with_ssl(@conn, args[:tls_options], timeout) + @conn = self.class.wrap_with_ssl(@conn, args[:tls_options], timeout, hostname) # additional branches requiring server validation and peer certs, etc. # go here. when :start_tls @@ -169,7 +171,7 @@ def setup_encryption(args, timeout=nil) raise Net::LDAP::StartTLSError, "start_tls failed: #{pdu.result_code}" unless pdu.result_code.zero? - @conn = self.class.wrap_with_ssl(@conn, args[:tls_options], timeout) + @conn = self.class.wrap_with_ssl(@conn, args[:tls_options], timeout, hostname) else raise Net::LDAP::EncMethodUnsupportedError, "unsupported encryption method #{args[:method]}" end @@ -181,7 +183,7 @@ def setup_encryption(args, timeout=nil) # have to call it, but perhaps it will come in handy someday. #++ def close - return if @conn.nil? + return if !defined?(@conn) || @conn.nil? @conn.close @conn = nil end @@ -300,7 +302,7 @@ def encode_sort_controls(sort_definitions) control[2] = (control[2] == true).to_ber control.to_ber_sequence end - sort_control = [ + [ Net::LDAP::LDAPControls::SORT_REQUEST.to_ber, false.to_ber, sort_control_values.to_ber_sequence.to_s.to_ber, @@ -422,6 +424,7 @@ def search(args = nil) # this breaks when calling to_ber. (Can't force binary data to UTF-8) # we have to disable paging (even though server supports it) to get around this... + user_controls = args.fetch(:controls, []) controls = [] controls << [ @@ -431,7 +434,12 @@ def search(args = nil) rfc2696_cookie.map(&:to_ber).to_ber_sequence.to_s.to_ber, ].to_ber_sequence if paged controls << ber_sort if ber_sort - controls = controls.empty? ? nil : controls.to_ber_contextspecific(0) + if controls.empty? && user_controls.empty? + controls = nil + else + controls += user_controls + controls = controls.to_ber_contextspecific(0) + end write(request, controls, message_id) @@ -467,6 +475,10 @@ def search(args = nil) end end + if result_pdu.nil? + raise Net::LDAP::ResponseMissingOrInvalidError, "response missing" + end + # count number of pages of results payload[:page_count] ||= 0 payload[:page_count] += 1 @@ -557,7 +569,12 @@ def modify(args) ops.to_ber_sequence, ].to_ber_appsequence(Net::LDAP::PDU::ModifyRequest) - write(request, nil, message_id) + controls = args.fetch(:controls, nil) + unless controls.nil? + controls = controls.to_ber_contextspecific(0) + end + + write(request, controls, message_id) pdu = queued_read(message_id) if !pdu || pdu.app_tag != Net::LDAP::PDU::ModifyResponse @@ -606,7 +623,7 @@ def password_modify(args) pdu = queued_read(message_id) if !pdu || pdu.app_tag != Net::LDAP::PDU::ExtendedResponse - raise Net::LDAP::ResponseMissingError, "response missing or invalid" + raise Net::LDAP::ResponseMissingOrInvalidError, "response missing or invalid" end pdu @@ -629,7 +646,12 @@ def add(args) message_id = next_msgid request = [add_dn.to_ber, add_attrs.to_ber_sequence].to_ber_appsequence(Net::LDAP::PDU::AddRequest) - write(request, nil, message_id) + controls = args.fetch(:controls, nil) + unless controls.nil? + controls = controls.to_ber_contextspecific(0) + end + + write(request, controls, message_id) pdu = queued_read(message_id) if !pdu || pdu.app_tag != Net::LDAP::PDU::AddResponse @@ -681,12 +703,28 @@ def delete(args) pdu end + def ldapwhoami + ext_seq = [Net::LDAP::WhoamiOid.to_ber_contextspecific(0)] + request = ext_seq.to_ber_appsequence(Net::LDAP::PDU::ExtendedRequest) + + message_id = next_msgid + + write(request, nil, message_id) + pdu = queued_read(message_id) + + if !pdu || pdu.app_tag != Net::LDAP::PDU::ExtendedResponse + raise Net::LDAP::ResponseMissingOrInvalidError, "response missing or invalid" + end + + pdu + end + # Internal: Returns a Socket like object used internally to communicate with # LDAP server. # # Typically a TCPSocket, but can be a OpenSSL::SSL::SSLSocket def socket - return @conn if defined? @conn + return @conn if defined?(@conn) && !@conn.nil? # First refactoring uses the existing methods open_connection and # prepare_socket to set @conn. Next cleanup would centralize connection @@ -706,7 +744,7 @@ def socket # Wrap around Socket.tcp to normalize with other Socket initializers class DefaultSocket def self.new(host, port, socket_opts = {}) - Socket.tcp(host, port, socket_opts) + Socket.tcp(host, port, **socket_opts) end end end # class Connection diff --git a/lib/net/ldap/dataset.rb b/lib/net/ldap/dataset.rb index 9027ed28..bc225e89 100644 --- a/lib/net/ldap/dataset.rb +++ b/lib/net/ldap/dataset.rb @@ -103,7 +103,7 @@ def gets # with the conversion of def from_entry(entry) dataset = Net::LDAP::Dataset.new - hash = { } + hash = {} entry.each_attribute do |attribute, value| next if attribute == :dn hash[attribute] = value @@ -164,5 +164,3 @@ def read_ldif(io) end end end - -require 'net/ldap/entry' unless defined? Net::LDAP::Entry diff --git a/lib/net/ldap/dn.rb b/lib/net/ldap/dn.rb index e314b80e..9098cdb9 100644 --- a/lib/net/ldap/dn.rb +++ b/lib/net/ldap/dn.rb @@ -57,19 +57,19 @@ def each_pair state = :key_oid key << char when ' ' then state = :key - else raise "DN badly formed" + else raise Net::LDAP::InvalidDNError, "DN badly formed" end when :key_normal then case char when '=' then state = :value when 'a'..'z', 'A'..'Z', '0'..'9', '-', ' ' then key << char - else raise "DN badly formed" + else raise Net::LDAP::InvalidDNError, "DN badly formed" end when :key_oid then case char when '=' then state = :value when '0'..'9', '.', ' ' then key << char - else raise "DN badly formed" + else raise Net::LDAP::InvalidDNError, "DN badly formed" end when :value then case char @@ -81,7 +81,7 @@ def each_pair value << char when ',' then state = :key - yield key.string.strip, value.string.rstrip + yield key.string.strip, value.string key = StringIO.new value = StringIO.new; else @@ -93,7 +93,7 @@ def each_pair when '\\' then state = :value_normal_escape when ',' then state = :key - yield key.string.strip, value.string.rstrip + yield key.string.strip, value.string key = StringIO.new value = StringIO.new; else value << char @@ -110,7 +110,7 @@ def each_pair when '0'..'9', 'a'..'f', 'A'..'F' then state = :value_normal value << "#{hex_buffer}#{char}".to_i(16).chr - else raise "DN badly formed" + else raise Net::LDAP::InvalidDNError, "DN badly formed" end when :value_quoted then case char @@ -132,7 +132,7 @@ def each_pair when '0'..'9', 'a'..'f', 'A'..'F' then state = :value_quoted value << "#{hex_buffer}#{char}".to_i(16).chr - else raise "DN badly formed" + else raise Net::LDAP::InvalidDNError, "DN badly formed" end when :value_hexstring then case char @@ -142,37 +142,37 @@ def each_pair when ' ' then state = :value_end when ',' then state = :key - yield key.string.strip, value.string.rstrip + yield key.string.strip, value.string key = StringIO.new value = StringIO.new; - else raise "DN badly formed" + else raise Net::LDAP::InvalidDNError, "DN badly formed" end when :value_hexstring_hex then case char when '0'..'9', 'a'..'f', 'A'..'F' then state = :value_hexstring value << char - else raise "DN badly formed" + else raise Net::LDAP::InvalidDNError, "DN badly formed" end when :value_end then case char when ' ' then state = :value_end when ',' then state = :key - yield key.string.strip, value.string.rstrip + yield key.string.strip, value.string key = StringIO.new value = StringIO.new; - else raise "DN badly formed" + else raise Net::LDAP::InvalidDNError, "DN badly formed" end - else raise "Fell out of state machine" + else raise Net::LDAP::InvalidDNError, "Fell out of state machine" end end # Last pair - raise "DN badly formed" unless + raise Net::LDAP::InvalidDNError, "DN badly formed" unless [:value, :value_normal, :value_hexstring, :value_end].include? state - yield key.string.strip, value.string.rstrip + yield key.string.strip, value.string end ## @@ -192,27 +192,19 @@ def to_s # http://tools.ietf.org/html/rfc2253 section 2.4 lists these exceptions # for dn values. All of the following must be escaped in any normal string # using a single backslash ('\') as escape. - ESCAPES = { - ',' => ',', - '+' => '+', - '"' => '"', - '\\' => '\\', - '<' => '<', - '>' => '>', - ';' => ';', - } + ESCAPES = %w[, + " \\ < > ;] - # Compiled character class regexp using the keys from the above hash, and + # Compiled character class regexp using the values from the above list, and # checking for a space or # at the start, or space at the end, of the # string. ESCAPE_RE = Regexp.new("(^ |^#| $|[" + - ESCAPES.keys.map { |e| Regexp.escape(e) }.join + + ESCAPES.map { |e| Regexp.escape(e) }.join + "])") ## # Escape a string for use in a DN value def self.escape(string) - string.gsub(ESCAPE_RE) { |char| "\\" + ESCAPES[char] } + string.gsub(ESCAPE_RE) { |char| "\\" + char } end ## diff --git a/lib/net/ldap/entry.rb b/lib/net/ldap/entry.rb index 10965c7c..18668892 100644 --- a/lib/net/ldap/entry.rb +++ b/lib/net/ldap/entry.rb @@ -133,6 +133,13 @@ def attribute_names @myhash.keys end + ## + # Creates a duplicate of the internal Hash containing the attributes + # of the entry. + def to_h + @myhash.dup + end + ## # Accesses each of the attributes present in the Entry. # @@ -187,6 +194,8 @@ def setter?(sym) sym.to_s[-1] == ?= end private :setter? -end # class Entry -require 'net/ldap/dataset' unless defined? Net::LDAP::Dataset + def ==(other) + other.instance_of?(self.class) && @myhash == other.to_h + end +end # class Entry diff --git a/lib/net/ldap/error.rb b/lib/net/ldap/error.rb index 50442d06..49a338d6 100644 --- a/lib/net/ldap/error.rb +++ b/lib/net/ldap/error.rb @@ -1,38 +1,13 @@ class Net::LDAP - class LdapError < StandardError - def message - "Deprecation warning: Net::LDAP::LdapError is no longer used. Use Net::LDAP::Error or rescue one of it's subclasses. \n" + super - end - end - class Error < StandardError; end class AlreadyOpenedError < Error; end class SocketError < Error; end - class ConnectionRefusedError < Error; - def initialize(*args) - warn_deprecation_message - super - end - - def message - warn_deprecation_message - super - end - - private - - def warn_deprecation_message - warn "Deprecation warning: Net::LDAP::ConnectionRefused will be deprecated. Use Errno::ECONNREFUSED instead." - end - end class ConnectionError < Error def self.new(errors) error = errors.first.first if errors.size == 1 - if error.kind_of? Errno::ECONNREFUSED - return Net::LDAP::ConnectionRefusedError.new(error.message) - end + return error if error.is_a? Errno::ECONNREFUSED return Net::LDAP::Error.new(error.message) end @@ -60,6 +35,7 @@ class SearchScopeInvalidError < Error; end class ResponseTypeInvalidError < Error; end class ResponseMissingOrInvalidError < Error; end class EmptyDNError < Error; end + class InvalidDNError < Error; end class HashTypeUnsupportedError < Error; end class OperatorError < Error; end class SubstringFilterError < Error; end diff --git a/lib/net/ldap/filter.rb b/lib/net/ldap/filter.rb index 6f064488..dc0d0ab3 100644 --- a/lib/net/ldap/filter.rb +++ b/lib/net/ldap/filter.rb @@ -490,7 +490,7 @@ def to_ber when :eq if @right == "*" # presence test @left.to_s.to_ber_contextspecific(7) - elsif @right =~ /[*]/ # substring + elsif @right.to_s =~ /[*]/ # substring # Parsing substrings is a little tricky. We use String#split to # break a string into substrings delimited by the * (star) # character. But we also need to know whether there is a star at the @@ -646,7 +646,7 @@ def match(entry) ## # Converts escaped characters (e.g., "\\28") to unescaped characters # @note slawson20170317: Don't attempt to unescape 16 byte binary data which we assume are objectGUIDs - # The binary form of 5936AE79-664F-44EA-BCCB-5C39399514C6 triggers a BINARY -> UTF-8 conversion error + # The binary form of 5936AE79-664F-44EA-BCCB-5C39399514C6 triggers a BINARY -> UTF-8 conversion error def unescape(right) right = right.to_s if right.length == 16 && right.encoding == Encoding::BINARY @@ -755,7 +755,7 @@ def parse_paren_expression(scanner) # This parses a given expression inside of parentheses. def parse_filter_branch(scanner) scanner.scan(/\s*/) - if token = scanner.scan(/[-\w:.]*[\w]/) + if token = scanner.scan(/[-\w:.;]*[\w]/) scanner.scan(/\s*/) if op = scanner.scan(/<=|>=|!=|:=|=/) scanner.scan(/\s*/) diff --git a/lib/net/ldap/instrumentation.rb b/lib/net/ldap/instrumentation.rb index 143e03b3..d5cc6bf7 100644 --- a/lib/net/ldap/instrumentation.rb +++ b/lib/net/ldap/instrumentation.rb @@ -12,8 +12,8 @@ module Net::LDAP::Instrumentation def instrument(event, payload = {}) payload = (payload || {}).dup if instrumentation_service - instrumentation_service.instrument(event, payload) do |payload| - payload[:result] = yield(payload) if block_given? + instrumentation_service.instrument(event, payload) do |instr_payload| + instr_payload[:result] = yield(instr_payload) if block_given? end else yield(payload) if block_given? diff --git a/lib/net/ldap/password.rb b/lib/net/ldap/password.rb index 28406f03..9a6658ed 100644 --- a/lib/net/ldap/password.rb +++ b/lib/net/ldap/password.rb @@ -1,5 +1,6 @@ # -*- ruby encoding: utf-8 -*- require 'digest/sha1' +require 'digest/sha2' require 'digest/md5' require 'base64' require 'securerandom' @@ -19,20 +20,21 @@ class << self # * Should we provide sha1 as a synonym for sha1? I vote no because then # should you also provide ssha1 for symmetry? # - attribute_value = "" def generate(type, str) case type when :md5 - attribute_value = '{MD5}' + Base64.encode64(Digest::MD5.digest(str)).chomp! + '{MD5}' + Base64.strict_encode64(Digest::MD5.digest(str)) when :sha - attribute_value = '{SHA}' + Base64.encode64(Digest::SHA1.digest(str)).chomp! + '{SHA}' + Base64.strict_encode64(Digest::SHA1.digest(str)) when :ssha salt = SecureRandom.random_bytes(16) - attribute_value = '{SSHA}' + Base64.encode64(Digest::SHA1.digest(str + salt) + salt).chomp! + '{SSHA}' + Base64.strict_encode64(Digest::SHA1.digest(str + salt) + salt) + when :ssha256 + salt = SecureRandom.random_bytes(16) + '{SSHA256}' + Base64.strict_encode64(Digest::SHA256.digest(str + salt) + salt) else raise Net::LDAP::HashTypeUnsupportedError, "Unsupported password-hash type (#{type})" end - return attribute_value end end end diff --git a/lib/net/ldap/pdu.rb b/lib/net/ldap/pdu.rb index 382c7acb..83a609b7 100644 --- a/lib/net/ldap/pdu.rb +++ b/lib/net/ldap/pdu.rb @@ -123,7 +123,7 @@ def initialize(ber_object) when ExtendedResponse parse_extended_response(ber_object[1]) else - raise LdapPduError.new("unknown pdu-type: #{@app_tag}") + raise Error.new("unknown pdu-type: #{@app_tag}") end parse_controls(ber_object[2]) if ber_object[2] @@ -194,13 +194,13 @@ def parse_ldap_result(sequence) # requestValue [1] OCTET STRING OPTIONAL } def parse_extended_response(sequence) - sequence.length >= 3 or raise Net::LDAP::PDU::Error, "Invalid LDAP result length." + sequence.length.between?(3, 5) or raise Net::LDAP::PDU::Error, "Invalid LDAP result length." @ldap_result = { :resultCode => sequence[0], :matchedDN => sequence[1], :errorMessage => sequence[2], } - @extended_response = sequence[3] + @extended_response = sequence.length == 3 ? nil : sequence.last end private :parse_extended_response diff --git a/lib/net/ldap/version.rb b/lib/net/ldap/version.rb index 0a57d621..536b2f89 100644 --- a/lib/net/ldap/version.rb +++ b/lib/net/ldap/version.rb @@ -1,5 +1,5 @@ module Net class LDAP - VERSION = "0.16.1" + VERSION = "0.19.0" end end diff --git a/lib/net/snmp.rb b/lib/net/snmp.rb index 258e8060..f89fe267 100644 --- a/lib/net/snmp.rb +++ b/lib/net/snmp.rb @@ -1,5 +1,5 @@ # -*- ruby encoding: utf-8 -*- -require 'net/ldap/version' +require_relative 'ldap/version' # :stopdoc: module Net diff --git a/net-ldap.gemspec b/net-ldap.gemspec index 7516759b..3def4c20 100644 --- a/net-ldap.gemspec +++ b/net-ldap.gemspec @@ -1,7 +1,7 @@ # -*- encoding: utf-8 -*- lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) -require 'net/ldap/version' +require_relative 'lib/net/ldap/version' Gem::Specification.new do |s| s.name = %q{net-ldap} @@ -21,17 +21,18 @@ Our roadmap for Net::LDAP 1.0 is to gain full client compliance with the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).} s.email = ["blackhedd@rubyforge.org", "gemiel@gmail.com", "rory.ocon@gmail.com", "kaspar.schiess@absurd.li", "austin@rubyforge.org"] s.extra_rdoc_files = ["Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "README.rdoc"] - s.files = `git ls-files`.split $/ + s.files = Dir["*.rdoc", "lib/**/*"] s.test_files = s.files.grep(%r{^test}) s.homepage = %q{http://github.com/ruby-ldap/ruby-net-ldap} s.rdoc_options = ["--main", "README.rdoc"] s.require_paths = ["lib"] - s.required_ruby_version = ">= 2.0.0" + s.required_ruby_version = ">= 3.0.0" s.summary = %q{Net::LDAP for Ruby (also called net-ldap) implements client access for the Lightweight Directory Access Protocol (LDAP), an IETF standard protocol for accessing distributed directory services} + s.add_dependency("ostruct") s.add_development_dependency("flexmock", "~> 1.3") - s.add_development_dependency("rake", "~> 10.0") - s.add_development_dependency("rubocop", "~> 0.42.0") - s.add_development_dependency("test-unit") - s.add_development_dependency("byebug") + s.add_development_dependency("rake", "~> 12.3.3") + s.add_development_dependency("rubocop", "~> 1.48") + s.add_development_dependency("test-unit", "~> 3.3") + s.add_development_dependency("byebug", "~> 9.0.6") unless RUBY_PLATFORM == "java" end diff --git a/script/changelog b/script/changelog index cda2ad83..f42a0bd4 100755 --- a/script/changelog +++ b/script/changelog @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Usage: script/changelog [-r ] [-b ] [-h ] # # repo: BASE string of GitHub REPOsitory url. e.g. "user_or_org/REPOsitory". Defaults to git remote url. diff --git a/script/generate-fixture-ca b/script/generate-fixture-ca deleted file mode 100755 index 89eb3d8d..00000000 --- a/script/generate-fixture-ca +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash - -BASE_PATH=$( cd "`dirname $0`/../test/fixtures/ca" && pwd ) -cd "${BASE_PATH}" || exit 4 - -USAGE=$( cat << EOS -Usage: - $0 --regenerate - -Generates a new self-signed CA, for integration testing. This should only need -to be run if you are writing new TLS/SSL tests, and need to generate -additional fixtuer CAs. - -This script uses the GnuTLS certtool CLI. If you are on macOS, -'brew install gnutls', and it will be installed as 'gnutls-certtool'. -Apple unfortunately ships with an incompatible /usr/bin/certtool that does -different things. -EOS -) - -if [ "x$1" != 'x--regenerate' ]; then - echo "${USAGE}" - exit 1 -fi - -TOOL=`type -p certtool` -if [ "$(uname)" = "Darwin" ]; then - TOOL=`type -p gnutls-certtool` - if [ ! -x "${TOOL}" ]; then - echo "Sorry, Darwin requires gnutls-certtool; try `brew install gnutls`" - exit 2 - fi -fi - -if [ ! -x "${TOOL}" ]; then - echo "Sorry, no certtool found!" - exit 3 -fi -export TOOL - - -${TOOL} --generate-privkey > ./cakey.pem -${TOOL} --generate-self-signed \ - --load-privkey ./cakey.pem \ - --template ./ca.info \ - --outfile ./cacert.pem - -echo "cert and private key generated! Don't forget to check them in" diff --git a/script/install-openldap b/script/install-openldap deleted file mode 100755 index 3e391d87..00000000 --- a/script/install-openldap +++ /dev/null @@ -1,134 +0,0 @@ -#!/usr/bin/env sh -set -e -set -x - -BASE_PATH=$( cd "`dirname $0`/../test/fixtures/openldap" && pwd ) -SEED_PATH=$( cd "`dirname $0`/../test/fixtures" && pwd ) - -dpkg -s slapd time ldap-utils gnutls-bin ssl-cert > /dev/null ||\ - DEBIAN_FRONTEND=noninteractive apt-get update -y --force-yes && \ - DEBIAN_FRONTEND=noninteractive apt-get install -y --force-yes slapd time ldap-utils gnutls-bin ssl-cert - -/etc/init.d/slapd stop - -TMPDIR=$(mktemp -d) -cd $TMPDIR - -# Delete data and reconfigure. -cp -v /var/lib/ldap/DB_CONFIG ./DB_CONFIG -rm -rf /etc/ldap/slapd.d/* -rm -rf /var/lib/ldap/* -cp -v ./DB_CONFIG /var/lib/ldap/DB_CONFIG -slapadd -F /etc/ldap/slapd.d -b "cn=config" -l $BASE_PATH/slapd.conf.ldif -# Load memberof and ref-int overlays and configure them. -slapadd -F /etc/ldap/slapd.d -b "cn=config" -l $BASE_PATH/memberof.ldif -# Load retcode overlay and configure -slapadd -F /etc/ldap/slapd.d -b "cn=config" -l $BASE_PATH/retcode.ldif - -# Add base domain. -slapadd -F /etc/ldap/slapd.d < /etc/ssl/ldap01.info <> /etc/ssl/ldap01.info -done - -# Create the server certificate -certtool --generate-certificate \ - --load-privkey /etc/ssl/private/ldap01_slapd_key.pem \ - --load-ca-certificate "${CA_CERT}" \ - --load-ca-privkey "${CA_KEY}" \ - --template /etc/ssl/ldap01.info \ - --outfile /etc/ssl/certs/ldap01_slapd_cert.pem - -ldapmodify -Y EXTERNAL -H ldapi:/// <> /etc/hosts -grep ldap02 /etc/hosts || echo "127.0.0.1 ldap02.example.com" >> /etc/hosts -grep bogus /etc/hosts || echo "127.0.0.1 bogus.example.com" >> /etc/hosts - -service slapd restart diff --git a/script/ldap-docker b/script/ldap-docker new file mode 100755 index 00000000..c677eec8 --- /dev/null +++ b/script/ldap-docker @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# Usage: script/ldap-docker +# +# Starts a openldap docker container ready for integration tests + +docker run --rm -ti \ + --hostname ldap.example.org \ + --env LDAP_TLS_VERIFY_CLIENT=try \ + -p 389:389 -p 636:636 \ + -v "$(pwd)"/test/fixtures/ldif:/container/service/slapd/assets/config/bootstrap/ldif/custom \ + --name my-openldap-container \ + osixia/openldap:1.3.0 --copy-service --loglevel debug \ No newline at end of file diff --git a/script/release b/script/release index 6dcd8cb3..595a00dc 100755 --- a/script/release +++ b/script/release @@ -9,8 +9,7 @@ version="$(script/package | grep Version: | awk '{print $2}')" [ -n "$version" ] || exit 1 echo $version -git commit --allow-empty -a -m "Release $version" -git tag "v$version" +git tag "v$version" -m "Release $version" git push origin git push origin "v$version" gem push pkg/*-${version}.gem diff --git a/test/ber/test_ber.rb b/test/ber/test_ber.rb index 5d5c1266..b700972e 100644 --- a/test/ber/test_ber.rb +++ b/test/ber/test_ber.rb @@ -95,7 +95,7 @@ def test_utf8_encodable_strings def test_encode_binary_data # This is used for searching for GUIDs in Active Directory assert_equal "\x04\x10" + "j1\xB4\xA1*\xA2zA\xAC\xA9`?'\xDDQ\x16".b, - ["6a31b4a12aa27a41aca9603f27dd5116"].pack("H*").to_ber_bin + ["6a31b4a12aa27a41aca9603f27dd5116"].pack("H*").to_ber_bin end def test_non_utf8_encodable_strings diff --git a/test/fixtures/ca/ca.info b/test/fixtures/ca/ca.info deleted file mode 100644 index c0fd3629..00000000 --- a/test/fixtures/ca/ca.info +++ /dev/null @@ -1,4 +0,0 @@ -cn = rubyldap -ca -cert_signing_key -expiration_days = 7200 diff --git a/test/fixtures/ca/cacert.pem b/test/fixtures/ca/cacert.pem deleted file mode 100644 index 0218dd8a..00000000 --- a/test/fixtures/ca/cacert.pem +++ /dev/null @@ -1,24 +0,0 @@ ------BEGIN CERTIFICATE----- -MIID7zCCAlegAwIBAgIMV7zWei6SNfABx6jMMA0GCSqGSIb3DQEBCwUAMBMxETAP -BgNVBAMTCHJ1YnlsZGFwMB4XDTE2MDgyMzIzMDQyNloXDTM2MDUxMDIzMDQyNlow -EzERMA8GA1UEAxMIcnVieWxkYXAwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGK -AoIBgQDGe9wziGHZJhIf+IEKSk1tpT9Mu7YgsUwjrlutvkoO1Q6K+amTAVDXizPf -1DVSDpZP5+CfBOznhgLMsPvrQ02w4qx5/6X9L+zJcMk8jTNYSKj5uIKpK52E7Uok -aygMXeaqroPONGkoJIZiVGgdbWfTvcffTm8FOhztXUbMrMXJNinFsocGHEoMNN8b -vqgAyG4+DFHoK4L0c6eQjE4nZBChieZdShUhaBpV7r2qSNbPw67cvAKuEzml58mV -1ZF1F73Ua8gPWXHEfUe2GEfG0NnRq6sGbsDYe/DIKxC7AZ89udZF3WZXNrPhvXKj -ZT7njwcMQemns4dNPQ0k2V4vAQ8pD8r8Qvb65FiSopUhVaGQswAnIMS1DnFq88AQ -KJTKIXbBuMwuaNNSs6R/qTS2RDk1w+CGpRXAg7+1SX5NKdrEsu1IaABA/tQ/zKKk -OLLJaD0giX1weBVmNeFcKxIoT34VS59eEt5APmPcguJnx+aBrA9TLzSO788apBN0 -4lGAmR0CAwEAAaNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwQA -MB0GA1UdDgQWBBRTvXSkge03oqLu7UUjFI+oLYwnujANBgkqhkiG9w0BAQsFAAOC -AYEATSZQWH+uSN5GvOUvJ8LHWkeVovn0UhboK0K7GzmMeGz+dp/Xrj6eQ4ONK0zI -RCJyoo/nCR7CfQ5ujVXr03XD2SUgyD565ulXuhw336DasL5//fucmQYDeqhwbKML -FTzsF9H9dO4J5TjxJs7e5dRJ0wrP/XEY+WFhXXdSHTl8vGCI6QqWc7TvDpmbS4iX -uTzjJswu9Murt9JUJNMN2DlDi/vBBeruaj4c2cMMnKMvkfj14kd8wMocmzj+gVQl -r+fRQbKAJNec65lA4/Zeb6sD9SAi0ZIVgxA4a7g8/sdNWHIAxPicpJkIJf30TsyY -F+8+Hd5mBtCbvFfAVkT6bHBP1OiAgNke+Rh/j/sQbyWbKCKw0+jpFJgO9KUNGfC0 -O/CqX+J4G7HqL8VJqrLnBvOdhfetAvNQtf1gcw5ZwpeEFM+Kvx/lsILaIYdAUSjX -ePOc5gI2Bi9WXq+T9AuhSf+TWUR874m/rdTWe5fM8mXCNl7C4I5zCqLltEDkSoMP -jDj/ ------END CERTIFICATE----- diff --git a/test/fixtures/ca/cakey.pem b/test/fixtures/ca/cakey.pem deleted file mode 100644 index d75ab299..00000000 --- a/test/fixtures/ca/cakey.pem +++ /dev/null @@ -1,190 +0,0 @@ -Public Key Info: - Public Key Algorithm: RSA - Key Security Level: High (3072 bits) - -modulus: - 00:c6:7b:dc:33:88:61:d9:26:12:1f:f8:81:0a:4a:4d - 6d:a5:3f:4c:bb:b6:20:b1:4c:23:ae:5b:ad:be:4a:0e - d5:0e:8a:f9:a9:93:01:50:d7:8b:33:df:d4:35:52:0e - 96:4f:e7:e0:9f:04:ec:e7:86:02:cc:b0:fb:eb:43:4d - b0:e2:ac:79:ff:a5:fd:2f:ec:c9:70:c9:3c:8d:33:58 - 48:a8:f9:b8:82:a9:2b:9d:84:ed:4a:24:6b:28:0c:5d - e6:aa:ae:83:ce:34:69:28:24:86:62:54:68:1d:6d:67 - d3:bd:c7:df:4e:6f:05:3a:1c:ed:5d:46:cc:ac:c5:c9 - 36:29:c5:b2:87:06:1c:4a:0c:34:df:1b:be:a8:00:c8 - 6e:3e:0c:51:e8:2b:82:f4:73:a7:90:8c:4e:27:64:10 - a1:89:e6:5d:4a:15:21:68:1a:55:ee:bd:aa:48:d6:cf - c3:ae:dc:bc:02:ae:13:39:a5:e7:c9:95:d5:91:75:17 - bd:d4:6b:c8:0f:59:71:c4:7d:47:b6:18:47:c6:d0:d9 - d1:ab:ab:06:6e:c0:d8:7b:f0:c8:2b:10:bb:01:9f:3d - b9:d6:45:dd:66:57:36:b3:e1:bd:72:a3:65:3e:e7:8f - 07:0c:41:e9:a7:b3:87:4d:3d:0d:24:d9:5e:2f:01:0f - 29:0f:ca:fc:42:f6:fa:e4:58:92:a2:95:21:55:a1:90 - b3:00:27:20:c4:b5:0e:71:6a:f3:c0:10:28:94:ca:21 - 76:c1:b8:cc:2e:68:d3:52:b3:a4:7f:a9:34:b6:44:39 - 35:c3:e0:86:a5:15:c0:83:bf:b5:49:7e:4d:29:da:c4 - b2:ed:48:68:00:40:fe:d4:3f:cc:a2:a4:38:b2:c9:68 - 3d:20:89:7d:70:78:15:66:35:e1:5c:2b:12:28:4f:7e - 15:4b:9f:5e:12:de:40:3e:63:dc:82:e2:67:c7:e6:81 - ac:0f:53:2f:34:8e:ef:cf:1a:a4:13:74:e2:51:80:99 - 1d: - -public exponent: - 01:00:01: - -private exponent: - 1d:0d:9a:50:ec:c0:ad:e1:75:bb:ba:4b:61:2f:39:20 - 38:95:08:6d:5d:9e:71:75:5c:af:b3:f9:bd:a5:e7:7f - e6:4e:0f:77:73:ee:38:60:24:9f:26:3f:50:c2:bf:21 - df:76:68:99:be:45:d3:29:f9:94:ee:bf:21:53:cb:b6 - 7d:a7:93:80:09:53:03:45:dc:c2:a6:a2:37:64:f1:a2 - 49:21:ac:91:6b:a3:d7:bd:d2:62:0c:ec:a6:83:10:e7 - a7:ca:3d:be:dc:4b:1c:36:24:79:96:33:5b:43:5d:74 - 50:0e:46:b0:9b:6d:9f:71:06:89:a5:c8:65:ed:d9:a3 - 15:00:3c:3e:a9:75:50:9d:72:cb:c9:aa:e1:ba:a3:9c - 07:77:14:32:30:d4:4d:65:f4:7c:23:1d:79:84:9b:2e - 9a:19:df:43:ed:cd:e3:08:1f:d5:ff:6b:42:98:36:f7 - 44:cc:48:b4:f7:b8:16:b3:23:37:8d:b8:22:3f:8a:86 - db:71:b3:85:2d:6d:42:44:b7:dc:c1:36:e0:c4:0f:fe - cb:76:84:81:e2:83:f5:82:76:a9:7b:35:d5:44:00:d1 - 1a:fc:ef:b9:a4:2b:62:aa:f8:56:eb:60:e5:16:33:f1 - 28:e1:da:91:50:e3:a4:c7:d6:30:21:cf:04:07:cd:8c - b6:9e:b0:a7:6c:96:57:2e:09:5b:39:26:d0:60:be:e3 - 90:59:a3:8e:e7:6e:3f:62:7e:b4:2a:e1:8f:00:37:7a - 83:9e:7a:9c:d2:ae:ba:50:84:73:65:3a:64:95:d8:48 - f9:fd:0e:c3:5b:6e:08:3b:c5:c9:1c:29:55:bb:67:e8 - fa:50:40:30:2a:d1:b7:cf:54:a8:f0:f0:76:89:ad:19 - e7:a0:3a:56:6c:75:c5:bc:d8:46:ce:1e:66:f2:61:96 - 11:e4:57:cc:52:ff:e4:ed:6b:2c:ce:78:15:ba:b7:ed - 31:f2:68:88:79:bf:7c:29:3c:2f:66:71:0b:09:b7:41 - - -prime1: - 00:fd:c2:37:b9:6f:77:88:51:a2:f7:4f:c2:3c:a4:57 - bf:ba:71:14:f3:61:f4:39:78:22:3d:bc:d8:d2:4e:c0 - 4b:9e:c2:6d:38:a8:21:e2:70:1a:96:48:95:18:85:01 - 46:fb:62:a4:81:09:f8:2a:3a:87:78:07:5d:93:54:ce - 2a:51:b3:51:6f:61:0a:2e:9d:b0:51:37:e3:13:bd:81 - 23:2b:61:53:fa:ac:08:dc:a0:e6:63:a3:b0:cc:cf:73 - 1d:65:b7:11:bc:29:70:fb:72:ea:63:9d:67:02:d6:35 - 24:13:1d:bc:72:fb:9e:3d:ab:0b:57:6e:bd:a1:51:56 - f9:bc:96:15:74:a3:31:16:c6:b8:98:1b:0a:a2:59:7c - c8:b7:14:b8:5b:f3:2e:26:b4:f0:46:c4:3d:27:dd:41 - 31:52:a7:15:a8:af:6a:98:a5:9c:20:17:f9:1d:54:54 - ff:10:91:a3:a5:ca:ac:63:e7:16:2b:71:3c:3a:cd:4f - ed: - -prime2: - 00:c8:3c:a8:9f:8a:db:42:b5:8d:cf:2a:a1:2f:e5:73 - 05:de:30:d8:17:b9:5c:9d:08:60:02:c9:66:9d:88:50 - ac:cd:0f:b5:47:b4:a8:73:3b:7d:65:79:bf:4c:6f:d0 - e2:03:ed:d4:28:4e:00:07:23:00:01:4f:05:de:9b:44 - 1a:84:ae:09:4a:d6:ed:61:5d:77:e2:fa:13:99:4c:b7 - 76:72:3d:f8:53:93:69:78:e8:bd:26:cb:b0:f9:01:f4 - 1d:20:4f:60:f5:ab:3c:19:85:73:34:f3:ec:d2:67:ef - 56:b8:5d:93:73:8e:d9:3e:28:ff:87:f5:4a:26:fa:b1 - ae:c6:d3:9d:03:e3:fd:c2:24:48:af:85:2a:8e:3b:5b - 93:07:38:91:21:ae:49:cb:6d:e3:30:81:15:ed:65:eb - dc:01:df:3b:9d:43:fd:a6:e1:df:ef:ad:22:42:34:f1 - 3f:81:5e:57:0a:e0:56:94:f2:2a:00:d0:cc:c5:50:67 - f1: - -coefficient: - 00:bd:23:8c:2e:a7:7b:6b:1e:85:77:db:7d:77:f6:e5 - b0:15:c6:e1:9e:35:57:72:df:35:6d:93:89:7f:83:9f - 63:7f:08:0a:b3:d4:ba:63:9b:10:7f:0f:d3:55:e9:38 - cf:90:37:3d:85:3d:a7:97:8c:33:f2:c2:b1:38:2b:db - 39:ca:a8:d0:23:d7:89:cc:8d:02:7d:61:9b:b6:04:69 - 14:e8:c9:84:34:36:6c:fb:84:58:cc:9a:53:74:a4:42 - bd:1d:25:1b:ba:82:c0:fb:23:2c:90:bb:35:4b:5b:b0 - 98:d0:ab:9d:61:6e:ea:e8:84:e7:a7:6c:ae:1b:2c:00 - cb:0f:1a:f8:e2:7c:fd:42:1a:e2:13:52:c7:50:fa:65 - c9:5f:ed:40:a8:7f:46:0e:ce:f6:56:83:6f:0e:8e:39 - f8:33:5f:83:de:be:be:ef:8c:66:ad:16:c8:ec:98:d4 - b2:b2:55:66:a2:9e:27:6a:84:f1:31:07:e8:bf:a7:a7 - bd: - -exp1: - 00:b6:50:0c:53:19:07:8b:14:03:fe:a4:fa:0b:31:93 - ad:b7:18:b9:91:a6:c5:9d:68:77:49:5d:dd:75:33:89 - 2a:8b:54:6a:be:32:e5:ad:57:17:72:f3:90:d2:fd:f4 - 0d:f8:5c:45:8e:44:08:5c:e6:92:1f:a5:43:10:af:f4 - 33:29:61:a8:d7:59:a3:c4:1c:1c:ea:2d:39:e3:1b:da - a4:d6:ec:e5:36:0a:d5:8f:15:b6:90:cd:b1:1f:64:c7 - f2:cd:fa:3a:2e:b2:a3:6e:b4:80:3b:b3:81:a7:e3:18 - 68:e3:a7:10:96:97:ba:77:d9:e4:9b:1b:7f:f8:5f:85 - 1a:85:e8:5a:5f:e3:43:48:76:db:76:c4:ae:de:37:66 - d4:99:dc:b4:1b:b3:da:6b:8a:c1:ba:46:11:1e:0b:f3 - 63:a9:5b:4b:cf:56:c0:42:0d:71:df:08:fa:3c:9d:33 - 37:d1:c2:a1:0d:63:50:79:b2:34:16:60:13:82:b7:b1 - 7d: - -exp2: - 00:98:38:2c:c4:24:4e:2c:b7:52:17:a4:43:a6:e2:99 - ff:62:fa:e4:bb:9c:49:40:83:66:61:97:f3:af:5c:3a - 60:32:ff:77:03:0c:de:65:c3:5a:bf:72:bf:2f:7f:6d - 5e:f4:37:af:69:f8:69:e3:03:03:74:fb:3a:ee:10:40 - c4:9c:0a:a5:bb:c4:09:ef:53:9b:d8:eb:dd:4c:53:da - c0:6b:76:9a:ba:06:3d:4f:12:37:01:30:25:d8:16:59 - 1a:6f:3e:88:ea:19:83:75:af:52:76:75:dc:99:d3:33 - 4a:4c:9b:ae:85:51:99:ea:bc:46:0d:78:36:27:cd:ba - 97:b0:44:9c:7f:a1:a9:7e:16:11:3f:85:4f:65:92:d0 - 39:c4:6a:87:42:00:79:ce:f1:39:9d:dc:f3:eb:65:e8 - d8:76:7f:da:94:e2:64:08:a2:7b:97:7b:99:a8:95:10 - b5:03:46:d1:8a:ce:22:63:d6:78:81:e8:39:52:e2:9e - 31: - - -Public Key ID: 53:BD:74:A4:81:ED:37:A2:A2:EE:ED:45:23:14:8F:A8:2D:8C:27:BA -Public key's random art: -+--[ RSA 3072]----+ -| . o. . | -| . +...+ | -| . o o.+ . | -| o o . . .ooo | -| o = . S o..o . | -| . o . .+.. | -|. . .. | -| . .. . | -|E oo.o | -+-----------------+ - ------BEGIN RSA PRIVATE KEY----- -MIIG5QIBAAKCAYEAxnvcM4hh2SYSH/iBCkpNbaU/TLu2ILFMI65brb5KDtUOivmp -kwFQ14sz39Q1Ug6WT+fgnwTs54YCzLD760NNsOKsef+l/S/syXDJPI0zWEio+biC -qSudhO1KJGsoDF3mqq6DzjRpKCSGYlRoHW1n073H305vBToc7V1GzKzFyTYpxbKH -BhxKDDTfG76oAMhuPgxR6CuC9HOnkIxOJ2QQoYnmXUoVIWgaVe69qkjWz8Ou3LwC -rhM5pefJldWRdRe91GvID1lxxH1HthhHxtDZ0aurBm7A2HvwyCsQuwGfPbnWRd1m -Vzaz4b1yo2U+548HDEHpp7OHTT0NJNleLwEPKQ/K/EL2+uRYkqKVIVWhkLMAJyDE -tQ5xavPAECiUyiF2wbjMLmjTUrOkf6k0tkQ5NcPghqUVwIO/tUl+TSnaxLLtSGgA -QP7UP8yipDiyyWg9IIl9cHgVZjXhXCsSKE9+FUufXhLeQD5j3ILiZ8fmgawPUy80 -ju/PGqQTdOJRgJkdAgMBAAECggGAHQ2aUOzAreF1u7pLYS85IDiVCG1dnnF1XK+z -+b2l53/mTg93c+44YCSfJj9Qwr8h33Zomb5F0yn5lO6/IVPLtn2nk4AJUwNF3MKm -ojdk8aJJIayRa6PXvdJiDOymgxDnp8o9vtxLHDYkeZYzW0NddFAORrCbbZ9xBoml -yGXt2aMVADw+qXVQnXLLyarhuqOcB3cUMjDUTWX0fCMdeYSbLpoZ30PtzeMIH9X/ -a0KYNvdEzEi097gWsyM3jbgiP4qG23GzhS1tQkS33ME24MQP/st2hIHig/WCdql7 -NdVEANEa/O+5pCtiqvhW62DlFjPxKOHakVDjpMfWMCHPBAfNjLaesKdsllcuCVs5 -JtBgvuOQWaOO524/Yn60KuGPADd6g556nNKuulCEc2U6ZJXYSPn9DsNbbgg7xckc -KVW7Z+j6UEAwKtG3z1So8PB2ia0Z56A6Vmx1xbzYRs4eZvJhlhHkV8xS/+TtayzO -eBW6t+0x8miIeb98KTwvZnELCbdBAoHBAP3CN7lvd4hRovdPwjykV7+6cRTzYfQ5 -eCI9vNjSTsBLnsJtOKgh4nAalkiVGIUBRvtipIEJ+Co6h3gHXZNUzipRs1FvYQou -nbBRN+MTvYEjK2FT+qwI3KDmY6OwzM9zHWW3EbwpcPty6mOdZwLWNSQTHbxy+549 -qwtXbr2hUVb5vJYVdKMxFsa4mBsKoll8yLcUuFvzLia08EbEPSfdQTFSpxWor2qY -pZwgF/kdVFT/EJGjpcqsY+cWK3E8Os1P7QKBwQDIPKifittCtY3PKqEv5XMF3jDY -F7lcnQhgAslmnYhQrM0PtUe0qHM7fWV5v0xv0OID7dQoTgAHIwABTwXem0QahK4J -StbtYV134voTmUy3dnI9+FOTaXjovSbLsPkB9B0gT2D1qzwZhXM08+zSZ+9WuF2T -c47ZPij/h/VKJvqxrsbTnQPj/cIkSK+FKo47W5MHOJEhrknLbeMwgRXtZevcAd87 -nUP9puHf760iQjTxP4FeVwrgVpTyKgDQzMVQZ/ECgcEAtlAMUxkHixQD/qT6CzGT -rbcYuZGmxZ1od0ld3XUziSqLVGq+MuWtVxdy85DS/fQN+FxFjkQIXOaSH6VDEK/0 -MylhqNdZo8QcHOotOeMb2qTW7OU2CtWPFbaQzbEfZMfyzfo6LrKjbrSAO7OBp+MY -aOOnEJaXunfZ5Jsbf/hfhRqF6Fpf40NIdtt2xK7eN2bUmdy0G7Paa4rBukYRHgvz -Y6lbS89WwEINcd8I+jydMzfRwqENY1B5sjQWYBOCt7F9AoHBAJg4LMQkTiy3Uhek -Q6bimf9i+uS7nElAg2Zhl/OvXDpgMv93AwzeZcNav3K/L39tXvQ3r2n4aeMDA3T7 -Ou4QQMScCqW7xAnvU5vY691MU9rAa3aaugY9TxI3ATAl2BZZGm8+iOoZg3WvUnZ1 -3JnTM0pMm66FUZnqvEYNeDYnzbqXsEScf6GpfhYRP4VPZZLQOcRqh0IAec7xOZ3c -8+tl6Nh2f9qU4mQIonuXe5molRC1A0bRis4iY9Z4geg5UuKeMQKBwQC9I4wup3tr -HoV323139uWwFcbhnjVXct81bZOJf4OfY38ICrPUumObEH8P01XpOM+QNz2FPaeX -jDPywrE4K9s5yqjQI9eJzI0CfWGbtgRpFOjJhDQ2bPuEWMyaU3SkQr0dJRu6gsD7 -IyyQuzVLW7CY0KudYW7q6ITnp2yuGywAyw8a+OJ8/UIa4hNSx1D6Zclf7UCof0YO -zvZWg28Ojjn4M1+D3r6+74xmrRbI7JjUsrJVZqKeJ2qE8TEH6L+np70= ------END RSA PRIVATE KEY----- diff --git a/test/fixtures/ca/docker-ca.pem b/test/fixtures/ca/docker-ca.pem new file mode 100644 index 00000000..ab543a31 --- /dev/null +++ b/test/fixtures/ca/docker-ca.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC0zCCAlmgAwIBAgIUCfQ+m0pgZ/BjYAJvxrn/bdGNZokwCgYIKoZIzj0EAwMw +gZYxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxBMUEgQ2FyIFdhc2gxJDAiBgNVBAsT +G0luZm9ybWF0aW9uIFRlY2hub2xvZ3kgRGVwLjEUMBIGA1UEBxMLQWxidXF1ZXJx +dWUxEzARBgNVBAgTCk5ldyBNZXhpY28xHzAdBgNVBAMTFmRvY2tlci1saWdodC1i +YXNlaW1hZ2UwHhcNMTUxMjIzMTM1MzAwWhcNMjAxMjIxMTM1MzAwWjCBljELMAkG +A1UEBhMCVVMxFTATBgNVBAoTDEExQSBDYXIgV2FzaDEkMCIGA1UECxMbSW5mb3Jt +YXRpb24gVGVjaG5vbG9neSBEZXAuMRQwEgYDVQQHEwtBbGJ1cXVlcnF1ZTETMBEG +A1UECBMKTmV3IE1leGljbzEfMB0GA1UEAxMWZG9ja2VyLWxpZ2h0LWJhc2VpbWFn +ZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMZf/12pupAgl8Sm+j8GmjNeNbSFAZWW +oTmIvf2Mu4LWPHy4bTldkQgHUbBpT3xWz8f0lB/ru7596CHsGoL2A28hxuclq5hb +Ux1yrIt3bJIY3TuiX25HGTe6kGCJPB1aLaNmMGQwDgYDVR0PAQH/BAQDAgEGMBIG +A1UdEwEB/wQIMAYBAf8CAQIwHQYDVR0OBBYEFE+l6XolXDAYnGLTl4W6ULKHrm74 +MB8GA1UdIwQYMBaAFE+l6XolXDAYnGLTl4W6ULKHrm74MAoGCCqGSM49BAMDA2gA +MGUCMQCXLZj8okyxW6UTL7hribUUbu63PbjuwIXnwi420DdNsvA9A7fcQEXScWFL +XAGC8rkCMGcqwXZPSRfwuI9r+R11gTrP92hnaVxs9sjRikctpkQpOyNlIXFPopFK +8FdfWPypvA== +-----END CERTIFICATE----- diff --git a/test/fixtures/openldap/retcode.ldif b/test/fixtures/ldif/06-retcode.ldif similarity index 92% rename from test/fixtures/openldap/retcode.ldif rename to test/fixtures/ldif/06-retcode.ldif index 9faffe1d..dfd12d06 100644 --- a/test/fixtures/openldap/retcode.ldif +++ b/test/fixtures/ldif/06-retcode.ldif @@ -1,19 +1,18 @@ -dn: cn=module,cn=config -cn: module -objectClass: olcModuleList -objectClass: top -olcModulePath: /usr/lib/ldap -olcModuleLoad: retcode.la +dn: cn=module{0},cn=config +changetype: modify +add: olcModuleLoad +olcModuleLoad: retcode # source: http://www.opensource.apple.com/source/OpenLDAP/OpenLDAP-186/OpenLDAP/tests/data/retcode.conf?txt -dn: olcOverlay={2}retcode,olcDatabase={1}hdb,cn=config +dn: olcOverlay={2}retcode,olcDatabase={1}{{ LDAP_BACKEND }},cn=config +changetype: add objectClass: olcConfig objectClass: olcRetcodeConfig objectClass: olcOverlayConfig objectClass: top olcOverlay: retcode -olcRetcodeParent: ou=Retcodes,dc=rubyldap,dc=com +olcRetcodeParent: ou=Retcodes,dc=example,dc=org olcRetcodeInDir: TRUE olcRetcodeSleep: 0 olcRetcodeItem: "cn=success" 0x00 diff --git a/test/fixtures/ldif/50-seed.ldif b/test/fixtures/ldif/50-seed.ldif new file mode 100644 index 00000000..addedf5a --- /dev/null +++ b/test/fixtures/ldif/50-seed.ldif @@ -0,0 +1,374 @@ +dn: ou=People,dc=example,dc=org +objectClass: top +objectClass: organizationalUnit +ou: People + +dn: ou=Groups,dc=example,dc=org +objectClass: top +objectClass: organizationalUnit +ou: Groups + +# Directory Superuser +dn: uid=admin,dc=example,dc=org +uid: admin +cn: system administrator +sn: administrator +objectClass: top +objectClass: person +objectClass: organizationalPerson +objectClass: inetOrgPerson +displayName: Directory Superuser +userPassword: passworD1 + +# Users 1-10 + +dn: uid=user1,ou=People,dc=example,dc=org +uid: user1 +cn: user1 +sn: user1 +objectClass: top +objectClass: person +objectClass: organizationalPerson +objectClass: inetOrgPerson +userPassword: passworD1 +mail: user1@rubyldap.com + +dn: uid=user2,ou=People,dc=example,dc=org +uid: user2 +cn: user2 +sn: user2 +objectClass: top +objectClass: person +objectClass: organizationalPerson +objectClass: inetOrgPerson +userPassword: passworD1 +mail: user2@rubyldap.com + +dn: uid=user3,ou=People,dc=example,dc=org +uid: user3 +cn: user3 +sn: user3 +objectClass: top +objectClass: person +objectClass: organizationalPerson +objectClass: inetOrgPerson +userPassword: passworD1 +mail: user3@rubyldap.com + +dn: uid=user4,ou=People,dc=example,dc=org +uid: user4 +cn: user4 +sn: user4 +objectClass: top +objectClass: person +objectClass: organizationalPerson +objectClass: inetOrgPerson +userPassword: passworD1 +mail: user4@rubyldap.com + +dn: uid=user5,ou=People,dc=example,dc=org +uid: user5 +cn: user5 +sn: user5 +objectClass: top +objectClass: person +objectClass: organizationalPerson +objectClass: inetOrgPerson +userPassword: passworD1 +mail: user5@rubyldap.com + +dn: uid=user6,ou=People,dc=example,dc=org +uid: user6 +cn: user6 +sn: user6 +objectClass: top +objectClass: person +objectClass: organizationalPerson +objectClass: inetOrgPerson +userPassword: passworD1 +mail: user6@rubyldap.com + +dn: uid=user7,ou=People,dc=example,dc=org +uid: user7 +cn: user7 +sn: user7 +objectClass: top +objectClass: person +objectClass: organizationalPerson +objectClass: inetOrgPerson +userPassword: passworD1 +mail: user7@rubyldap.com + +dn: uid=user8,ou=People,dc=example,dc=org +uid: user8 +cn: user8 +sn: user8 +objectClass: top +objectClass: person +objectClass: organizationalPerson +objectClass: inetOrgPerson +userPassword: passworD1 +mail: user8@rubyldap.com + +dn: uid=user9,ou=People,dc=example,dc=org +uid: user9 +cn: user9 +sn: user9 +objectClass: top +objectClass: person +objectClass: organizationalPerson +objectClass: inetOrgPerson +userPassword: passworD1 +mail: user9@rubyldap.com + +dn: uid=user10,ou=People,dc=example,dc=org +uid: user10 +cn: user10 +sn: user10 +objectClass: top +objectClass: person +objectClass: organizationalPerson +objectClass: inetOrgPerson +userPassword: passworD1 +mail: user10@rubyldap.com + +# Emailless User + +dn: uid=emailless-user1,ou=People,dc=example,dc=org +uid: emailless-user1 +cn: emailless-user1 +sn: emailless-user1 +objectClass: top +objectClass: person +objectClass: organizationalPerson +objectClass: inetOrgPerson +userPassword: passworD1 + +# Groupless User + +dn: uid=groupless-user1,ou=People,dc=example,dc=org +uid: groupless-user1 +cn: groupless-user1 +sn: groupless-user1 +objectClass: top +objectClass: person +objectClass: organizationalPerson +objectClass: inetOrgPerson +userPassword: passworD1 + +# Admin User + +dn: uid=admin1,ou=People,dc=example,dc=org +uid: admin1 +cn: admin1 +sn: admin1 +objectClass: top +objectClass: person +objectClass: organizationalPerson +objectClass: inetOrgPerson +userPassword: passworD1 +mail: admin1@rubyldap.com + +# Groups + +dn: cn=ghe-users,ou=Groups,dc=example,dc=org +cn: ghe-users +objectClass: groupOfNames +member: uid=user1,ou=People,dc=example,dc=org +member: uid=emailless-user1,ou=People,dc=example,dc=org + +dn: cn=all-users,ou=Groups,dc=example,dc=org +cn: all-users +objectClass: groupOfNames +member: cn=ghe-users,ou=Groups,dc=example,dc=org +member: uid=user1,ou=People,dc=example,dc=org +member: uid=user2,ou=People,dc=example,dc=org +member: uid=user3,ou=People,dc=example,dc=org +member: uid=user4,ou=People,dc=example,dc=org +member: uid=user5,ou=People,dc=example,dc=org +member: uid=user6,ou=People,dc=example,dc=org +member: uid=user7,ou=People,dc=example,dc=org +member: uid=user8,ou=People,dc=example,dc=org +member: uid=user9,ou=People,dc=example,dc=org +member: uid=user10,ou=People,dc=example,dc=org +member: uid=emailless-user1,ou=People,dc=example,dc=org + +dn: cn=ghe-admins,ou=Groups,dc=example,dc=org +cn: ghe-admins +objectClass: groupOfNames +member: uid=admin1,ou=People,dc=example,dc=org + +dn: cn=all-admins,ou=Groups,dc=example,dc=org +cn: all-admins +objectClass: groupOfNames +member: cn=ghe-admins,ou=Groups,dc=example,dc=org +member: uid=admin1,ou=People,dc=example,dc=org + +dn: cn=n-member-group10,ou=Groups,dc=example,dc=org +cn: n-member-group10 +objectClass: groupOfNames +member: uid=user1,ou=People,dc=example,dc=org +member: uid=user2,ou=People,dc=example,dc=org +member: uid=user3,ou=People,dc=example,dc=org +member: uid=user4,ou=People,dc=example,dc=org +member: uid=user5,ou=People,dc=example,dc=org +member: uid=user6,ou=People,dc=example,dc=org +member: uid=user7,ou=People,dc=example,dc=org +member: uid=user8,ou=People,dc=example,dc=org +member: uid=user9,ou=People,dc=example,dc=org +member: uid=user10,ou=People,dc=example,dc=org + +dn: cn=nested-group1,ou=Groups,dc=example,dc=org +cn: nested-group1 +objectClass: groupOfNames +member: uid=user1,ou=People,dc=example,dc=org +member: uid=user2,ou=People,dc=example,dc=org +member: uid=user3,ou=People,dc=example,dc=org +member: uid=user4,ou=People,dc=example,dc=org +member: uid=user5,ou=People,dc=example,dc=org + +dn: cn=nested-group2,ou=Groups,dc=example,dc=org +cn: nested-group2 +objectClass: groupOfNames +member: uid=user6,ou=People,dc=example,dc=org +member: uid=user7,ou=People,dc=example,dc=org +member: uid=user8,ou=People,dc=example,dc=org +member: uid=user9,ou=People,dc=example,dc=org +member: uid=user10,ou=People,dc=example,dc=org + +dn: cn=nested-groups,ou=Groups,dc=example,dc=org +cn: nested-groups +objectClass: groupOfNames +member: cn=nested-group1,ou=Groups,dc=example,dc=org +member: cn=nested-group2,ou=Groups,dc=example,dc=org + +dn: cn=n-member-nested-group1,ou=Groups,dc=example,dc=org +cn: n-member-nested-group1 +objectClass: groupOfNames +member: cn=nested-group1,ou=Groups,dc=example,dc=org + +dn: cn=deeply-nested-group0.0.0,ou=Groups,dc=example,dc=org +cn: deeply-nested-group0.0.0 +objectClass: groupOfNames +member: uid=user1,ou=People,dc=example,dc=org +member: uid=user2,ou=People,dc=example,dc=org +member: uid=user3,ou=People,dc=example,dc=org +member: uid=user4,ou=People,dc=example,dc=org +member: uid=user5,ou=People,dc=example,dc=org + +dn: cn=deeply-nested-group0.0.1,ou=Groups,dc=example,dc=org +cn: deeply-nested-group0.0.1 +objectClass: groupOfNames +member: uid=user6,ou=People,dc=example,dc=org +member: uid=user7,ou=People,dc=example,dc=org +member: uid=user8,ou=People,dc=example,dc=org +member: uid=user9,ou=People,dc=example,dc=org +member: uid=user10,ou=People,dc=example,dc=org + +dn: cn=deeply-nested-group0.0,ou=Groups,dc=example,dc=org +cn: deeply-nested-group0.0 +objectClass: groupOfNames +member: cn=deeply-nested-group0.0.0,ou=Groups,dc=example,dc=org +member: cn=deeply-nested-group0.0.1,ou=Groups,dc=example,dc=org + +dn: cn=deeply-nested-group0,ou=Groups,dc=example,dc=org +cn: deeply-nested-group0 +objectClass: groupOfNames +member: cn=deeply-nested-group0.0,ou=Groups,dc=example,dc=org + +dn: cn=deeply-nested-groups,ou=Groups,dc=example,dc=org +cn: deeply-nested-groups +objectClass: groupOfNames +member: cn=deeply-nested-group0,ou=Groups,dc=example,dc=org + +dn: cn=n-depth-nested-group1,ou=Groups,dc=example,dc=org +cn: n-depth-nested-group1 +objectClass: groupOfNames +member: cn=nested-group1,ou=Groups,dc=example,dc=org + +dn: cn=n-depth-nested-group2,ou=Groups,dc=example,dc=org +cn: n-depth-nested-group2 +objectClass: groupOfNames +member: cn=n-depth-nested-group1,ou=Groups,dc=example,dc=org + +dn: cn=n-depth-nested-group3,ou=Groups,dc=example,dc=org +cn: n-depth-nested-group3 +objectClass: groupOfNames +member: cn=n-depth-nested-group2,ou=Groups,dc=example,dc=org + +dn: cn=n-depth-nested-group4,ou=Groups,dc=example,dc=org +cn: n-depth-nested-group4 +objectClass: groupOfNames +member: cn=n-depth-nested-group3,ou=Groups,dc=example,dc=org + +dn: cn=n-depth-nested-group5,ou=Groups,dc=example,dc=org +cn: n-depth-nested-group5 +objectClass: groupOfNames +member: cn=n-depth-nested-group4,ou=Groups,dc=example,dc=org + +dn: cn=n-depth-nested-group6,ou=Groups,dc=example,dc=org +cn: n-depth-nested-group6 +objectClass: groupOfNames +member: cn=n-depth-nested-group5,ou=Groups,dc=example,dc=org + +dn: cn=n-depth-nested-group7,ou=Groups,dc=example,dc=org +cn: n-depth-nested-group7 +objectClass: groupOfNames +member: cn=n-depth-nested-group6,ou=Groups,dc=example,dc=org + +dn: cn=n-depth-nested-group8,ou=Groups,dc=example,dc=org +cn: n-depth-nested-group8 +objectClass: groupOfNames +member: cn=n-depth-nested-group7,ou=Groups,dc=example,dc=org + +dn: cn=n-depth-nested-group9,ou=Groups,dc=example,dc=org +cn: n-depth-nested-group9 +objectClass: groupOfNames +member: cn=n-depth-nested-group8,ou=Groups,dc=example,dc=org + +dn: cn=head-group,ou=Groups,dc=example,dc=org +cn: head-group +objectClass: groupOfNames +member: cn=tail-group,ou=Groups,dc=example,dc=org +member: uid=user1,ou=People,dc=example,dc=org +member: uid=user2,ou=People,dc=example,dc=org +member: uid=user3,ou=People,dc=example,dc=org +member: uid=user4,ou=People,dc=example,dc=org +member: uid=user5,ou=People,dc=example,dc=org + +dn: cn=tail-group,ou=Groups,dc=example,dc=org +cn: tail-group +objectClass: groupOfNames +member: cn=head-group,ou=Groups,dc=example,dc=org +member: uid=user6,ou=People,dc=example,dc=org +member: uid=user7,ou=People,dc=example,dc=org +member: uid=user8,ou=People,dc=example,dc=org +member: uid=user9,ou=People,dc=example,dc=org +member: uid=user10,ou=People,dc=example,dc=org + +dn: cn=recursively-nested-groups,ou=Groups,dc=example,dc=org +cn: recursively-nested-groups +objectClass: groupOfNames +member: cn=head-group,ou=Groups,dc=example,dc=org +member: cn=tail-group,ou=Groups,dc=example,dc=org + +# posixGroup + +dn: cn=posix-group1,ou=Groups,dc=example,dc=org +cn: posix-group1 +objectClass: posixGroup +gidNumber: 1001 +memberUid: user1 +memberUid: user2 +memberUid: user3 +memberUid: user4 +memberUid: user5 + +# missing members + +dn: cn=missing-users,ou=Groups,dc=example,dc=org +cn: missing-users +objectClass: groupOfNames +member: uid=user1,ou=People,dc=example,dc=org +member: uid=user2,ou=People,dc=example,dc=org +member: uid=nonexistent-user,ou=People,dc=example,dc=org diff --git a/test/fixtures/openldap/memberof.ldif b/test/fixtures/openldap/memberof.ldif deleted file mode 100644 index dac7c6b5..00000000 --- a/test/fixtures/openldap/memberof.ldif +++ /dev/null @@ -1,33 +0,0 @@ -dn: cn=module,cn=config -cn: module -objectClass: olcModuleList -objectClass: top -olcModulePath: /usr/lib/ldap -olcModuleLoad: memberof.la - -dn: olcOverlay={0}memberof,olcDatabase={1}hdb,cn=config -objectClass: olcConfig -objectClass: olcMemberOf -objectClass: olcOverlayConfig -objectClass: top -olcOverlay: memberof -olcMemberOfDangling: ignore -olcMemberOfRefInt: TRUE -olcMemberOfGroupOC: groupOfNames -olcMemberOfMemberAD: member -olcMemberOfMemberOfAD: memberOf - -dn: cn=module,cn=config -cn: module -objectclass: olcModuleList -objectclass: top -olcmoduleload: refint.la -olcmodulepath: /usr/lib/ldap - -dn: olcOverlay={1}refint,olcDatabase={1}hdb,cn=config -objectClass: olcConfig -objectClass: olcOverlayConfig -objectClass: olcRefintConfig -objectClass: top -olcOverlay: {1}refint -olcRefintAttribute: memberof member manager owner diff --git a/test/fixtures/openldap/slapd.conf.ldif b/test/fixtures/openldap/slapd.conf.ldif deleted file mode 100644 index 77a6af09..00000000 --- a/test/fixtures/openldap/slapd.conf.ldif +++ /dev/null @@ -1,67 +0,0 @@ -dn: cn=config -objectClass: olcGlobal -cn: config -olcPidFile: /var/run/slapd/slapd.pid -olcArgsFile: /var/run/slapd/slapd.args -olcLogLevel: -1 -olcToolThreads: 1 - -dn: olcDatabase={-1}frontend,cn=config -objectClass: olcDatabaseConfig -objectClass: olcFrontendConfig -olcDatabase: {-1}frontend -olcSizeLimit: 500 -olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by * break -olcAccess: {1}to dn.exact="" by * read -olcAccess: {2}to dn.base="cn=Subschema" by * read - -dn: olcDatabase=config,cn=config -objectClass: olcDatabaseConfig -olcDatabase: config -olcAccess: to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by * break - -dn: cn=schema,cn=config -objectClass: olcSchemaConfig -cn: schema - -include: file:///etc/ldap/schema/core.ldif -include: file:///etc/ldap/schema/cosine.ldif -include: file:///etc/ldap/schema/nis.ldif -include: file:///etc/ldap/schema/inetorgperson.ldif - -dn: cn=module{0},cn=config -objectClass: olcModuleList -cn: module{0} -olcModulePath: /usr/lib/ldap -olcModuleLoad: back_hdb - -dn: olcBackend=hdb,cn=config -objectClass: olcBackendConfig -olcBackend: hdb - -dn: olcDatabase=hdb,cn=config -objectClass: olcDatabaseConfig -objectClass: olcHdbConfig -olcDatabase: hdb -olcDbCheckpoint: 512 30 -olcDbConfig: set_cachesize 1 0 0 -olcDbConfig: set_lk_max_objects 1500 -olcDbConfig: set_lk_max_locks 1500 -olcDbConfig: set_lk_max_lockers 1500 -olcLastMod: TRUE -olcSuffix: dc=rubyldap,dc=com -olcDbDirectory: /var/lib/ldap -olcRootDN: cn=admin,dc=rubyldap,dc=com -# admin's password: "passworD1" -olcRootPW: {SHA}LFSkM9eegU6j3PeGG7UuHrT/KZM= -olcDbIndex: objectClass eq -olcAccess: to attrs=userPassword,shadowLastChange - by self write - by anonymous auth - by dn="cn=admin,dc=rubyldap,dc=com" write - by * none -olcAccess: to dn.base="" by * read -olcAccess: to * - by self write - by dn="cn=admin,dc=rubyldap,dc=com" write - by * read diff --git a/test/fixtures/seed.ldif b/test/fixtures/seed.ldif deleted file mode 100644 index 3ad3e293..00000000 --- a/test/fixtures/seed.ldif +++ /dev/null @@ -1,374 +0,0 @@ -dn: ou=People,dc=rubyldap,dc=com -objectClass: top -objectClass: organizationalUnit -ou: People - -dn: ou=Groups,dc=rubyldap,dc=com -objectClass: top -objectClass: organizationalUnit -ou: Groups - -# Directory Superuser -dn: uid=admin,dc=rubyldap,dc=com -uid: admin -cn: system administrator -sn: administrator -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: inetOrgPerson -displayName: Directory Superuser -userPassword: passworD1 - -# Users 1-10 - -dn: uid=user1,ou=People,dc=rubyldap,dc=com -uid: user1 -cn: user1 -sn: user1 -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: inetOrgPerson -userPassword: passworD1 -mail: user1@rubyldap.com - -dn: uid=user2,ou=People,dc=rubyldap,dc=com -uid: user2 -cn: user2 -sn: user2 -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: inetOrgPerson -userPassword: passworD1 -mail: user2@rubyldap.com - -dn: uid=user3,ou=People,dc=rubyldap,dc=com -uid: user3 -cn: user3 -sn: user3 -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: inetOrgPerson -userPassword: passworD1 -mail: user3@rubyldap.com - -dn: uid=user4,ou=People,dc=rubyldap,dc=com -uid: user4 -cn: user4 -sn: user4 -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: inetOrgPerson -userPassword: passworD1 -mail: user4@rubyldap.com - -dn: uid=user5,ou=People,dc=rubyldap,dc=com -uid: user5 -cn: user5 -sn: user5 -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: inetOrgPerson -userPassword: passworD1 -mail: user5@rubyldap.com - -dn: uid=user6,ou=People,dc=rubyldap,dc=com -uid: user6 -cn: user6 -sn: user6 -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: inetOrgPerson -userPassword: passworD1 -mail: user6@rubyldap.com - -dn: uid=user7,ou=People,dc=rubyldap,dc=com -uid: user7 -cn: user7 -sn: user7 -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: inetOrgPerson -userPassword: passworD1 -mail: user7@rubyldap.com - -dn: uid=user8,ou=People,dc=rubyldap,dc=com -uid: user8 -cn: user8 -sn: user8 -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: inetOrgPerson -userPassword: passworD1 -mail: user8@rubyldap.com - -dn: uid=user9,ou=People,dc=rubyldap,dc=com -uid: user9 -cn: user9 -sn: user9 -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: inetOrgPerson -userPassword: passworD1 -mail: user9@rubyldap.com - -dn: uid=user10,ou=People,dc=rubyldap,dc=com -uid: user10 -cn: user10 -sn: user10 -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: inetOrgPerson -userPassword: passworD1 -mail: user10@rubyldap.com - -# Emailless User - -dn: uid=emailless-user1,ou=People,dc=rubyldap,dc=com -uid: emailless-user1 -cn: emailless-user1 -sn: emailless-user1 -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: inetOrgPerson -userPassword: passworD1 - -# Groupless User - -dn: uid=groupless-user1,ou=People,dc=rubyldap,dc=com -uid: groupless-user1 -cn: groupless-user1 -sn: groupless-user1 -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: inetOrgPerson -userPassword: passworD1 - -# Admin User - -dn: uid=admin1,ou=People,dc=rubyldap,dc=com -uid: admin1 -cn: admin1 -sn: admin1 -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: inetOrgPerson -userPassword: passworD1 -mail: admin1@rubyldap.com - -# Groups - -dn: cn=ghe-users,ou=Groups,dc=rubyldap,dc=com -cn: ghe-users -objectClass: groupOfNames -member: uid=user1,ou=People,dc=rubyldap,dc=com -member: uid=emailless-user1,ou=People,dc=rubyldap,dc=com - -dn: cn=all-users,ou=Groups,dc=rubyldap,dc=com -cn: all-users -objectClass: groupOfNames -member: cn=ghe-users,ou=Groups,dc=rubyldap,dc=com -member: uid=user1,ou=People,dc=rubyldap,dc=com -member: uid=user2,ou=People,dc=rubyldap,dc=com -member: uid=user3,ou=People,dc=rubyldap,dc=com -member: uid=user4,ou=People,dc=rubyldap,dc=com -member: uid=user5,ou=People,dc=rubyldap,dc=com -member: uid=user6,ou=People,dc=rubyldap,dc=com -member: uid=user7,ou=People,dc=rubyldap,dc=com -member: uid=user8,ou=People,dc=rubyldap,dc=com -member: uid=user9,ou=People,dc=rubyldap,dc=com -member: uid=user10,ou=People,dc=rubyldap,dc=com -member: uid=emailless-user1,ou=People,dc=rubyldap,dc=com - -dn: cn=ghe-admins,ou=Groups,dc=rubyldap,dc=com -cn: ghe-admins -objectClass: groupOfNames -member: uid=admin1,ou=People,dc=rubyldap,dc=com - -dn: cn=all-admins,ou=Groups,dc=rubyldap,dc=com -cn: all-admins -objectClass: groupOfNames -member: cn=ghe-admins,ou=Groups,dc=rubyldap,dc=com -member: uid=admin1,ou=People,dc=rubyldap,dc=com - -dn: cn=n-member-group10,ou=Groups,dc=rubyldap,dc=com -cn: n-member-group10 -objectClass: groupOfNames -member: uid=user1,ou=People,dc=rubyldap,dc=com -member: uid=user2,ou=People,dc=rubyldap,dc=com -member: uid=user3,ou=People,dc=rubyldap,dc=com -member: uid=user4,ou=People,dc=rubyldap,dc=com -member: uid=user5,ou=People,dc=rubyldap,dc=com -member: uid=user6,ou=People,dc=rubyldap,dc=com -member: uid=user7,ou=People,dc=rubyldap,dc=com -member: uid=user8,ou=People,dc=rubyldap,dc=com -member: uid=user9,ou=People,dc=rubyldap,dc=com -member: uid=user10,ou=People,dc=rubyldap,dc=com - -dn: cn=nested-group1,ou=Groups,dc=rubyldap,dc=com -cn: nested-group1 -objectClass: groupOfNames -member: uid=user1,ou=People,dc=rubyldap,dc=com -member: uid=user2,ou=People,dc=rubyldap,dc=com -member: uid=user3,ou=People,dc=rubyldap,dc=com -member: uid=user4,ou=People,dc=rubyldap,dc=com -member: uid=user5,ou=People,dc=rubyldap,dc=com - -dn: cn=nested-group2,ou=Groups,dc=rubyldap,dc=com -cn: nested-group2 -objectClass: groupOfNames -member: uid=user6,ou=People,dc=rubyldap,dc=com -member: uid=user7,ou=People,dc=rubyldap,dc=com -member: uid=user8,ou=People,dc=rubyldap,dc=com -member: uid=user9,ou=People,dc=rubyldap,dc=com -member: uid=user10,ou=People,dc=rubyldap,dc=com - -dn: cn=nested-groups,ou=Groups,dc=rubyldap,dc=com -cn: nested-groups -objectClass: groupOfNames -member: cn=nested-group1,ou=Groups,dc=rubyldap,dc=com -member: cn=nested-group2,ou=Groups,dc=rubyldap,dc=com - -dn: cn=n-member-nested-group1,ou=Groups,dc=rubyldap,dc=com -cn: n-member-nested-group1 -objectClass: groupOfNames -member: cn=nested-group1,ou=Groups,dc=rubyldap,dc=com - -dn: cn=deeply-nested-group0.0.0,ou=Groups,dc=rubyldap,dc=com -cn: deeply-nested-group0.0.0 -objectClass: groupOfNames -member: uid=user1,ou=People,dc=rubyldap,dc=com -member: uid=user2,ou=People,dc=rubyldap,dc=com -member: uid=user3,ou=People,dc=rubyldap,dc=com -member: uid=user4,ou=People,dc=rubyldap,dc=com -member: uid=user5,ou=People,dc=rubyldap,dc=com - -dn: cn=deeply-nested-group0.0.1,ou=Groups,dc=rubyldap,dc=com -cn: deeply-nested-group0.0.1 -objectClass: groupOfNames -member: uid=user6,ou=People,dc=rubyldap,dc=com -member: uid=user7,ou=People,dc=rubyldap,dc=com -member: uid=user8,ou=People,dc=rubyldap,dc=com -member: uid=user9,ou=People,dc=rubyldap,dc=com -member: uid=user10,ou=People,dc=rubyldap,dc=com - -dn: cn=deeply-nested-group0.0,ou=Groups,dc=rubyldap,dc=com -cn: deeply-nested-group0.0 -objectClass: groupOfNames -member: cn=deeply-nested-group0.0.0,ou=Groups,dc=rubyldap,dc=com -member: cn=deeply-nested-group0.0.1,ou=Groups,dc=rubyldap,dc=com - -dn: cn=deeply-nested-group0,ou=Groups,dc=rubyldap,dc=com -cn: deeply-nested-group0 -objectClass: groupOfNames -member: cn=deeply-nested-group0.0,ou=Groups,dc=rubyldap,dc=com - -dn: cn=deeply-nested-groups,ou=Groups,dc=rubyldap,dc=com -cn: deeply-nested-groups -objectClass: groupOfNames -member: cn=deeply-nested-group0,ou=Groups,dc=rubyldap,dc=com - -dn: cn=n-depth-nested-group1,ou=Groups,dc=rubyldap,dc=com -cn: n-depth-nested-group1 -objectClass: groupOfNames -member: cn=nested-group1,ou=Groups,dc=rubyldap,dc=com - -dn: cn=n-depth-nested-group2,ou=Groups,dc=rubyldap,dc=com -cn: n-depth-nested-group2 -objectClass: groupOfNames -member: cn=n-depth-nested-group1,ou=Groups,dc=rubyldap,dc=com - -dn: cn=n-depth-nested-group3,ou=Groups,dc=rubyldap,dc=com -cn: n-depth-nested-group3 -objectClass: groupOfNames -member: cn=n-depth-nested-group2,ou=Groups,dc=rubyldap,dc=com - -dn: cn=n-depth-nested-group4,ou=Groups,dc=rubyldap,dc=com -cn: n-depth-nested-group4 -objectClass: groupOfNames -member: cn=n-depth-nested-group3,ou=Groups,dc=rubyldap,dc=com - -dn: cn=n-depth-nested-group5,ou=Groups,dc=rubyldap,dc=com -cn: n-depth-nested-group5 -objectClass: groupOfNames -member: cn=n-depth-nested-group4,ou=Groups,dc=rubyldap,dc=com - -dn: cn=n-depth-nested-group6,ou=Groups,dc=rubyldap,dc=com -cn: n-depth-nested-group6 -objectClass: groupOfNames -member: cn=n-depth-nested-group5,ou=Groups,dc=rubyldap,dc=com - -dn: cn=n-depth-nested-group7,ou=Groups,dc=rubyldap,dc=com -cn: n-depth-nested-group7 -objectClass: groupOfNames -member: cn=n-depth-nested-group6,ou=Groups,dc=rubyldap,dc=com - -dn: cn=n-depth-nested-group8,ou=Groups,dc=rubyldap,dc=com -cn: n-depth-nested-group8 -objectClass: groupOfNames -member: cn=n-depth-nested-group7,ou=Groups,dc=rubyldap,dc=com - -dn: cn=n-depth-nested-group9,ou=Groups,dc=rubyldap,dc=com -cn: n-depth-nested-group9 -objectClass: groupOfNames -member: cn=n-depth-nested-group8,ou=Groups,dc=rubyldap,dc=com - -dn: cn=head-group,ou=Groups,dc=rubyldap,dc=com -cn: head-group -objectClass: groupOfNames -member: cn=tail-group,ou=Groups,dc=rubyldap,dc=com -member: uid=user1,ou=People,dc=rubyldap,dc=com -member: uid=user2,ou=People,dc=rubyldap,dc=com -member: uid=user3,ou=People,dc=rubyldap,dc=com -member: uid=user4,ou=People,dc=rubyldap,dc=com -member: uid=user5,ou=People,dc=rubyldap,dc=com - -dn: cn=tail-group,ou=Groups,dc=rubyldap,dc=com -cn: tail-group -objectClass: groupOfNames -member: cn=head-group,ou=Groups,dc=rubyldap,dc=com -member: uid=user6,ou=People,dc=rubyldap,dc=com -member: uid=user7,ou=People,dc=rubyldap,dc=com -member: uid=user8,ou=People,dc=rubyldap,dc=com -member: uid=user9,ou=People,dc=rubyldap,dc=com -member: uid=user10,ou=People,dc=rubyldap,dc=com - -dn: cn=recursively-nested-groups,ou=Groups,dc=rubyldap,dc=com -cn: recursively-nested-groups -objectClass: groupOfNames -member: cn=head-group,ou=Groups,dc=rubyldap,dc=com -member: cn=tail-group,ou=Groups,dc=rubyldap,dc=com - -# posixGroup - -dn: cn=posix-group1,ou=Groups,dc=rubyldap,dc=com -cn: posix-group1 -objectClass: posixGroup -gidNumber: 1001 -memberUid: user1 -memberUid: user2 -memberUid: user3 -memberUid: user4 -memberUid: user5 - -# missing members - -dn: cn=missing-users,ou=Groups,dc=rubyldap,dc=com -cn: missing-users -objectClass: groupOfNames -member: uid=user1,ou=People,dc=rubyldap,dc=com -member: uid=user2,ou=People,dc=rubyldap,dc=com -member: uid=nonexistent-user,ou=People,dc=rubyldap,dc=com diff --git a/test/integration/test_add.rb b/test/integration/test_add.rb index dcac6149..108fd93b 100644 --- a/test/integration/test_add.rb +++ b/test/integration/test_add.rb @@ -3,9 +3,7 @@ class TestAddIntegration < LDAPIntegrationTestCase def setup super - @ldap.authenticate "cn=admin,dc=rubyldap,dc=com", "passworD1" - - @dn = "uid=added-user1,ou=People,dc=rubyldap,dc=com" + @dn = "uid=added-user1,ou=People,dc=example,dc=org" end def test_add diff --git a/test/integration/test_ber.rb b/test/integration/test_ber.rb index 51e93334..4464bf78 100644 --- a/test/integration/test_ber.rb +++ b/test/integration/test_ber.rb @@ -8,7 +8,7 @@ def test_true_ber_encoding attrs = [:dn, :uid, :cn, :mail] assert types_entry = @ldap.search( - base: "dc=rubyldap,dc=com", + base: "dc=example,dc=org", filter: "(uid=user1)", size: 1, attributes: attrs, @@ -25,6 +25,6 @@ def test_true_ber_encoding end assert_includes Net::LDAP::ResultCodesSearchSuccess, - @ldap.get_operation_result.code, "should be a successful search operation" + @ldap.get_operation_result.code, "should be a successful search operation" end end diff --git a/test/integration/test_bind.rb b/test/integration/test_bind.rb index bd1281e2..4a1a0194 100644 --- a/test/integration/test_bind.rb +++ b/test/integration/test_bind.rb @@ -1,13 +1,16 @@ require_relative '../test_helper' class TestBindIntegration < LDAPIntegrationTestCase + INTEGRATION_HOSTNAME = 'ldap.example.org'.freeze + def test_bind_success assert @ldap.bind(BIND_CREDS), @ldap.get_operation_result.inspect end def test_bind_timeout - @ldap.port = 8389 + @ldap.host = "10.255.255.1" # non-routable IP + error = assert_raise Net::LDAP::Error do @ldap.bind BIND_CREDS end @@ -24,7 +27,7 @@ def test_bind_anonymous_fail assert_equal Net::LDAP::ResultCodeUnwillingToPerform, result.code assert_equal Net::LDAP::ResultStrings[Net::LDAP::ResultCodeUnwillingToPerform], result.message assert_equal "unauthenticated bind (DN with no password) disallowed", - result.error_message + result.error_message assert_equal "", result.matched_dn end @@ -34,6 +37,8 @@ def test_bind_fail end def test_bind_tls_with_cafile + omit "We need to update our CA cert" + @ldap.host = INTEGRATION_HOSTNAME @ldap.encryption( method: :start_tls, tls_options: TLS_OPTS.merge(ca_file: CA_FILE), @@ -43,7 +48,7 @@ def test_bind_tls_with_cafile end def test_bind_tls_with_bad_hostname_verify_none_no_ca_passes - @ldap.host = '127.0.0.1' + @ldap.host = INTEGRATION_HOSTNAME @ldap.encryption( method: :start_tls, tls_options: { verify_mode: OpenSSL::SSL::VERIFY_NONE }, @@ -53,7 +58,7 @@ def test_bind_tls_with_bad_hostname_verify_none_no_ca_passes end def test_bind_tls_with_bad_hostname_verify_none_no_ca_opt_merge_passes - @ldap.host = '127.0.0.1' + @ldap.host = 'cert.mismatch.example.org' @ldap.encryption( method: :start_tls, tls_options: TLS_OPTS.merge(verify_mode: OpenSSL::SSL::VERIFY_NONE), @@ -63,14 +68,15 @@ def test_bind_tls_with_bad_hostname_verify_none_no_ca_opt_merge_passes end def test_bind_tls_with_bad_hostname_verify_peer_ca_fails - @ldap.host = '127.0.0.1' + omit "We need to update our CA cert" + @ldap.host = 'cert.mismatch.example.org' @ldap.encryption( method: :start_tls, tls_options: { verify_mode: OpenSSL::SSL::VERIFY_PEER, ca_file: CA_FILE }, ) error = assert_raise Net::LDAP::Error, - Net::LDAP::ConnectionRefusedError do + Errno::ECONNREFUSED do @ldap.bind BIND_CREDS end assert_equal( @@ -80,13 +86,14 @@ def test_bind_tls_with_bad_hostname_verify_peer_ca_fails end def test_bind_tls_with_bad_hostname_ca_default_opt_merge_fails - @ldap.host = '127.0.0.1' + omit "We need to update our CA cert" + @ldap.host = 'cert.mismatch.example.org' @ldap.encryption( method: :start_tls, tls_options: TLS_OPTS.merge(ca_file: CA_FILE), ) error = assert_raise Net::LDAP::Error, - Net::LDAP::ConnectionRefusedError do + Errno::ECONNREFUSED do @ldap.bind BIND_CREDS end assert_equal( @@ -96,13 +103,14 @@ def test_bind_tls_with_bad_hostname_ca_default_opt_merge_fails end def test_bind_tls_with_bad_hostname_ca_no_opt_merge_fails - @ldap.host = '127.0.0.1' + omit "We need to update our CA cert" + @ldap.host = 'cert.mismatch.example.org' @ldap.encryption( method: :start_tls, tls_options: { ca_file: CA_FILE }, ) error = assert_raise Net::LDAP::Error, - Net::LDAP::ConnectionRefusedError do + Errno::ECONNREFUSED do @ldap.bind BIND_CREDS end assert_equal( @@ -112,7 +120,8 @@ def test_bind_tls_with_bad_hostname_ca_no_opt_merge_fails end def test_bind_tls_with_valid_hostname_default_opts_passes - @ldap.host = 'localhost' + omit "We need to update our CA cert" + @ldap.host = INTEGRATION_HOSTNAME @ldap.encryption( method: :start_tls, tls_options: TLS_OPTS.merge(verify_mode: OpenSSL::SSL::VERIFY_PEER, @@ -123,7 +132,8 @@ def test_bind_tls_with_valid_hostname_default_opts_passes end def test_bind_tls_with_valid_hostname_just_verify_peer_ca_passes - @ldap.host = 'localhost' + omit "We need to update our CA cert" + @ldap.host = INTEGRATION_HOSTNAME @ldap.encryption( method: :start_tls, tls_options: { verify_mode: OpenSSL::SSL::VERIFY_PEER, @@ -134,10 +144,10 @@ def test_bind_tls_with_valid_hostname_just_verify_peer_ca_passes end def test_bind_tls_with_bogus_hostname_system_ca_fails - @ldap.host = '127.0.0.1' + @ldap.host = 'cert.mismatch.example.org' @ldap.encryption(method: :start_tls, tls_options: {}) error = assert_raise Net::LDAP::Error, - Net::LDAP::ConnectionRefusedError do + Errno::ECONNREFUSED do @ldap.bind BIND_CREDS end assert_equal( @@ -146,13 +156,10 @@ def test_bind_tls_with_bogus_hostname_system_ca_fails ) end - # The following depend on /etc/hosts hacking. - # We can do that on CI, but it's less than cool on people's dev boxes def test_bind_tls_with_multiple_hosts - omit_unless ENV['TRAVIS'] == 'true' - + omit "We need to update our CA cert" @ldap.host = nil - @ldap.hosts = [['ldap01.example.com', 389], ['ldap02.example.com', 389]] + @ldap.hosts = [[INTEGRATION_HOSTNAME, 389], [INTEGRATION_HOSTNAME, 389]] @ldap.encryption( method: :start_tls, tls_options: TLS_OPTS.merge(verify_mode: OpenSSL::SSL::VERIFY_PEER, @@ -163,10 +170,9 @@ def test_bind_tls_with_multiple_hosts end def test_bind_tls_with_multiple_bogus_hosts - omit_unless ENV['TRAVIS'] == 'true' - + # omit "We need to update our CA cert" @ldap.host = nil - @ldap.hosts = [['127.0.0.1', 389], ['bogus.example.com', 389]] + @ldap.hosts = [['cert.mismatch.example.org', 389], ['bogus.example.com', 389]] @ldap.encryption( method: :start_tls, tls_options: TLS_OPTS.merge(verify_mode: OpenSSL::SSL::VERIFY_PEER, @@ -181,10 +187,9 @@ def test_bind_tls_with_multiple_bogus_hosts end def test_bind_tls_with_multiple_bogus_hosts_no_verification - omit_unless ENV['TRAVIS'] == 'true' - + omit "We need to update our CA cert" @ldap.host = nil - @ldap.hosts = [['127.0.0.1', 389], ['bogus.example.com', 389]] + @ldap.hosts = [['cert.mismatch.example.org', 389], ['bogus.example.com', 389]] @ldap.encryption( method: :start_tls, tls_options: TLS_OPTS.merge(verify_mode: OpenSSL::SSL::VERIFY_NONE), @@ -194,10 +199,8 @@ def test_bind_tls_with_multiple_bogus_hosts_no_verification end def test_bind_tls_with_multiple_bogus_hosts_ca_check_only_fails - omit_unless ENV['TRAVIS'] == 'true' - @ldap.host = nil - @ldap.hosts = [['127.0.0.1', 389], ['bogus.example.com', 389]] + @ldap.hosts = [['cert.mismatch.example.org', 389], ['bogus.example.com', 389]] @ldap.encryption( method: :start_tls, tls_options: { ca_file: CA_FILE }, @@ -213,8 +216,10 @@ def test_bind_tls_with_multiple_bogus_hosts_ca_check_only_fails # This test is CI-only because we can't add the fixture CA # to the system CA store on people's dev boxes. def test_bind_tls_valid_hostname_system_ca_on_travis_passes + omit "not sure how to install custom CA cert in travis" omit_unless ENV['TRAVIS'] == 'true' + @ldap.host = INTEGRATION_HOSTNAME @ldap.encryption( method: :start_tls, tls_options: { verify_mode: OpenSSL::SSL::VERIFY_PEER }, @@ -222,23 +227,4 @@ def test_bind_tls_valid_hostname_system_ca_on_travis_passes assert @ldap.bind(BIND_CREDS), @ldap.get_operation_result.inspect end - - # Inverse of the above! Don't run this on Travis, only on Vagrant. - # Since Vagrant's hypervisor *won't* have the CA in the system - # x509 store, we can assume validation will fail - def test_bind_tls_valid_hostname_system_on_vagrant_fails - omit_if ENV['TRAVIS'] == 'true' - - @ldap.encryption( - method: :start_tls, - tls_options: { verify_mode: OpenSSL::SSL::VERIFY_PEER }, - ) - error = assert_raise Net::LDAP::Error do - @ldap.bind BIND_CREDS - end - assert_equal( - "SSL_connect returned=1 errno=0 state=error: certificate verify failed", - error.message, - ) - end end diff --git a/test/integration/test_delete.rb b/test/integration/test_delete.rb index 0cca32a9..20e3414c 100644 --- a/test/integration/test_delete.rb +++ b/test/integration/test_delete.rb @@ -3,9 +3,7 @@ class TestDeleteIntegration < LDAPIntegrationTestCase def setup super - @ldap.authenticate "cn=admin,dc=rubyldap,dc=com", "passworD1" - - @dn = "uid=delete-user1,ou=People,dc=rubyldap,dc=com" + @dn = "uid=delete-user1,ou=People,dc=example,dc=org" attrs = { objectclass: %w(top inetOrgPerson organizationalPerson person), @@ -18,6 +16,29 @@ def setup assert @ldap.add(dn: @dn, attributes: attrs), @ldap.get_operation_result.inspect end assert @ldap.search(base: @dn, scope: Net::LDAP::SearchScope_BaseObject) + + @parent_dn = "uid=parent,ou=People,dc=example,dc=org" + parent_attrs = { + objectclass: %w(top inetOrgPerson organizationalPerson person), + uid: "parent", + cn: "parent", + sn: "parent", + mail: "parent@rubyldap.com", + } + @child_dn = "uid=child,uid=parent,ou=People,dc=example,dc=org" + child_attrs = { + objectclass: %w(top inetOrgPerson organizationalPerson person), + uid: "child", + cn: "child", + sn: "child", + mail: "child@rubyldap.com", + } + unless @ldap.search(base: @parent_dn, scope: Net::LDAP::SearchScope_BaseObject) + assert @ldap.add(dn: @parent_dn, attributes: parent_attrs), @ldap.get_operation_result.inspect + assert @ldap.add(dn: @child_dn, attributes: child_attrs), @ldap.get_operation_result.inspect + end + assert @ldap.search(base: @parent_dn, scope: Net::LDAP::SearchScope_BaseObject) + assert @ldap.search(base: @child_dn, scope: Net::LDAP::SearchScope_BaseObject) end def test_delete @@ -28,4 +49,14 @@ def test_delete assert_equal Net::LDAP::ResultCodeNoSuchObject, result.code assert_equal Net::LDAP::ResultStrings[Net::LDAP::ResultCodeNoSuchObject], result.message end + + def test_delete_tree + assert @ldap.delete_tree(dn: @parent_dn), @ldap.get_operation_result.inspect + refute @ldap.search(base: @parent_dn, scope: Net::LDAP::SearchScope_BaseObject) + refute @ldap.search(base: @child_dn, scope: Net::LDAP::SearchScope_BaseObject) + + result = @ldap.get_operation_result + assert_equal Net::LDAP::ResultCodeNoSuchObject, result.code + assert_equal Net::LDAP::ResultStrings[Net::LDAP::ResultCodeNoSuchObject], result.message + end end diff --git a/test/integration/test_open.rb b/test/integration/test_open.rb index a7ac09da..9ce36d72 100644 --- a/test/integration/test_open.rb +++ b/test/integration/test_open.rb @@ -4,8 +4,8 @@ class TestBindIntegration < LDAPIntegrationTestCase def test_binds_without_open events = @service.subscribe "bind.net_ldap_connection" - @ldap.search(filter: "uid=user1", base: "ou=People,dc=rubyldap,dc=com", ignore_server_caps: true) - @ldap.search(filter: "uid=user1", base: "ou=People,dc=rubyldap,dc=com", ignore_server_caps: true) + @ldap.search(filter: "uid=user1", base: "ou=People,dc=example,dc=org", ignore_server_caps: true) + @ldap.search(filter: "uid=user1", base: "ou=People,dc=example,dc=org", ignore_server_caps: true) assert_equal 2, events.size end @@ -14,8 +14,8 @@ def test_binds_with_open events = @service.subscribe "bind.net_ldap_connection" @ldap.open do - @ldap.search(filter: "uid=user1", base: "ou=People,dc=rubyldap,dc=com", ignore_server_caps: true) - @ldap.search(filter: "uid=user1", base: "ou=People,dc=rubyldap,dc=com", ignore_server_caps: true) + @ldap.search(filter: "uid=user1", base: "ou=People,dc=example,dc=org", ignore_server_caps: true) + @ldap.search(filter: "uid=user1", base: "ou=People,dc=example,dc=org", ignore_server_caps: true) end assert_equal 1, events.size @@ -29,9 +29,9 @@ def test_nested_search_without_open entries = [] nested_entry = nil - @ldap.search(filter: "(|(uid=user1)(uid=user2))", base: "ou=People,dc=rubyldap,dc=com") do |entry| + @ldap.search(filter: "(|(uid=user1)(uid=user2))", base: "ou=People,dc=example,dc=org") do |entry| entries << entry.uid.first - nested_entry ||= @ldap.search(filter: "uid=user3", base: "ou=People,dc=rubyldap,dc=com").first + nested_entry ||= @ldap.search(filter: "uid=user3", base: "ou=People,dc=example,dc=org").first end assert_equal "user3", nested_entry.uid.first @@ -43,9 +43,9 @@ def test_nested_search_with_open nested_entry = nil @ldap.open do - @ldap.search(filter: "(|(uid=user1)(uid=user2))", base: "ou=People,dc=rubyldap,dc=com") do |entry| + @ldap.search(filter: "(|(uid=user1)(uid=user2))", base: "ou=People,dc=example,dc=org") do |entry| entries << entry.uid.first - nested_entry ||= @ldap.search(filter: "uid=user3", base: "ou=People,dc=rubyldap,dc=com").first + nested_entry ||= @ldap.search(filter: "uid=user3", base: "ou=People,dc=example,dc=org").first end end @@ -57,7 +57,7 @@ def test_nested_add_with_open entries = [] nested_entry = nil - dn = "uid=nested-open-added-user1,ou=People,dc=rubyldap,dc=com" + dn = "uid=nested-open-added-user1,ou=People,dc=example,dc=org" attrs = { objectclass: %w(top inetOrgPerson organizationalPerson person), uid: "nested-open-added-user1", @@ -66,11 +66,10 @@ def test_nested_add_with_open mail: "nested-open-added-user1@rubyldap.com", } - @ldap.authenticate "cn=admin,dc=rubyldap,dc=com", "passworD1" @ldap.delete dn: dn @ldap.open do - @ldap.search(filter: "(|(uid=user1)(uid=user2))", base: "ou=People,dc=rubyldap,dc=com") do |entry| + @ldap.search(filter: "(|(uid=user1)(uid=user2))", base: "ou=People,dc=example,dc=org") do |entry| entries << entry.uid.first nested_entry ||= begin diff --git a/test/integration/test_password_modify.rb b/test/integration/test_password_modify.rb index ed8d4f5b..e7d8d670 100644 --- a/test/integration/test_password_modify.rb +++ b/test/integration/test_password_modify.rb @@ -1,12 +1,19 @@ require_relative '../test_helper' class TestPasswordModifyIntegration < LDAPIntegrationTestCase + # see: https://www.rfc-editor.org/rfc/rfc3062#section-2 + PASSWORD_MODIFY_SYNTAX = Net::BER.compile_syntax( + application: {}, + universal: {}, + context_specific: { primitive: { 0 => :string } }, + ) + def setup super - @admin_account = {dn: 'cn=admin,dc=rubyldap,dc=com', password: 'passworD1', method: :simple} + @admin_account = { dn: 'cn=admin,dc=example,dc=org', password: 'admin', method: :simple } @ldap.authenticate @admin_account[:dn], @admin_account[:password] - @dn = 'uid=modify-password-user1,ou=People,dc=rubyldap,dc=com' + @dn = 'uid=modify-password-user1,ou=People,dc=example,dc=org' attrs = { objectclass: %w(top inetOrgPerson organizationalPerson person), @@ -14,7 +21,7 @@ def setup cn: 'modify-password-user1', sn: 'modify-password-user1', mail: 'modify-password-user1@rubyldap.com', - userPassword: 'passworD1', + userPassword: 'admin', } unless @ldap.search(base: @dn, scope: Net::LDAP::SearchScope_BaseObject) assert @ldap.add(dn: @dn, attributes: attrs), @ldap.get_operation_result.inspect @@ -24,55 +31,66 @@ def setup @auth = { method: :simple, username: @dn, - password: 'passworD1', + password: 'admin', } end def test_password_modify assert @ldap.password_modify(dn: @dn, auth: @auth, - old_password: 'passworD1', + old_password: 'admin', new_password: 'passworD2') assert @ldap.get_operation_result.extended_response.nil?, - 'Should not have generated a new password' + 'Should not have generated a new password' - refute @ldap.bind(username: @dn, password: 'passworD1', method: :simple), - 'Old password should no longer be valid' + refute @ldap.bind(username: @dn, password: 'admin', method: :simple), + 'Old password should no longer be valid' assert @ldap.bind(username: @dn, password: 'passworD2', method: :simple), - 'New password should be valid' + 'New password should be valid' end def test_password_modify_generate assert @ldap.password_modify(dn: @dn, auth: @auth, - old_password: 'passworD1') + old_password: 'admin') - generated_password = @ldap.get_operation_result.extended_response[0][0] + passwd_modify_response_value = @ldap.get_operation_result.extended_response + seq = Net::BER::BerIdentifiedArray.new + sio = StringIO.new(passwd_modify_response_value) + until (e = sio.read_ber(PASSWORD_MODIFY_SYNTAX)).nil? + seq << e + end + generated_password = seq[0][0] assert generated_password, 'Should have generated a password' - refute @ldap.bind(username: @dn, password: 'passworD1', method: :simple), - 'Old password should no longer be valid' + refute @ldap.bind(username: @dn, password: 'admin', method: :simple), + 'Old password should no longer be valid' assert @ldap.bind(username: @dn, password: generated_password, method: :simple), - 'New password should be valid' + 'New password should be valid' end def test_password_modify_generate_no_old_password assert @ldap.password_modify(dn: @dn, auth: @auth) - generated_password = @ldap.get_operation_result.extended_response[0][0] - + passwd_modify_response_value = @ldap.get_operation_result.extended_response + seq = Net::BER::BerIdentifiedArray.new + sio = StringIO.new(passwd_modify_response_value) + until (e = sio.read_ber(PASSWORD_MODIFY_SYNTAX)).nil? + seq << e + end + generated_password = seq[0][0] assert generated_password, 'Should have generated a password' - refute @ldap.bind(username: @dn, password: 'passworD1', method: :simple), - 'Old password should no longer be valid' + refute @ldap.bind(username: @dn, password: 'admin', method: :simple), + 'Old password should no longer be valid' assert @ldap.bind(username: @dn, password: generated_password, method: :simple), - 'New password should be valid' + 'New password should be valid' end def test_password_modify_overwrite_old_password @@ -80,11 +98,11 @@ def test_password_modify_overwrite_old_password auth: @admin_account, new_password: 'passworD3') - refute @ldap.bind(username: @dn, password: 'passworD1', method: :simple), - 'Old password should no longer be valid' + refute @ldap.bind(username: @dn, password: 'admin', method: :simple), + 'Old password should no longer be valid' assert @ldap.bind(username: @dn, password: 'passworD3', method: :simple), - 'New password should be valid' + 'New password should be valid' end def teardown diff --git a/test/integration/test_return_codes.rb b/test/integration/test_return_codes.rb index 0e381a0a..30057a2a 100644 --- a/test/integration/test_return_codes.rb +++ b/test/integration/test_return_codes.rb @@ -4,8 +4,16 @@ # See: section 12.12 http://www.openldap.org/doc/admin24/overlays.html class TestReturnCodeIntegration < LDAPIntegrationTestCase + def test_open_error + @ldap.authenticate "cn=fake", "creds" + @ldap.open do + result = @ldap.get_operation_result + assert_equal Net::LDAP::ResultCodeInvalidCredentials, result.code + end + end + def test_operations_error - refute @ldap.search(filter: "cn=operationsError", base: "ou=Retcodes,dc=rubyldap,dc=com") + refute @ldap.search(filter: "cn=operationsError", base: "ou=Retcodes,dc=example,dc=org") assert result = @ldap.get_operation_result assert_equal Net::LDAP::ResultCodeOperationsError, result.code @@ -13,7 +21,7 @@ def test_operations_error end def test_protocol_error - refute @ldap.search(filter: "cn=protocolError", base: "ou=Retcodes,dc=rubyldap,dc=com") + refute @ldap.search(filter: "cn=protocolError", base: "ou=Retcodes,dc=example,dc=org") assert result = @ldap.get_operation_result assert_equal Net::LDAP::ResultCodeProtocolError, result.code @@ -21,7 +29,7 @@ def test_protocol_error end def test_time_limit_exceeded - assert @ldap.search(filter: "cn=timeLimitExceeded", base: "ou=Retcodes,dc=rubyldap,dc=com") + assert @ldap.search(filter: "cn=timeLimitExceeded", base: "ou=Retcodes,dc=example,dc=org") assert result = @ldap.get_operation_result assert_equal Net::LDAP::ResultCodeTimeLimitExceeded, result.code @@ -29,7 +37,7 @@ def test_time_limit_exceeded end def test_size_limit_exceeded - assert @ldap.search(filter: "cn=sizeLimitExceeded", base: "ou=Retcodes,dc=rubyldap,dc=com") + assert @ldap.search(filter: "cn=sizeLimitExceeded", base: "ou=Retcodes,dc=example,dc=org") assert result = @ldap.get_operation_result assert_equal Net::LDAP::ResultCodeSizeLimitExceeded, result.code diff --git a/test/integration/test_search.rb b/test/integration/test_search.rb index 96f9ff42..1f562c22 100644 --- a/test/integration/test_search.rb +++ b/test/integration/test_search.rb @@ -4,7 +4,7 @@ class TestSearchIntegration < LDAPIntegrationTestCase def test_search entries = [] - result = @ldap.search(base: "dc=rubyldap,dc=com") do |entry| + result = @ldap.search(base: "dc=example,dc=org") do |entry| assert_kind_of Net::LDAP::Entry, entry entries << entry end @@ -16,7 +16,7 @@ def test_search def test_search_without_result entries = [] - result = @ldap.search(base: "dc=rubyldap,dc=com", return_result: false) do |entry| + result = @ldap.search(base: "dc=example,dc=org", return_result: false) do |entry| assert_kind_of Net::LDAP::Entry, entry entries << entry end @@ -26,24 +26,24 @@ def test_search_without_result end def test_search_filter_string - entries = @ldap.search(base: "dc=rubyldap,dc=com", filter: "(uid=user1)") + entries = @ldap.search(base: "dc=example,dc=org", filter: "(uid=user1)") assert_equal 1, entries.size end def test_search_filter_object filter = Net::LDAP::Filter.eq("uid", "user1") | Net::LDAP::Filter.eq("uid", "user2") - entries = @ldap.search(base: "dc=rubyldap,dc=com", filter: filter) + entries = @ldap.search(base: "dc=example,dc=org", filter: filter) assert_equal 2, entries.size end def test_search_constrained_attributes - entry = @ldap.search(base: "uid=user1,ou=People,dc=rubyldap,dc=com", attributes: ["cn", "sn"]).first + entry = @ldap.search(base: "uid=user1,ou=People,dc=example,dc=org", attributes: ["cn", "sn"]).first assert_equal [:cn, :dn, :sn], entry.attribute_names.sort # :dn is always included assert_empty entry[:mail] end def test_search_attributes_only - entry = @ldap.search(base: "uid=user1,ou=People,dc=rubyldap,dc=com", attributes_only: true).first + entry = @ldap.search(base: "uid=user1,ou=People,dc=example,dc=org", attributes_only: true).first assert_empty entry[:cn], "unexpected attribute value: #{entry[:cn]}" end @@ -52,7 +52,7 @@ def test_search_timeout entries = [] events = @service.subscribe "search.net_ldap_connection" - result = @ldap.search(base: "dc=rubyldap,dc=com", time: 5) do |entry| + result = @ldap.search(base: "dc=example,dc=org", time: 5) do |entry| assert_kind_of Net::LDAP::Entry, entry entries << entry end @@ -66,7 +66,7 @@ def test_search_timeout def test_search_with_size entries = [] - result = @ldap.search(base: "dc=rubyldap,dc=com", size: 1) do |entry| + result = @ldap.search(base: "dc=example,dc=org", size: 1) do |entry| assert_kind_of Net::LDAP::Entry, entry entries << entry end diff --git a/test/support/vm/openldap/README.md b/test/support/vm/openldap/README.md deleted file mode 100644 index f79f4dc6..00000000 --- a/test/support/vm/openldap/README.md +++ /dev/null @@ -1,64 +0,0 @@ -# Local OpenLDAP Integration Testing - -Set up a [Vagrant](http://www.vagrantup.com/) VM to run integration -tests against OpenLDAP locally. *NOTE*: To support some of the SSL tests, -Vagrant forwards localhost port 9389 to VM host port 9389. The port mapping -goes away when you run `vagrant destroy`. - -## Install Vagrant - -*NOTE*: The Vagrant gem (`gem install vagrant`) is -[no longer supported](https://www.vagrantup.com/docs/installation/). If you've -previously installed it, run `gem uninstall vagrant`. If you're an rbenv -user, you probably want to follow that up with `rbenv rehash; hash -r`. - -If you use Homebrew on macOS: -``` bash -$ brew update -$ brew cask install virtualbox -$ brew cask install vagrant -$ brew cask install vagrant-manager -$ vagrant plugin install vagrant-vbguest -``` - -Installing Vagrant and virtualbox on other operating systems is left -as an exercise to the reader. Note the `vagrant-vbguest` plugin is required -to update the VirtualBox guest extensions in the guest VM image. - -## Run the tests - -``` bash -# start VM (from the correct directory) -$ cd test/support/vm/openldap/ -$ vagrant up - -# get the IP address of the VM -$ ip=$(vagrant ssh -- "ifconfig eth1 | grep -o -E '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | head -n1") - -# change back to root project directory -$ cd ../../../.. - -# set the TCP port for testing -$ export INTEGRATION_PORT=9389 - -# run all tests, including integration tests -$ time INTEGRATION=openldap INTEGRATION_HOST=$ip bundle exec rake - -# run a specific integration test file -$ time INTEGRATION=openldap INTEGRATION_HOST=$ip bundle exec ruby test/integration/test_search.rb - -# run integration tests by default -$ export INTEGRATION=openldap -$ export INTEGRATION_HOST=$ip - -# now run tests without having to set ENV variables -$ time bundle exec rake - -# Once you're all done -$ cd test/support/vm/openldap -$ vagrant destroy -``` - -If at any point your VM appears to have broken itself, `vagrant destroy` -from the `test/support/vm/openldap` directory will blow it away. You can -then do `vagrant up` and start over. diff --git a/test/support/vm/openldap/Vagrantfile b/test/support/vm/openldap/Vagrantfile deleted file mode 100644 index 1f375e76..00000000 --- a/test/support/vm/openldap/Vagrantfile +++ /dev/null @@ -1,34 +0,0 @@ -# -*- mode: ruby -*- -# vi: set ft=ruby : - -# Vagrantfile API/syntax version. Don't touch unless you know what you're doing! -VAGRANTFILE_API_VERSION = "2" - -Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| - config.vm.hostname = "rubyldap.com" - - config.vm.box = "hashicorp/precise64" - - config.vm.network "private_network", type: :dhcp - config.vm.network "forwarded_port", guest: 389, host: 9389 - - config.ssh.forward_agent = true - - config.vm.provision "shell", inline: "apt-get update; exec env /vagrant_data/script/install-openldap" - - config.vm.synced_folder "../../../..", "/vagrant_data" - - config.vm.provider "vmware_fusion" do |vb, override| - override.vm.box = "hashicorp/precise64" - vb.memory = 4596 - vb.vmx["displayname"] = "integration tests vm" - vb.vmx["numvcpus"] = "2" - end - - config.vm.provider "virtualbox" do |vb, override| - vb.memory = 4096 - vb.customize ["modifyvm", :id, "--nicpromisc2", "allow-all"] - vb.customize ["modifyvm", :id, "--chipset", "ich9"] - vb.customize ["modifyvm", :id, "--vram", "16"] - end -end diff --git a/test/test_dn.rb b/test/test_dn.rb index 5fff6ae8..52e87bd7 100644 --- a/test/test_dn.rb +++ b/test/test_dn.rb @@ -1,11 +1,25 @@ require_relative 'test_helper' -require 'net/ldap/dn' +require_relative '../lib/net/ldap/dn' class TestDN < Test::Unit::TestCase def test_escape assert_equal '\\,\\+\\"\\\\\\<\\>\\;', Net::LDAP::DN.escape(',+"\\<>;') end + def test_escape_pound_sign + assert_equal '\\#test', Net::LDAP::DN.escape('#test') + end + + def test_escape_space + assert_equal '\\ before_after\\ ', Net::LDAP::DN.escape(' before_after ') + end + + def test_retain_spaces + dn = Net::LDAP::DN.new('CN=Foo.bar.baz, OU=Foo \ ,OU=\ Bar, O=Baz') + assert_equal "CN=Foo.bar.baz, OU=Foo \\ ,OU=\\ Bar, O=Baz", dn.to_s + assert_equal ["CN", "Foo.bar.baz", "OU", "Foo ", "OU", " Bar", "O", "Baz"], dn.to_a + end + def test_escape_on_initialize dn = Net::LDAP::DN.new('cn', ',+"\\<>;', 'ou=company') assert_equal 'cn=\\,\\+\\"\\\\\\<\\>\\;,ou=company', dn.to_s @@ -18,7 +32,7 @@ def test_to_a def test_to_a_parenthesis dn = Net::LDAP::DN.new('cn = \ James , ou = "Comp\28ny" ') - assert_equal ['cn', ' James', 'ou', 'Comp(ny'], dn.to_a + assert_equal ['cn', ' James ', 'ou', 'Comp(ny'], dn.to_a end def test_to_a_hash_symbol @@ -26,7 +40,6 @@ def test_to_a_hash_symbol assert_equal ['1.23.4', '#A3B4D5', 'ou', 'Company'], dn.to_a end - # TODO: raise a more specific exception than RuntimeError def test_bad_input_raises_error [ 'cn=James,', @@ -38,7 +51,7 @@ def test_bad_input_raises_error 'd1.2=Value', ].each do |input| dn = Net::LDAP::DN.new(input) - assert_raises(RuntimeError) { dn.to_a } + assert_raises(Net::LDAP::InvalidDNError) { dn.to_a } end end end diff --git a/test/test_entry.rb b/test/test_entry.rb index e2184747..60c89ba6 100644 --- a/test/test_entry.rb +++ b/test/test_entry.rb @@ -39,6 +39,32 @@ def test_case_insensitive_attribute_names assert_equal ['Jensen'], @entry['Sn'] assert_equal ['Jensen'], @entry['SN'] end + + def test_to_h + @entry['sn'] = 'Jensen' + expected = { + dn: ['cn=Barbara,o=corp'], + sn: ['Jensen'], + } + duplicate = @entry.to_h + assert_equal expected, duplicate + + # check that changing the duplicate + # does not affect the internal state + duplicate.delete(:sn) + assert_not_equal duplicate, @entry.to_h + end + + def test_equal_operator + entry_two = Net::LDAP::Entry.new 'cn=Barbara,o=corp' + assert_equal @entry, entry_two + + @entry['sn'] = 'Jensen' + assert_not_equal @entry, entry_two + + entry_two['sn'] = 'Jensen' + assert_equal @entry, entry_two + end end class TestEntryLDIF < Test::Unit::TestCase @@ -47,7 +73,8 @@ def setup %Q{dn: something foo: foo barAttribute: bar - }) + }, + ) end def test_attribute @@ -59,7 +86,7 @@ def test_modify_attribute @entry.foo = 'bar' assert_equal ['bar'], @entry.foo - @entry.fOo= 'baz' + @entry.fOo = 'baz' assert_equal ['baz'], @entry.foo end end diff --git a/test/test_filter_parser.rb b/test/test_filter_parser.rb index 6f1ca48b..960ff1ad 100644 --- a/test/test_filter_parser.rb +++ b/test/test_filter_parser.rb @@ -1,4 +1,5 @@ # encoding: utf-8 + require_relative 'test_helper' class TestFilterParser < Test::Unit::TestCase @@ -21,4 +22,8 @@ def test_slash def test_colons assert_kind_of Net::LDAP::Filter, Net::LDAP::Filter::FilterParser.parse("(ismemberof=cn=edu:berkeley:app:calmessages:deans,ou=campus groups,dc=berkeley,dc=edu)") end + + def test_attr_tag + assert_kind_of Net::LDAP::Filter, Net::LDAP::Filter::FilterParser.parse("(mail;primary=jane@example.org)") + end end diff --git a/test/test_helper.rb b/test/test_helper.rb index 0a976be4..4a7600bd 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,6 +1,6 @@ # Add 'lib' to load path. require 'test/unit' -require 'net/ldap' +require_relative '../lib/net/ldap' require 'flexmock/test_unit' # Whether integration tests should be run. @@ -14,14 +14,14 @@ if File.exist?("/etc/ssl/certs/cacert.pem") "/etc/ssl/certs/cacert.pem" else - File.expand_path("fixtures/ca/cacert.pem", File.dirname(__FILE__)) + File.expand_path("fixtures/ca/docker-ca.pem", File.dirname(__FILE__)) end end BIND_CREDS = { method: :simple, - username: "uid=user1,ou=People,dc=rubyldap,dc=com", - password: "passworD1", + username: "cn=admin,dc=example,dc=org", + password: "admin", }.freeze TLS_OPTS = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS.merge({}).freeze @@ -65,10 +65,9 @@ def setup @ldap = Net::LDAP.new \ host: ENV.fetch('https://github.com/INTEGRATION_HOST', 'localhost'), port: ENV.fetch('https://github.com/INTEGRATION_PORT', 389), - admin_user: 'uid=admin,dc=rubyldap,dc=com', - admin_password: 'passworD1', - search_domains: %w(dc=rubyldap,dc=com), + search_domains: %w(dc=example,dc=org), uid: 'uid', instrumentation_service: @service + @ldap.authenticate "cn=admin,dc=example,dc=org", "admin" end end diff --git a/test/test_ldap.rb b/test/test_ldap.rb index 8d6a9a72..6c061475 100644 --- a/test/test_ldap.rb +++ b/test/test_ldap.rb @@ -1,4 +1,4 @@ -require 'test_helper' +require_relative 'test_helper' class TestLDAPInstrumentation < Test::Unit::TestCase # Fake Net::LDAP::Connection for testing @@ -94,7 +94,7 @@ def test_encryption def test_normalize_encryption_symbol enc = @subject.send(:normalize_encryption, :start_tls) - assert_equal enc, {:method => :start_tls, :tls_options => {}} + assert_equal enc, :method => :start_tls, :tls_options => {} end def test_normalize_encryption_nil @@ -104,11 +104,11 @@ def test_normalize_encryption_nil def test_normalize_encryption_string enc = @subject.send(:normalize_encryption, 'start_tls') - assert_equal enc, {:method => :start_tls, :tls_options => {}} + assert_equal enc, :method => :start_tls, :tls_options => {} end def test_normalize_encryption_hash - enc = @subject.send(:normalize_encryption, {:method => :start_tls, :tls_options => {:foo => :bar}}) - assert_equal enc, {:method => :start_tls, :tls_options => {:foo => :bar}} + enc = @subject.send(:normalize_encryption, :method => :start_tls, :tls_options => { :foo => :bar }) + assert_equal enc, :method => :start_tls, :tls_options => { :foo => :bar } end end diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 8489c377..fdfa418c 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -61,7 +61,7 @@ def test_result_for_connection_failed_is_set ldap_client = Net::LDAP.new(host: '127.0.0.1', port: 12345) - assert_raise Net::LDAP::ConnectionRefusedError do + assert_raise Errno::ECONNREFUSED do ldap_client.bind(method: :simple, username: 'asdf', password: 'asdf') end @@ -86,16 +86,15 @@ def test_blocked_port def test_connection_refused connection = Net::LDAP::Connection.new(:host => "fail.Errno::ECONNREFUSED", :port => 636, :socket_class => FakeTCPSocket) stderr = capture_stderr do - assert_raise Net::LDAP::ConnectionRefusedError do + assert_raise Errno::ECONNREFUSED do connection.socket end end - assert_equal("Deprecation warning: Net::LDAP::ConnectionRefused will be deprecated. Use Errno::ECONNREFUSED instead.\n", stderr) end def test_connection_timeout connection = Net::LDAP::Connection.new(:host => "fail.Errno::ETIMEDOUT", :port => 636, :socket_class => FakeTCPSocket) - stderr = capture_stderr do + capture_stderr do assert_raise Net::LDAP::Error do connection.socket end @@ -124,7 +123,7 @@ def test_modify_ops_add end def test_modify_ops_replace - args = { :operations =>[[:replace, "mail", "testuser@example.com"]] } + args = { :operations => [[:replace, "mail", "testuser@example.com"]] } result = Net::LDAP::Connection.modify_ops(args[:operations]) expected = ["0#\n\x01\x020\x1E\x04\x04mail1\x16\x04\x14testuser@example.com"] assert_equal(expected, result) @@ -191,9 +190,9 @@ def test_queued_read_reads_until_message_id_match result2 = make_message(2) mock = flexmock("socket") - mock.should_receive(:read_ber). - and_return(result1). - and_return(result2) + mock.should_receive(:read_ber) + .and_return(result1) + .and_return(result2) conn = Net::LDAP::Connection.new(:socket => mock) assert result = conn.queued_read(2) @@ -206,9 +205,9 @@ def test_queued_read_modify result2 = make_message(2, app_tag: Net::LDAP::PDU::ModifyResponse) mock = flexmock("socket") - mock.should_receive(:read_ber). - and_return(result1). - and_return(result2) + mock.should_receive(:read_ber) + .and_return(result1) + .and_return(result2) mock.should_receive(:write) conn = Net::LDAP::Connection.new(:socket => mock) @@ -227,9 +226,9 @@ def test_queued_read_add result2 = make_message(2, app_tag: Net::LDAP::PDU::AddResponse) mock = flexmock("socket") - mock.should_receive(:read_ber). - and_return(result1). - and_return(result2) + mock.should_receive(:read_ber) + .and_return(result1) + .and_return(result2) mock.should_receive(:write) conn = Net::LDAP::Connection.new(:socket => mock) @@ -245,9 +244,9 @@ def test_queued_read_rename result2 = make_message(2, app_tag: Net::LDAP::PDU::ModifyRDNResponse) mock = flexmock("socket") - mock.should_receive(:read_ber). - and_return(result1). - and_return(result2) + mock.should_receive(:read_ber) + .and_return(result1) + .and_return(result2) mock.should_receive(:write) conn = Net::LDAP::Connection.new(:socket => mock) @@ -266,9 +265,9 @@ def test_queued_read_delete result2 = make_message(2, app_tag: Net::LDAP::PDU::DeleteResponse) mock = flexmock("socket") - mock.should_receive(:read_ber). - and_return(result1). - and_return(result2) + mock.should_receive(:read_ber) + .and_return(result1) + .and_return(result2) mock.should_receive(:write) conn = Net::LDAP::Connection.new(:socket => mock) @@ -284,13 +283,13 @@ def test_queued_read_setup_encryption_with_start_tls result2 = make_message(2, app_tag: Net::LDAP::PDU::ExtendedResponse) mock = flexmock("socket") - mock.should_receive(:read_ber). - and_return(result1). - and_return(result2) + mock.should_receive(:read_ber) + .and_return(result1) + .and_return(result2) mock.should_receive(:write) conn = Net::LDAP::Connection.new(:socket => mock) - flexmock(Net::LDAP::Connection).should_receive(:wrap_with_ssl).with(mock, {}, nil). - and_return(mock) + flexmock(Net::LDAP::Connection).should_receive(:wrap_with_ssl).with(mock, {}, nil, nil) + .and_return(mock) conn.next_msgid # simulates ongoing query @@ -303,9 +302,9 @@ def test_queued_read_bind_simple result2 = make_message(2, app_tag: Net::LDAP::PDU::BindResult) mock = flexmock("socket") - mock.should_receive(:read_ber). - and_return(result1). - and_return(result2) + mock.should_receive(:read_ber) + .and_return(result1) + .and_return(result2) mock.should_receive(:write) conn = Net::LDAP::Connection.new(:socket => mock) @@ -314,7 +313,8 @@ def test_queued_read_bind_simple assert result = conn.bind( method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", - password: "passworD1") + password: "passworD1", + ) assert result.success? assert_equal 2, result.message_id end @@ -324,9 +324,9 @@ def test_queued_read_bind_sasl result2 = make_message(2, app_tag: Net::LDAP::PDU::BindResult) mock = flexmock("socket") - mock.should_receive(:read_ber). - and_return(result1). - and_return(result2) + mock.should_receive(:read_ber) + .and_return(result1) + .and_return(result2) mock.should_receive(:write) conn = Net::LDAP::Connection.new(:socket => mock) @@ -336,10 +336,23 @@ def test_queued_read_bind_sasl method: :sasl, mechanism: "fake", initial_credential: "passworD1", - challenge_response: flexmock("challenge proc")) + challenge_response: flexmock("challenge proc"), + ) assert result.success? assert_equal 2, result.message_id end + + def test_invalid_pdu_type + options = { + code: Net::LDAP::ResultCodeSuccess, + matched_dn: "", + error_message: "", + } + ber = Net::BER::BerIdentifiedArray.new([options[:code], options[:matched_dn], options[:error_message]]) + assert_raise Net::LDAP::PDU::Error do + Net::LDAP::PDU.new([0, ber]) + end + end end class TestLDAPConnectionErrors < Test::Unit::TestCase @@ -469,8 +482,8 @@ def test_search_net_ldap_connection_event search_result_ber = Net::BER::BerIdentifiedArray.new([Net::LDAP::ResultCodeSuccess, "", ""]) search_result_ber.ber_identifier = Net::LDAP::PDU::SearchResult search_result = [1, search_result_ber] - @tcp_socket.should_receive(:read_ber).and_return(search_data). - and_return(search_result) + @tcp_socket.should_receive(:read_ber).and_return(search_data) + .and_return(search_result) events = @service.subscribe "search.net_ldap_connection" unread = @service.subscribe "search_messages_unread.net_ldap_connection" @@ -488,4 +501,88 @@ def test_search_net_ldap_connection_event # ensure no unread assert unread.empty?, "should not have any leftover unread messages" end + + def test_add_with_controls + dacl_flag = 0x4 # DACL_SECURITY_INFORMATION + control_values = [dacl_flag].map(&:to_ber).to_ber_sequence.to_s.to_ber + controls = [] + # LDAP_SERVER_SD_FLAGS constant definition, taken from https://ldapwiki.com/wiki/LDAP_SERVER_SD_FLAGS_OID + ldap_server_sd_flags = '1.2.840.113556.1.4.801'.freeze + controls << [ldap_server_sd_flags.to_ber, true.to_ber, control_values].to_ber_sequence + + ber = Net::BER::BerIdentifiedArray.new([Net::LDAP::ResultCodeSuccess, "", ""]) + ber.ber_identifier = Net::LDAP::PDU::AddResponse + @tcp_socket.should_receive(:read_ber).and_return([1, ber]) + + result = @connection.add(:dn => "uid=added-user1,ou=People,dc=rubyldap,dc=com", :controls => controls) + assert result.success?, "should be success" + assert_equal "", result.error_message + end + + def test_modify_with_controls + dacl_flag = 0x4 # DACL_SECURITY_INFORMATION + control_values = [dacl_flag].map(&:to_ber).to_ber_sequence.to_s.to_ber + controls = [] + # LDAP_SERVER_SD_FLAGS constant definition, taken from https://ldapwiki.com/wiki/LDAP_SERVER_SD_FLAGS_OID + ldap_server_sd_flags = '1.2.840.113556.1.4.801'.freeze + controls << [ldap_server_sd_flags.to_ber, true.to_ber, control_values].to_ber_sequence + + ber = Net::BER::BerIdentifiedArray.new([Net::LDAP::ResultCodeSuccess, "", ""]) + ber.ber_identifier = Net::LDAP::PDU::ModifyResponse + @tcp_socket.should_receive(:read_ber).and_return([1, ber]) + + result = @connection.modify(:dn => "1", :operations => [[:replace, "mail", "something@sothsdkf.com"]], :controls => controls) + assert result.success?, "should be success" + assert_equal "", result.error_message + end + + def test_search_with_controls + # search data + search_data_ber = Net::BER::BerIdentifiedArray.new([1, [ + "uid=user1,ou=People,dc=rubyldap,dc=com", + [["uid", ["user1"]]], + ]]) + search_data_ber.ber_identifier = Net::LDAP::PDU::SearchReturnedData + search_data = [1, search_data_ber] + # search result (end of results) + search_result_ber = Net::BER::BerIdentifiedArray.new([Net::LDAP::ResultCodeSuccess, "", ""]) + search_result_ber.ber_identifier = Net::LDAP::PDU::SearchResult + search_result = [1, search_result_ber] + @tcp_socket.should_receive(:read_ber).and_return(search_data) + .and_return(search_result) + + events = @service.subscribe "search.net_ldap_connection" + unread = @service.subscribe "search_messages_unread.net_ldap_connection" + + all_but_sacl_flag = 0x1 | 0x2 | 0x4 # OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION + control_values = [all_but_sacl_flag].map(&:to_ber).to_ber_sequence.to_s.to_ber + controls = [] + # LDAP_SERVER_SD_FLAGS constant definition, taken from https://ldapwiki.com/wiki/LDAP_SERVER_SD_FLAGS_OID + ldap_server_sd_flags = '1.2.840.113556.1.4.801'.freeze + controls << [ldap_server_sd_flags.to_ber, true.to_ber, control_values].to_ber_sequence + + result = @connection.search(filter: "(uid=user1)", base: "ou=People,dc=rubyldap,dc=com", controls: controls) + assert result.success?, "should be success" + + # a search event + payload, result = events.pop + assert payload.key?(:result) + assert payload.key?(:filter) + assert_equal "(uid=user1)", payload[:filter].to_s + assert result + + # ensure no unread + assert unread.empty?, "should not have any leftover unread messages" + end + + def test_ldapwhoami + ber = Net::BER::BerIdentifiedArray.new([Net::LDAP::ResultCodeSuccess, '', '', 0, 'dn:uid=zerosteiner,ou=users,dc=example,dc=org']) + ber.ber_identifier = Net::LDAP::PDU::ExtendedResponse + response = [1, ber] + + @tcp_socket.should_receive(:read_ber).and_return(response) + + result = @connection.ldapwhoami + assert result.extended_response == 'dn:uid=zerosteiner,ou=users,dc=example,dc=org' + end end diff --git a/test/test_ldif.rb b/test/test_ldif.rb index cc1ee2bf..c74ea6e7 100644 --- a/test/test_ldif.rb +++ b/test/test_ldif.rb @@ -22,46 +22,46 @@ def test_ldif_with_version def test_ldif_with_comments str = ["# Hello from LDIF-land", "# This is an unterminated comment"] io = StringIO.new(str[0] + "\r\n" + str[1]) - ds = Net::LDAP::Dataset::read_ldif(io) + ds = Net::LDAP::Dataset.read_ldif(io) assert_equal(str, ds.comments) end def test_ldif_with_password psw = "goldbricks" - hashed_psw = "{SHA}" + Base64::encode64(Digest::SHA1.digest(psw)).chomp + hashed_psw = "{SHA}" + Base64.encode64(Digest::SHA1.digest(psw)).chomp - ldif_encoded = Base64::encode64(hashed_psw).chomp - ds = Net::LDAP::Dataset::read_ldif(StringIO.new("dn: Goldbrick\r\nuserPassword:: #{ldif_encoded}\r\n\r\n")) + ldif_encoded = Base64.encode64(hashed_psw).chomp + ds = Net::LDAP::Dataset.read_ldif(StringIO.new("dn: Goldbrick\r\nuserPassword:: #{ldif_encoded}\r\n\r\n")) recovered_psw = ds["Goldbrick"][:userpassword].shift assert_equal(hashed_psw, recovered_psw) end def test_ldif_with_continuation_lines - ds = Net::LDAP::Dataset::read_ldif(StringIO.new("dn: abcdefg\r\n hijklmn\r\n\r\n")) + ds = Net::LDAP::Dataset.read_ldif(StringIO.new("dn: abcdefg\r\n hijklmn\r\n\r\n")) assert_equal(true, ds.key?("abcdefghijklmn")) end def test_ldif_with_continuation_lines_and_extra_whitespace - ds1 = Net::LDAP::Dataset::read_ldif(StringIO.new("dn: abcdefg\r\n hijklmn\r\n\r\n")) + ds1 = Net::LDAP::Dataset.read_ldif(StringIO.new("dn: abcdefg\r\n hijklmn\r\n\r\n")) assert_equal(true, ds1.key?("abcdefg hijklmn")) - ds2 = Net::LDAP::Dataset::read_ldif(StringIO.new("dn: abcdefg\r\n hij klmn\r\n\r\n")) + ds2 = Net::LDAP::Dataset.read_ldif(StringIO.new("dn: abcdefg\r\n hij klmn\r\n\r\n")) assert_equal(true, ds2.key?("abcdefghij klmn")) end def test_ldif_tab_is_not_continuation - ds = Net::LDAP::Dataset::read_ldif(StringIO.new("dn: key\r\n\tnotcontinued\r\n\r\n")) + ds = Net::LDAP::Dataset.read_ldif(StringIO.new("dn: key\r\n\tnotcontinued\r\n\r\n")) assert_equal(true, ds.key?("key")) end def test_ldif_with_base64_dn str = "dn:: Q049QmFzZTY0IGRuIHRlc3QsT1U9VGVzdCxPVT1Vbml0cyxEQz1leGFtcGxlLERDPWNvbQ==\r\n\r\n" - ds = Net::LDAP::Dataset::read_ldif(StringIO.new(str)) + ds = Net::LDAP::Dataset.read_ldif(StringIO.new(str)) assert_equal(true, ds.key?("CN=Base64 dn test,OU=Test,OU=Units,DC=example,DC=com")) end def test_ldif_with_base64_dn_and_continuation_lines str = "dn:: Q049QmFzZTY0IGRuIHRlc3Qgd2l0aCBjb250aW51YXRpb24gbGluZSxPVT1UZXN0LE9VPVVua\r\n XRzLERDPWV4YW1wbGUsREM9Y29t\r\n\r\n" - ds = Net::LDAP::Dataset::read_ldif(StringIO.new(str)) + ds = Net::LDAP::Dataset.read_ldif(StringIO.new(str)) assert_equal(true, ds.key?("CN=Base64 dn test with continuation line,OU=Test,OU=Units,DC=example,DC=com")) end @@ -69,7 +69,7 @@ def test_ldif_with_base64_dn_and_continuation_lines # to verify the content. def test_ldif File.open(TestLdifFilename, "r") do |f| - ds = Net::LDAP::Dataset::read_ldif(f) + ds = Net::LDAP::Dataset.read_ldif(f) assert_equal(13, ds.length) end end @@ -84,7 +84,7 @@ def test_to_ldif entries = data.lines.grep(/^dn:\s*/) { $'.chomp } dn_entries = entries.dup - ds = Net::LDAP::Dataset::read_ldif(io) do |type, value| + ds = Net::LDAP::Dataset.read_ldif(io) do |type, value| case type when :dn assert_equal(dn_entries.first, value) diff --git a/test/test_password.rb b/test/test_password.rb index 87b47d91..cc1878da 100644 --- a/test/test_password.rb +++ b/test/test_password.rb @@ -4,7 +4,12 @@ class TestPassword < Test::Unit::TestCase def test_psw - assert_equal("{MD5}xq8jwrcfibi0sZdZYNkSng==", Net::LDAP::Password.generate( :md5, "cashflow" )) - assert_equal("{SHA}YE4eGkN4BvwNN1f5R7CZz0kFn14=", Net::LDAP::Password.generate( :sha, "cashflow" )) + assert_equal("{MD5}xq8jwrcfibi0sZdZYNkSng==", Net::LDAP::Password.generate(:md5, "cashflow")) + assert_equal("{SHA}YE4eGkN4BvwNN1f5R7CZz0kFn14=", Net::LDAP::Password.generate(:sha, "cashflow")) + end + + def test_psw_with_ssha256_should_not_contain_linefeed + flexmock(SecureRandom).should_receive(:random_bytes).and_return('\xE5\x8A\x99\xF8\xCB\x15GW\xE8\xEA\xAD\x0F\xBF\x95\xB0\xDC') + assert_equal("{SSHA256}Cc7MXboTyUP5PnPAeJeCrgMy8+7Gus0sw7kBJuTrmf1ceEU1XHg4QVx4OTlceEY4XHhDQlx4MTVHV1x4RThceEVBXHhBRFx4MEZceEJGXHg5NVx4QjBceERD", Net::LDAP::Password.generate(:ssha256, "cashflow")) end end diff --git a/test/test_snmp.rb b/test/test_snmp.rb index 6a809a80..fa064d41 100644 --- a/test/test_snmp.rb +++ b/test/test_snmp.rb @@ -1,7 +1,7 @@ # $Id: testsnmp.rb 231 2006-12-21 15:09:29Z blackhedd $ require_relative 'test_helper' -require 'net/snmp' +require_relative '../lib/net/snmp' class TestSnmp < Test::Unit::TestCase def self.raw_string(s) @@ -17,7 +17,7 @@ def self.raw_string(s) def test_invalid_packet data = "xxxx" assert_raise(Net::BER::BerError) do -ary = data.read_ber(Net::SNMP::AsnSyntax) + data.read_ber(Net::SNMP::AsnSyntax) end end @@ -41,7 +41,7 @@ def _test_consume_string def test_weird_packet assert_raise(Net::SnmpPdu::Error) do -Net::SnmpPdu.parse("aaaaaaaaaaaaaa") + Net::SnmpPdu.parse("aaaaaaaaaaaaaa") end end @@ -93,7 +93,7 @@ def test_make_response def test_make_bad_response pdu = Net::SnmpPdu.new - assert_raise(Net::SnmpPdu::Error) {pdu.to_ber_string} + assert_raise(Net::SnmpPdu::Error) { pdu.to_ber_string } pdu.pdu_type = :get_response pdu.request_id = 999 pdu.to_ber_string @@ -115,5 +115,4 @@ def test_community pdu = Net::SnmpPdu.parse(ary) assert_equal("xxxxxx", pdu.community) end - end diff --git a/test/test_ssl_ber.rb b/test/test_ssl_ber.rb index 7711558b..766c8b84 100644 --- a/test/test_ssl_ber.rb +++ b/test/test_ssl_ber.rb @@ -5,7 +5,7 @@ class TestSSLBER < Test::Unit::TestCase # Transmits str to @to and reads it back from @from. # def transmit(str) - Timeout::timeout(1) do + Timeout.timeout(1) do @to.write(str) @to.close @@ -22,18 +22,24 @@ def setup # # TODO: Replace test with real socket # https://github.com/ruby-ldap/ruby-net-ldap/pull/121#discussion_r18746386 - flexmock(OpenSSL::SSL::SSLSocket). - new_instances.should_receive(:connect => nil) + flexmock(OpenSSL::SSL::SSLSocket) + .new_instances.should_receive(:connect => nil) @to = Net::LDAP::Connection.wrap_with_ssl(@to) @from = Net::LDAP::Connection.wrap_with_ssl(@from) end def test_transmit_strings + omit_if RUBY_PLATFORM == "java", "JRuby throws an error without a real socket" + omit_if (RUBY_VERSION >= "3.1" || RUBY_ENGINE == "truffleruby"), "Ruby complains about connection not being open" + assert_equal "foo", transmit("foo") end def test_transmit_ber_encoded_numbers + omit_if RUBY_PLATFORM == "java", "JRuby throws an error without a real socket" + omit_if (RUBY_VERSION >= "3.1" || RUBY_ENGINE == "truffleruby"), "Ruby complains about connection not being open" + @to.write 1234.to_ber assert_equal 1234, @from.read_ber end diff --git a/testserver/ldapserver.rb b/testserver/ldapserver.rb index 809f9e7e..9adeacb0 100644 --- a/testserver/ldapserver.rb +++ b/testserver/ldapserver.rb @@ -15,8 +15,7 @@ #------------------------------------------------ module LdapServer - - LdapServerAsnSyntax = { + LdapServerAsnSyntaxTemplate = { :application => { :constructed => { 0 => :array, # LDAP BindRequest @@ -46,7 +45,7 @@ def receive_data data @data ||= ""; @data << data while pdu = @data.read_ber!(LdapServerAsnSyntax) begin - handle_ldap_pdu pdu + handle_ldap_pdu pdu rescue $logger.error "closing connection due to error #{$!}" close_connection @@ -87,9 +86,7 @@ def handle_bind_request pdu end end - - - #-- + # -- # Search Response ::= # CHOICE { # entry [APPLICATION 4] SEQUENCE { @@ -119,9 +116,9 @@ def handle_search_request pdu # pdu[1][7] is the list of requested attributes. # If it's an empty array, that means that *all* attributes were requested. requested_attrs = if pdu[1][7].length > 0 - pdu[1][7].map(&:downcase) - else - :all + pdu[1][7].map(&:downcase) + else + :all end filters = pdu[1][6] @@ -131,13 +128,13 @@ def handle_search_request pdu end # TODO, what if this returns nil? - filter = Net::LDAP::Filter.parse_ldap_filter( filters ) + filter = Net::LDAP::Filter.parse_ldap_filter(filters) $ldif.each do |dn, entry| - if filter.match( entry ) + if filter.match(entry) attrs = [] entry.each do |k, v| - if requested_attrs == :all or requested_attrs.include?(k.downcase) + if requested_attrs == :all || requested_attrs.include?(k.downcase) attrvals = v.map(&:to_ber).to_ber_set attrs << [k.to_ber, attrvals].to_ber_sequence end @@ -149,32 +146,27 @@ def handle_search_request pdu end end - send_ldap_response 5, pdu[0].to_i, 0, "", "Was that what you wanted?" end - - def send_ldap_response pkt_tag, msgid, code, dn, text - send_data( [msgid.to_ber, [code.to_ber, dn.to_ber, text.to_ber].to_ber_appsequence(pkt_tag)].to_ber ) + send_data([msgid.to_ber, [code.to_ber, dn.to_ber, text.to_ber].to_ber_appsequence(pkt_tag)].to_ber) end - end - #------------------------------------------------ # Rather bogus, a global method, which reads a HARDCODED filename # parses out LDIF data. It will be used to serve LDAP queries out of this server. # def load_test_data - ary = File.readlines( "./testdata.ldif" ) + ary = File.readlines("./testdata.ldif") hash = {} - while line = ary.shift and line.chomp! + while (line = ary.shift) && line.chomp! if line =~ /^dn:[\s]*/i dn = $' hash[dn] = {} - while attr = ary.shift and attr.chomp! and attr =~ /^([\w]+)[\s]*:[\s]*/ + while (attr = ary.shift) && attr.chomp! && attr =~ /^([\w]+)[\s]*:[\s]*/ hash[dn][$1.downcase] ||= [] hash[dn][$1.downcase] << $' end @@ -183,7 +175,6 @@ def load_test_data hash end - #------------------------------------------------ if __FILE__ == $0 @@ -200,10 +191,10 @@ def load_test_data $ldif = load_test_data require 'net/ldap' - + LdapServerAsnSyntax = Net::BER.compile_syntax(LdapServerAsnSyntaxTemplate) EventMachine.run do $logger.info "starting LDAP server on 127.0.0.1 port 3890" EventMachine.start_server "127.0.0.1", 3890, LdapServer - EventMachine.add_periodic_timer 60, proc {$logger.info "heartbeat"} + EventMachine.add_periodic_timer 60, proc { $logger.info "heartbeat" } end end