diff options
101 files changed, 5740 insertions, 9 deletions
@@ -63,6 +63,8 @@ java_library( visibility = [ "//org.eclipse.jgit.junit:__pkg__", "//org.eclipse.jgit.test:__pkg__", + "//org.eclipse.jgit.ssh.apache:__pkg__", + "//org.eclipse.jgit.ssh.apache.test:__pkg__", ], exports = ["@sshd-core//jar"], ) @@ -72,6 +74,8 @@ java_library( visibility = [ "//org.eclipse.jgit.junit:__pkg__", "//org.eclipse.jgit.test:__pkg__", + "//org.eclipse.jgit.ssh.apache:__pkg__", + "//org.eclipse.jgit.ssh.apache.test:__pkg__", ], exports = ["@sshd-sftp//jar"], ) diff --git a/org.eclipse.jgit.ssh.apache.test/.classpath b/org.eclipse.jgit.ssh.apache.test/.classpath new file mode 100644 index 0000000000..f08af0a4e9 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache.test/.classpath @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="src" path="tst"> + <attributes> + <attribute name="test" value="true"/> + </attributes> + </classpathentry> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/org.eclipse.jgit.ssh.apache.test/.gitignore b/org.eclipse.jgit.ssh.apache.test/.gitignore new file mode 100644 index 0000000000..934e0e06ff --- /dev/null +++ b/org.eclipse.jgit.ssh.apache.test/.gitignore @@ -0,0 +1,2 @@ +/bin +/target diff --git a/org.eclipse.jgit.ssh.apache.test/.project b/org.eclipse.jgit.ssh.apache.test/.project new file mode 100644 index 0000000000..0aafb730fb --- /dev/null +++ b/org.eclipse.jgit.ssh.apache.test/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.jgit.ssh.apache.test</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.core.resources.prefs b/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000000..f77db3b723 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,3 @@ +#Sat Dec 20 21:21:24 CET 2008 +eclipse.preferences.version=1 +encoding/<project>=UTF-8 diff --git a/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.core.runtime.prefs b/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.core.runtime.prefs new file mode 100644 index 0000000000..9f733eeea7 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.core.runtime.prefs @@ -0,0 +1,3 @@ +#Mon Mar 24 18:55:56 EDT 2008 +eclipse.preferences.version=1 +line.separator=\n diff --git a/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..794592dee1 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,399 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=warning +org.eclipse.jdt.core.compiler.problem.comparingIdentical=error +org.eclipse.jdt.core.compiler.problem.deadCode=error +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=warning +org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=warning +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=error +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=error +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=error +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private +org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=error +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=protected +org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=error +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=error +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error +org.eclipse.jdt.core.compiler.problem.nullReference=error +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore +org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=error +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=error +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedImport=error +org.eclipse.jdt.core.compiler.problem.unusedLabel=error +org.eclipse.jdt.core.compiler.problem.unusedLocal=error +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=warning +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error +org.eclipse.jdt.core.compiler.source=1.8 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=1 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert +org.eclipse.jdt.core.formatter.comment.line_length=80 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=true +org.eclipse.jdt.core.formatter.join_wrapped_lines=true +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=80 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=tab +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 0000000000..fef3713825 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,66 @@ +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +formatter_profile=_JGit Format +formatter_settings_version=12 +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; +org.eclipse.jdt.ui.ondemandthreshold=99 +org.eclipse.jdt.ui.staticondemandthreshold=99 +org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?><templates/> +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_functional_interfaces=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=true +sp_cleanup.format_source_code_changes_only=true +sp_cleanup.insert_inferred_type_arguments=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=false +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=false +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_redundant_type_arguments=true +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=false +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_anonymous_class_creation=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_lambda=false +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.mylyn.tasks.ui.prefs b/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.mylyn.tasks.ui.prefs new file mode 100644 index 0000000000..823c0f56ae --- /dev/null +++ b/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.mylyn.tasks.ui.prefs @@ -0,0 +1,4 @@ +#Tue Jul 19 20:11:28 CEST 2011 +eclipse.preferences.version=1 +project.repository.kind=bugzilla +project.repository.url=https\://bugs.eclipse.org/bugs diff --git a/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.mylyn.team.ui.prefs b/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.mylyn.team.ui.prefs new file mode 100644 index 0000000000..0cba949fb7 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.mylyn.team.ui.prefs @@ -0,0 +1,3 @@ +#Tue Jul 19 20:11:28 CEST 2011 +commit.comment.template=${task.description} \n\nBug\: ${task.key} +eclipse.preferences.version=1 diff --git a/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.pde.api.tools.prefs b/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.pde.api.tools.prefs new file mode 100644 index 0000000000..c0030ded71 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.pde.api.tools.prefs @@ -0,0 +1,104 @@ +ANNOTATION_ELEMENT_TYPE_ADDED_FIELD=Error +ANNOTATION_ELEMENT_TYPE_ADDED_METHOD_WITHOUT_DEFAULT_VALUE=Error +ANNOTATION_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error +ANNOTATION_ELEMENT_TYPE_REMOVED_FIELD=Error +ANNOTATION_ELEMENT_TYPE_REMOVED_METHOD=Error +ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error +API_COMPONENT_ELEMENT_TYPE_REMOVED_API_TYPE=Error +API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_API_TYPE=Error +API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_TYPE=Error +API_COMPONENT_ELEMENT_TYPE_REMOVED_TYPE=Error +API_USE_SCAN_FIELD_SEVERITY=Error +API_USE_SCAN_METHOD_SEVERITY=Error +API_USE_SCAN_TYPE_SEVERITY=Error +CLASS_ELEMENT_TYPE_ADDED_FIELD=Error +CLASS_ELEMENT_TYPE_ADDED_METHOD=Error +CLASS_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error +CLASS_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error +CLASS_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error +CLASS_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error +CLASS_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error +CLASS_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error +CLASS_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error +CLASS_ELEMENT_TYPE_REMOVED_CONSTRUCTOR=Error +CLASS_ELEMENT_TYPE_REMOVED_FIELD=Error +CLASS_ELEMENT_TYPE_REMOVED_METHOD=Error +CLASS_ELEMENT_TYPE_REMOVED_SUPERCLASS=Error +CLASS_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error +CLASS_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error +CONSTRUCTOR_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error +CONSTRUCTOR_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error +CONSTRUCTOR_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error +CONSTRUCTOR_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error +ENUM_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error +ENUM_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error +ENUM_ELEMENT_TYPE_REMOVED_ENUM_CONSTANT=Error +ENUM_ELEMENT_TYPE_REMOVED_FIELD=Error +ENUM_ELEMENT_TYPE_REMOVED_METHOD=Error +ENUM_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error +FIELD_ELEMENT_TYPE_ADDED_VALUE=Error +FIELD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error +FIELD_ELEMENT_TYPE_CHANGED_FINAL_TO_NON_FINAL_STATIC_CONSTANT=Error +FIELD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error +FIELD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error +FIELD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error +FIELD_ELEMENT_TYPE_CHANGED_TYPE=Error +FIELD_ELEMENT_TYPE_CHANGED_VALUE=Error +FIELD_ELEMENT_TYPE_REMOVED_TYPE_ARGUMENT=Error +FIELD_ELEMENT_TYPE_REMOVED_VALUE=Error +ILLEGAL_EXTEND=Warning +ILLEGAL_IMPLEMENT=Warning +ILLEGAL_INSTANTIATE=Warning +ILLEGAL_OVERRIDE=Warning +ILLEGAL_REFERENCE=Warning +INTERFACE_ELEMENT_TYPE_ADDED_DEFAULT_METHOD=Error +INTERFACE_ELEMENT_TYPE_ADDED_FIELD=Error +INTERFACE_ELEMENT_TYPE_ADDED_METHOD=Error +INTERFACE_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error +INTERFACE_ELEMENT_TYPE_ADDED_SUPER_INTERFACE_WITH_METHODS=Error +INTERFACE_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error +INTERFACE_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error +INTERFACE_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error +INTERFACE_ELEMENT_TYPE_REMOVED_FIELD=Error +INTERFACE_ELEMENT_TYPE_REMOVED_METHOD=Error +INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error +INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error +INVALID_ANNOTATION=Ignore +INVALID_JAVADOC_TAG=Ignore +INVALID_REFERENCE_IN_SYSTEM_LIBRARIES=Error +LEAK_EXTEND=Warning +LEAK_FIELD_DECL=Warning +LEAK_IMPLEMENT=Warning +LEAK_METHOD_PARAM=Warning +LEAK_METHOD_RETURN_TYPE=Warning +METHOD_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error +METHOD_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error +METHOD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error +METHOD_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error +METHOD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error +METHOD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error +METHOD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error +METHOD_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error +METHOD_ELEMENT_TYPE_REMOVED_ANNOTATION_DEFAULT_VALUE=Error +METHOD_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error +MISSING_EE_DESCRIPTIONS=Warning +TYPE_PARAMETER_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error +TYPE_PARAMETER_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error +TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error +TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error +TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error +TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error +UNUSED_PROBLEM_FILTERS=Warning +automatically_removed_unused_problem_filters=false +changed_execution_env=Error +eclipse.preferences.version=1 +incompatible_api_component_version=Error +incompatible_api_component_version_include_major_without_breaking_change=Disabled +incompatible_api_component_version_include_minor_without_api_change=Disabled +incompatible_api_component_version_report_major_without_breaking_change=Warning +incompatible_api_component_version_report_minor_without_api_change=Ignore +invalid_since_tag_version=Error +malformed_since_tag=Error +missing_since_tag=Error +report_api_breakage_when_major_version_incremented=Disabled +report_resolution_errors_api_component=Warning diff --git a/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.pde.core.prefs b/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 0000000000..82793f2d27 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,3 @@ +#Thu Jan 14 14:34:32 CST 2010 +eclipse.preferences.version=1 +resolve.requirebundle=false diff --git a/org.eclipse.jgit.ssh.apache.test/BUILD b/org.eclipse.jgit.ssh.apache.test/BUILD new file mode 100644 index 0000000000..92ed4de696 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache.test/BUILD @@ -0,0 +1,18 @@ +load( + "@com_googlesource_gerrit_bazlets//tools:junit.bzl", + "junit_tests", +) + +junit_tests( + name = "sshd_apache", + srcs = glob(["tst/**/*.java"]), + tags = ["sshd"], + deps = [ + "//org.eclipse.jgit.test:sshd-helpers", + "//lib:junit", + "//org.eclipse.jgit:jgit", + "//lib:sshd-core", + "//lib:sshd-sftp", + "//org.eclipse.jgit.ssh.apache:ssh-apache", + ], +) diff --git a/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..c8f53c4c15 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF @@ -0,0 +1,17 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %Bundle-Name +Automatic-Module-Name: org.eclipse.jgit.ssh.apache.test +Bundle-SymbolicName: org.eclipse.jgit.ssh.apache.test +Bundle-Version: 5.2.0.qualifier +Bundle-Vendor: %Provider-Name +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Import-Package: org.eclipse.jgit.junit;version="[5.2.0,5.3.0)", + org.eclipse.jgit.lib;version="[5.2.0,5.3.0)", + org.eclipse.jgit.transport;version="[5.2.0,5.3.0)", + org.eclipse.jgit.transport.ssh;version="[5.2.0,5.3.0)", + org.eclipse.jgit.transport.sshd;version="[5.2.0,5.3.0)", + org.eclipse.jgit.util;version="[5.2.0,5.3.0)", + org.junit;version="[4.12,5.0.0)", + org.junit.experimental.theories;version="[4.12,5.0.0)", + org.junit.runner;version="[4.12,5.0.0)" diff --git a/org.eclipse.jgit.ssh.apache.test/about.html b/org.eclipse.jgit.ssh.apache.test/about.html new file mode 100644 index 0000000000..f971af18d0 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache.test/about.html @@ -0,0 +1,96 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> + +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /> +<title>Eclipse Distribution License - Version 1.0</title> +<style type="text/css"> + body { + size: 8.5in 11.0in; + margin: 0.25in 0.5in 0.25in 0.5in; + tab-interval: 0.5in; + } + p { + margin-left: auto; + margin-top: 0.5em; + margin-bottom: 0.5em; + } + p.list { + margin-left: 0.5in; + margin-top: 0.05em; + margin-bottom: 0.05em; + } + .ubc-name { + margin-left: 0.5in; + white-space: pre; + } + </style> + +</head> + +<body lang="EN-US"> + +<p><b>Eclipse Distribution License - v 1.0</b></p> + +<p>Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors. </p> + +<p>All rights reserved.</p> +<p>Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: +<ul><li>Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. </li> +<li>Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. </li> +<li>Neither the name of the Eclipse Foundation, Inc. nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. </li></ul> +</p> +<p>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE.</p> + +<hr> +<p><b>SHA-1 UbcCheck - MIT</b></p> + +<p>Copyright (c) 2017:</p> +<div class="ubc-name"> +Marc Stevens +Cryptology Group +Centrum Wiskunde & Informatica +P.O. Box 94079, 1090 GB Amsterdam, Netherlands +marc@marc-stevens.nl +</div> +<div class="ubc-name"> +Dan Shumow +Microsoft Research +danshu@microsoft.com +</div> +<p>Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +</p> +<ul><li>The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software.</li></ul> +<p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.</p> + +</body> + +</html> diff --git a/org.eclipse.jgit.ssh.apache.test/build.properties b/org.eclipse.jgit.ssh.apache.test/build.properties new file mode 100644 index 0000000000..9ffa0caf78 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache.test/build.properties @@ -0,0 +1,5 @@ +source.. = tst/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.properties diff --git a/org.eclipse.jgit.ssh.apache.test/plugin.properties b/org.eclipse.jgit.ssh.apache.test/plugin.properties new file mode 100644 index 0000000000..67c296d9e5 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache.test/plugin.properties @@ -0,0 +1,2 @@ +plugin_name=JGit Tests for SSH with Apache MINA sshd +provider_name=Eclipse JGit diff --git a/org.eclipse.jgit.ssh.apache.test/pom.xml b/org.eclipse.jgit.ssh.apache.test/pom.xml new file mode 100644 index 0000000000..0d5463da6d --- /dev/null +++ b/org.eclipse.jgit.ssh.apache.test/pom.xml @@ -0,0 +1,145 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> + and other copyright owners as documented in the project's IP log. + + This program and the accompanying materials are made available + under the terms of the Eclipse Distribution License v1.0 which + accompanies this distribution, is reproduced below, and is + available at http://www.eclipse.org/org/documents/edl-v10.php + + All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, are permitted provided that the following + conditions are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + - Neither the name of the Eclipse Foundation, Inc. nor the + names of its contributors may be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit-parent</artifactId> + <version>5.2.0-SNAPSHOT</version> + </parent> + + <artifactId>org.eclipse.jgit.ssh.apache.test</artifactId> + <name>JGit - Apache sshd SSH Tests</name> + + <description> + JUnit tests for the JGit SSH support based on Apache MINA sshd. + </description> + + <properties> + <maven.javadoc.skip>true</maven.javadoc.skip> + </properties> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> + + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit.junit</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit.ssh.apache</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit.test</artifactId> + <version>${project.version}</version> + </dependency> + + </dependencies> + + <profiles> + <!-- Profile provides a property which enables long running tests. --> + <profile> + <id>test.long</id> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <argLine>-Djgit.test.long=true</argLine> + </configuration> + </plugin> + </plugins> + </build> + </profile> + </profiles> + + <build> + <sourceDirectory>src/</sourceDirectory> + <testSourceDirectory>tst/</testSourceDirectory> + + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>test-jar</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <argLine>-Xmx1024m -Dfile.encoding=UTF-8 -Djava.io.tmpdir=${project.build.directory}</argLine> + <includes> + <include>**/*Test.java</include> + <include>**/*Tests.java</include> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/transport/sshd/ApacheSshTest.java b/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/transport/sshd/ApacheSshTest.java new file mode 100644 index 0000000000..cbbc6386f0 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/transport/sshd/ApacheSshTest.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.transport.sshd; + +import java.io.File; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.util.Arrays; + +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.transport.SshSessionFactory; +import org.eclipse.jgit.transport.ssh.SshTestBase; +import org.eclipse.jgit.transport.sshd.SshdSessionFactory; +import org.eclipse.jgit.util.FS; +import org.junit.experimental.theories.Theories; +import org.junit.runner.RunWith; + +@RunWith(Theories.class) +public class ApacheSshTest extends SshTestBase { + + @Override + protected SshSessionFactory createSessionFactory() { + SshdSessionFactory result = new SshdSessionFactory(new JGitKeyCache()); + // The home directory is mocked at this point! + result.setHomeDirectory(FS.DETECTED.userHome()); + result.setSshDirectory(sshDir); + return result; + } + + @Override + protected void installConfig(String... config) { + File configFile = new File(sshDir, Constants.CONFIG); + if (config != null) { + try { + Files.write(configFile.toPath(), Arrays.asList(config)); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + } + +} diff --git a/org.eclipse.jgit.ssh.apache/.classpath b/org.eclipse.jgit.ssh.apache/.classpath new file mode 100644 index 0000000000..110168ffa1 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/.classpath @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="src" path="src"/> + <classpathentry kind="src" path="resources"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/org.eclipse.jgit.ssh.apache/.fbprefs b/org.eclipse.jgit.ssh.apache/.fbprefs new file mode 100644 index 0000000000..81a0767ff6 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/.fbprefs @@ -0,0 +1,125 @@ +#FindBugs User Preferences +#Mon May 04 16:24:13 PDT 2009 +detectorAppendingToAnObjectOutputStream=AppendingToAnObjectOutputStream|true +detectorBadAppletConstructor=BadAppletConstructor|false +detectorBadResultSetAccess=BadResultSetAccess|true +detectorBadSyntaxForRegularExpression=BadSyntaxForRegularExpression|true +detectorBadUseOfReturnValue=BadUseOfReturnValue|true +detectorBadlyOverriddenAdapter=BadlyOverriddenAdapter|true +detectorBooleanReturnNull=BooleanReturnNull|true +detectorCallToUnsupportedMethod=CallToUnsupportedMethod|true +detectorCheckImmutableAnnotation=CheckImmutableAnnotation|true +detectorCheckTypeQualifiers=CheckTypeQualifiers|true +detectorCloneIdiom=CloneIdiom|false +detectorComparatorIdiom=ComparatorIdiom|true +detectorConfusedInheritance=ConfusedInheritance|true +detectorConfusionBetweenInheritedAndOuterMethod=ConfusionBetweenInheritedAndOuterMethod|true +detectorCrossSiteScripting=CrossSiteScripting|true +detectorDoInsideDoPrivileged=DoInsideDoPrivileged|true +detectorDontCatchIllegalMonitorStateException=DontCatchIllegalMonitorStateException|true +detectorDontUseEnum=DontUseEnum|true +detectorDroppedException=DroppedException|true +detectorDumbMethodInvocations=DumbMethodInvocations|true +detectorDumbMethods=DumbMethods|true +detectorDuplicateBranches=DuplicateBranches|true +detectorEmptyZipFileEntry=EmptyZipFileEntry|true +detectorEqualsOperandShouldHaveClassCompatibleWithThis=EqualsOperandShouldHaveClassCompatibleWithThis|true +detectorFinalizerNullsFields=FinalizerNullsFields|true +detectorFindBadCast2=FindBadCast2|true +detectorFindBadForLoop=FindBadForLoop|true +detectorFindCircularDependencies=FindCircularDependencies|false +detectorFindDeadLocalStores=FindDeadLocalStores|true +detectorFindDoubleCheck=FindDoubleCheck|true +detectorFindEmptySynchronizedBlock=FindEmptySynchronizedBlock|true +detectorFindFieldSelfAssignment=FindFieldSelfAssignment|true +detectorFindFinalizeInvocations=FindFinalizeInvocations|true +detectorFindFloatEquality=FindFloatEquality|true +detectorFindHEmismatch=FindHEmismatch|true +detectorFindInconsistentSync2=FindInconsistentSync2|true +detectorFindJSR166LockMonitorenter=FindJSR166LockMonitorenter|true +detectorFindLocalSelfAssignment2=FindLocalSelfAssignment2|true +detectorFindMaskedFields=FindMaskedFields|true +detectorFindMismatchedWaitOrNotify=FindMismatchedWaitOrNotify|true +detectorFindNakedNotify=FindNakedNotify|true +detectorFindNonSerializableStoreIntoSession=FindNonSerializableStoreIntoSession|true +detectorFindNonSerializableValuePassedToWriteObject=FindNonSerializableValuePassedToWriteObject|true +detectorFindNonShortCircuit=FindNonShortCircuit|true +detectorFindNullDeref=FindNullDeref|true +detectorFindNullDerefsInvolvingNonShortCircuitEvaluation=FindNullDerefsInvolvingNonShortCircuitEvaluation|true +detectorFindOpenStream=FindOpenStream|true +detectorFindPuzzlers=FindPuzzlers|true +detectorFindRefComparison=FindRefComparison|true +detectorFindReturnRef=FindReturnRef|true +detectorFindRunInvocations=FindRunInvocations|true +detectorFindSelfComparison=FindSelfComparison|true +detectorFindSelfComparison2=FindSelfComparison2|true +detectorFindSleepWithLockHeld=FindSleepWithLockHeld|true +detectorFindSpinLoop=FindSpinLoop|true +detectorFindSqlInjection=FindSqlInjection|true +detectorFindTwoLockWait=FindTwoLockWait|true +detectorFindUncalledPrivateMethods=FindUncalledPrivateMethods|true +detectorFindUnconditionalWait=FindUnconditionalWait|true +detectorFindUninitializedGet=FindUninitializedGet|true +detectorFindUnrelatedTypesInGenericContainer=FindUnrelatedTypesInGenericContainer|true +detectorFindUnreleasedLock=FindUnreleasedLock|true +detectorFindUnsatisfiedObligation=FindUnsatisfiedObligation|true +detectorFindUnsyncGet=FindUnsyncGet|true +detectorFindUselessControlFlow=FindUselessControlFlow|true +detectorFormatStringChecker=FormatStringChecker|true +detectorHugeSharedStringConstants=HugeSharedStringConstants|true +detectorIDivResultCastToDouble=IDivResultCastToDouble|true +detectorIncompatMask=IncompatMask|true +detectorInconsistentAnnotations=InconsistentAnnotations|true +detectorInefficientMemberAccess=InefficientMemberAccess|false +detectorInefficientToArray=InefficientToArray|true +detectorInfiniteLoop=InfiniteLoop|true +detectorInfiniteRecursiveLoop=InfiniteRecursiveLoop|true +detectorInfiniteRecursiveLoop2=InfiniteRecursiveLoop2|false +detectorInheritanceUnsafeGetResource=InheritanceUnsafeGetResource|true +detectorInitializationChain=InitializationChain|true +detectorInstantiateStaticClass=InstantiateStaticClass|true +detectorInvalidJUnitTest=InvalidJUnitTest|true +detectorIteratorIdioms=IteratorIdioms|true +detectorLazyInit=LazyInit|true +detectorLoadOfKnownNullValue=LoadOfKnownNullValue|true +detectorMethodReturnCheck=MethodReturnCheck|true +detectorMultithreadedInstanceAccess=MultithreadedInstanceAccess|true +detectorMutableLock=MutableLock|true +detectorMutableStaticFields=MutableStaticFields|true +detectorNaming=Naming|true +detectorNumberConstructor=NumberConstructor|true +detectorOverridingEqualsNotSymmetrical=OverridingEqualsNotSymmetrical|true +detectorPreferZeroLengthArrays=PreferZeroLengthArrays|true +detectorPublicSemaphores=PublicSemaphores|false +detectorQuestionableBooleanAssignment=QuestionableBooleanAssignment|true +detectorReadReturnShouldBeChecked=ReadReturnShouldBeChecked|true +detectorRedundantInterfaces=RedundantInterfaces|true +detectorRepeatedConditionals=RepeatedConditionals|true +detectorRuntimeExceptionCapture=RuntimeExceptionCapture|true +detectorSerializableIdiom=SerializableIdiom|true +detectorStartInConstructor=StartInConstructor|true +detectorStaticCalendarDetector=StaticCalendarDetector|true +detectorStringConcatenation=StringConcatenation|true +detectorSuperfluousInstanceOf=SuperfluousInstanceOf|true +detectorSuspiciousThreadInterrupted=SuspiciousThreadInterrupted|true +detectorSwitchFallthrough=SwitchFallthrough|true +detectorSynchronizeAndNullCheckField=SynchronizeAndNullCheckField|true +detectorSynchronizeOnClassLiteralNotGetClass=SynchronizeOnClassLiteralNotGetClass|true +detectorSynchronizingOnContentsOfFieldToProtectField=SynchronizingOnContentsOfFieldToProtectField|true +detectorURLProblems=URLProblems|true +detectorUncallableMethodOfAnonymousClass=UncallableMethodOfAnonymousClass|true +detectorUnnecessaryMath=UnnecessaryMath|true +detectorUnreadFields=UnreadFields|true +detectorUseObjectEquals=UseObjectEquals|false +detectorUselessSubclassMethod=UselessSubclassMethod|false +detectorVarArgsProblems=VarArgsProblems|true +detectorVolatileUsage=VolatileUsage|true +detectorWaitInLoop=WaitInLoop|true +detectorWrongMapIterator=WrongMapIterator|true +detectorXMLFactoryBypass=XMLFactoryBypass|true +detector_threshold=2 +effort=default +excludefilter0=findBugs/FindBugsExcludeFilter.xml +filter_settings=Medium|BAD_PRACTICE,CORRECTNESS,MT_CORRECTNESS,PERFORMANCE,STYLE|false +filter_settings_neg=MALICIOUS_CODE,NOISE,I18N,SECURITY,EXPERIMENTAL| +run_at_full_build=true diff --git a/org.eclipse.jgit.ssh.apache/.gitignore b/org.eclipse.jgit.ssh.apache/.gitignore new file mode 100644 index 0000000000..934e0e06ff --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/.gitignore @@ -0,0 +1,2 @@ +/bin +/target diff --git a/org.eclipse.jgit.ssh.apache/.project b/org.eclipse.jgit.ssh.apache/.project new file mode 100644 index 0000000000..a7bbd6bafd --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/.project @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.jgit.ssh.apache</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + <nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature> + </natures> +</projectDescription> diff --git a/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.core.resources.prefs b/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000000..66ac15c47c --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,3 @@ +#Mon Aug 11 16:46:12 PDT 2008 +eclipse.preferences.version=1 +encoding/<project>=UTF-8 diff --git a/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.core.runtime.prefs b/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.core.runtime.prefs new file mode 100644 index 0000000000..006e07ede5 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.core.runtime.prefs @@ -0,0 +1,3 @@ +#Mon Mar 24 18:55:50 EDT 2008 +eclipse.preferences.version=1 +line.separator=\n diff --git a/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..13c32a6d94 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,399 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=enabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jgit.annotations.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jgit.annotations.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jgit.annotations.Nullable +org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=warning +org.eclipse.jdt.core.compiler.problem.comparingIdentical=error +org.eclipse.jdt.core.compiler.problem.deadCode=error +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=warning +org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=warning +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=error +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=error +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=error +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private +org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=error +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=error +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=protected +org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=error +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=error +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error +org.eclipse.jdt.core.compiler.problem.nullReference=error +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=ignore +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error +org.eclipse.jdt.core.compiler.problem.potentialNullReference=error +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore +org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=error +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedImport=error +org.eclipse.jdt.core.compiler.problem.unusedLabel=error +org.eclipse.jdt.core.compiler.problem.unusedLocal=error +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=warning +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error +org.eclipse.jdt.core.compiler.source=1.8 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=1 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert +org.eclipse.jdt.core.formatter.comment.line_length=80 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=true +org.eclipse.jdt.core.formatter.join_wrapped_lines=true +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=80 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=tab +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 0000000000..fef3713825 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,66 @@ +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +formatter_profile=_JGit Format +formatter_settings_version=12 +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; +org.eclipse.jdt.ui.ondemandthreshold=99 +org.eclipse.jdt.ui.staticondemandthreshold=99 +org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?><templates/> +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_functional_interfaces=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=true +sp_cleanup.format_source_code_changes_only=true +sp_cleanup.insert_inferred_type_arguments=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=false +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=false +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_redundant_type_arguments=true +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=false +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_anonymous_class_creation=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_lambda=false +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.mylyn.tasks.ui.prefs b/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.mylyn.tasks.ui.prefs new file mode 100644 index 0000000000..823c0f56ae --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.mylyn.tasks.ui.prefs @@ -0,0 +1,4 @@ +#Tue Jul 19 20:11:28 CEST 2011 +eclipse.preferences.version=1 +project.repository.kind=bugzilla +project.repository.url=https\://bugs.eclipse.org/bugs diff --git a/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.mylyn.team.ui.prefs b/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.mylyn.team.ui.prefs new file mode 100644 index 0000000000..0cba949fb7 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.mylyn.team.ui.prefs @@ -0,0 +1,3 @@ +#Tue Jul 19 20:11:28 CEST 2011 +commit.comment.template=${task.description} \n\nBug\: ${task.key} +eclipse.preferences.version=1 diff --git a/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.pde.api.tools.prefs b/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.pde.api.tools.prefs new file mode 100644 index 0000000000..c0030ded71 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.pde.api.tools.prefs @@ -0,0 +1,104 @@ +ANNOTATION_ELEMENT_TYPE_ADDED_FIELD=Error +ANNOTATION_ELEMENT_TYPE_ADDED_METHOD_WITHOUT_DEFAULT_VALUE=Error +ANNOTATION_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error +ANNOTATION_ELEMENT_TYPE_REMOVED_FIELD=Error +ANNOTATION_ELEMENT_TYPE_REMOVED_METHOD=Error +ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error +API_COMPONENT_ELEMENT_TYPE_REMOVED_API_TYPE=Error +API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_API_TYPE=Error +API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_TYPE=Error +API_COMPONENT_ELEMENT_TYPE_REMOVED_TYPE=Error +API_USE_SCAN_FIELD_SEVERITY=Error +API_USE_SCAN_METHOD_SEVERITY=Error +API_USE_SCAN_TYPE_SEVERITY=Error +CLASS_ELEMENT_TYPE_ADDED_FIELD=Error +CLASS_ELEMENT_TYPE_ADDED_METHOD=Error +CLASS_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error +CLASS_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error +CLASS_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error +CLASS_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error +CLASS_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error +CLASS_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error +CLASS_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error +CLASS_ELEMENT_TYPE_REMOVED_CONSTRUCTOR=Error +CLASS_ELEMENT_TYPE_REMOVED_FIELD=Error +CLASS_ELEMENT_TYPE_REMOVED_METHOD=Error +CLASS_ELEMENT_TYPE_REMOVED_SUPERCLASS=Error +CLASS_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error +CLASS_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error +CONSTRUCTOR_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error +CONSTRUCTOR_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error +CONSTRUCTOR_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error +CONSTRUCTOR_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error +ENUM_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error +ENUM_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error +ENUM_ELEMENT_TYPE_REMOVED_ENUM_CONSTANT=Error +ENUM_ELEMENT_TYPE_REMOVED_FIELD=Error +ENUM_ELEMENT_TYPE_REMOVED_METHOD=Error +ENUM_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error +FIELD_ELEMENT_TYPE_ADDED_VALUE=Error +FIELD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error +FIELD_ELEMENT_TYPE_CHANGED_FINAL_TO_NON_FINAL_STATIC_CONSTANT=Error +FIELD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error +FIELD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error +FIELD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error +FIELD_ELEMENT_TYPE_CHANGED_TYPE=Error +FIELD_ELEMENT_TYPE_CHANGED_VALUE=Error +FIELD_ELEMENT_TYPE_REMOVED_TYPE_ARGUMENT=Error +FIELD_ELEMENT_TYPE_REMOVED_VALUE=Error +ILLEGAL_EXTEND=Warning +ILLEGAL_IMPLEMENT=Warning +ILLEGAL_INSTANTIATE=Warning +ILLEGAL_OVERRIDE=Warning +ILLEGAL_REFERENCE=Warning +INTERFACE_ELEMENT_TYPE_ADDED_DEFAULT_METHOD=Error +INTERFACE_ELEMENT_TYPE_ADDED_FIELD=Error +INTERFACE_ELEMENT_TYPE_ADDED_METHOD=Error +INTERFACE_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error +INTERFACE_ELEMENT_TYPE_ADDED_SUPER_INTERFACE_WITH_METHODS=Error +INTERFACE_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error +INTERFACE_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error +INTERFACE_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error +INTERFACE_ELEMENT_TYPE_REMOVED_FIELD=Error +INTERFACE_ELEMENT_TYPE_REMOVED_METHOD=Error +INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error +INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error +INVALID_ANNOTATION=Ignore +INVALID_JAVADOC_TAG=Ignore +INVALID_REFERENCE_IN_SYSTEM_LIBRARIES=Error +LEAK_EXTEND=Warning +LEAK_FIELD_DECL=Warning +LEAK_IMPLEMENT=Warning +LEAK_METHOD_PARAM=Warning +LEAK_METHOD_RETURN_TYPE=Warning +METHOD_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error +METHOD_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error +METHOD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error +METHOD_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error +METHOD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error +METHOD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error +METHOD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error +METHOD_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error +METHOD_ELEMENT_TYPE_REMOVED_ANNOTATION_DEFAULT_VALUE=Error +METHOD_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error +MISSING_EE_DESCRIPTIONS=Warning +TYPE_PARAMETER_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error +TYPE_PARAMETER_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error +TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error +TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error +TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error +TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error +UNUSED_PROBLEM_FILTERS=Warning +automatically_removed_unused_problem_filters=false +changed_execution_env=Error +eclipse.preferences.version=1 +incompatible_api_component_version=Error +incompatible_api_component_version_include_major_without_breaking_change=Disabled +incompatible_api_component_version_include_minor_without_api_change=Disabled +incompatible_api_component_version_report_major_without_breaking_change=Warning +incompatible_api_component_version_report_minor_without_api_change=Ignore +invalid_since_tag_version=Error +malformed_since_tag=Error +missing_since_tag=Error +report_api_breakage_when_major_version_incremented=Disabled +report_resolution_errors_api_component=Warning diff --git a/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.pde.core.prefs b/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 0000000000..82793f2d27 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,3 @@ +#Thu Jan 14 14:34:32 CST 2010 +eclipse.preferences.version=1 +resolve.requirebundle=false diff --git a/org.eclipse.jgit.ssh.apache/BUILD b/org.eclipse.jgit.ssh.apache/BUILD new file mode 100644 index 0000000000..d6a145381c --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/BUILD @@ -0,0 +1,18 @@ +package(default_visibility = ["//visibility:public"]) + +SRCS = glob(["src/**/*.java"]) + +RESOURCES = glob(["resources/**"]) + +java_library( + name = "ssh-apache", + srcs = SRCS, + resource_strip_prefix = "org.eclipse.jgit.ssh.apache/resources", + resources = RESOURCES, + deps = [ + "//lib:slf4j-api", + "//lib:sshd-core", + "//lib:sshd-sftp", + "//org.eclipse.jgit:jgit", + ], +) diff --git a/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..acc81018e8 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF @@ -0,0 +1,76 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %Bundle-Name +Automatic-Module-Name: org.eclipse.jgit.ssh.apache +Bundle-SymbolicName: org.eclipse.jgit.ssh.apache +Bundle-Vendor: %Provider-Name +Bundle-ActivationPolicy: lazy +Bundle-Version: 5.2.0.qualifier +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Export-Package: org.eclipse.jgit.internal.transport.sshd;version="5.2.0";x-internal:=true; + uses:="org.apache.sshd.client, + org.apache.sshd.client.auth, + org.apache.sshd.client.auth.keyboard, + org.apache.sshd.client.auth.pubkey, + org.apache.sshd.client.config.hosts, + org.apache.sshd.client.future, + org.apache.sshd.client.keyverifier, + org.apache.sshd.client.session, + org.apache.sshd.common.config.keys, + org.apache.sshd.common.io, + org.apache.sshd.common.keyprovider, + org.apache.sshd.common.signature, + org.apache.sshd.common.util.buffer, + org.eclipse.jgit.transport", + org.eclipse.jgit.transport.sshd;version="5.2.0"; + uses:="org.apache.sshd.client, + org.apache.sshd.client.config.hosts, + org.apache.sshd.common.keyprovider, + org.apache.sshd.client.keyverifier, + org.eclipse.jgit.internal.transport.sshd, + org.eclipse.jgit.transport, + org.eclipse.jgit.util" +Import-Package: org.apache.sshd.agent;version="[2.0.0,2.1.0)", + org.apache.sshd.client;version="[2.0.0,2.1.0)", + org.apache.sshd.client.auth;version="[2.0.0,2.1.0)", + org.apache.sshd.client.auth.keyboard;version="[2.0.0,2.1.0)", + org.apache.sshd.client.auth.password;version="[2.0.0,2.1.0)", + org.apache.sshd.client.auth.pubkey;version="[2.0.0,2.1.0)", + org.apache.sshd.client.channel;version="[2.0.0,2.1.0)", + org.apache.sshd.client.config.hosts;version="[2.0.0,2.1.0)", + org.apache.sshd.client.config.keys;version="[2.0.0,2.1.0)", + org.apache.sshd.client.future;version="[2.0.0,2.1.0)", + org.apache.sshd.client.keyverifier;version="[2.0.0,2.1.0)", + org.apache.sshd.client.session;version="[2.0.0,2.1.0)", + org.apache.sshd.client.subsystem.sftp;version="[2.0.0,2.1.0)", + org.apache.sshd.common;version="[2.0.0,2.1.0)", + org.apache.sshd.common.auth;version="[2.0.0,2.1.0)", + org.apache.sshd.common.channel;version="[2.0.0,2.1.0)", + org.apache.sshd.common.compression;version="[2.0.0,2.1.0)", + org.apache.sshd.common.config.keys;version="[2.0.0,2.1.0)", + org.apache.sshd.common.digest;version="[2.0.0,2.1.0)", + org.apache.sshd.common.forward;version="[2.0.0,2.1.0)", + org.apache.sshd.common.future;version="[2.0.0,2.1.0)", + org.apache.sshd.common.io;version="[2.0.0,2.1.0)", + org.apache.sshd.common.kex;version="[2.0.0,2.1.0)", + org.apache.sshd.common.keyprovider;version="[2.0.0,2.1.0)", + org.apache.sshd.common.mac;version="[2.0.0,2.1.0)", + org.apache.sshd.common.random;version="[2.0.0,2.1.0)", + org.apache.sshd.common.session;version="[2.0.0,2.1.0)", + org.apache.sshd.common.session.helpers;version="[2.0.0,2.1.0)", + org.apache.sshd.common.signature;version="[2.0.0,2.1.0)", + org.apache.sshd.common.subsystem.sftp;version="[2.0.0,2.1.0)", + org.apache.sshd.common.util;version="[2.0.0,2.1.0)", + org.apache.sshd.common.util.buffer;version="[2.0.0,2.1.0)", + org.apache.sshd.common.util.io;version="[2.0.0,2.1.0)", + org.apache.sshd.common.util.logging;version="[2.0.0,2.1.0)", + org.apache.sshd.common.util.net;version="[2.0.0,2.1.0)", + org.apache.sshd.server.auth;version="[2.0.0,2.1.0)", + org.eclipse.jgit.annotations;version="[5.2.0,5.3.0)", + org.eclipse.jgit.errors;version="[5.2.0,5.3.0)", + org.eclipse.jgit.internal.storage.file;version="[5.2.0,5.3.0)", + org.eclipse.jgit.internal.transport.ssh;version="[5.2.0,5.3.0)", + org.eclipse.jgit.nls;version="[5.2.0,5.3.0)", + org.eclipse.jgit.transport;version="[5.2.0,5.3.0)", + org.eclipse.jgit.util;version="[5.2.0,5.3.0)", + org.slf4j;version="[1.7.0,2.0.0)" diff --git a/org.eclipse.jgit.ssh.apache/about.html b/org.eclipse.jgit.ssh.apache/about.html new file mode 100644 index 0000000000..f971af18d0 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/about.html @@ -0,0 +1,96 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> + +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /> +<title>Eclipse Distribution License - Version 1.0</title> +<style type="text/css"> + body { + size: 8.5in 11.0in; + margin: 0.25in 0.5in 0.25in 0.5in; + tab-interval: 0.5in; + } + p { + margin-left: auto; + margin-top: 0.5em; + margin-bottom: 0.5em; + } + p.list { + margin-left: 0.5in; + margin-top: 0.05em; + margin-bottom: 0.05em; + } + .ubc-name { + margin-left: 0.5in; + white-space: pre; + } + </style> + +</head> + +<body lang="EN-US"> + +<p><b>Eclipse Distribution License - v 1.0</b></p> + +<p>Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors. </p> + +<p>All rights reserved.</p> +<p>Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: +<ul><li>Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. </li> +<li>Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. </li> +<li>Neither the name of the Eclipse Foundation, Inc. nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. </li></ul> +</p> +<p>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE.</p> + +<hr> +<p><b>SHA-1 UbcCheck - MIT</b></p> + +<p>Copyright (c) 2017:</p> +<div class="ubc-name"> +Marc Stevens +Cryptology Group +Centrum Wiskunde & Informatica +P.O. Box 94079, 1090 GB Amsterdam, Netherlands +marc@marc-stevens.nl +</div> +<div class="ubc-name"> +Dan Shumow +Microsoft Research +danshu@microsoft.com +</div> +<p>Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +</p> +<ul><li>The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software.</li></ul> +<p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.</p> + +</body> + +</html> diff --git a/org.eclipse.jgit.ssh.apache/build.properties b/org.eclipse.jgit.ssh.apache/build.properties new file mode 100644 index 0000000000..8148271ef3 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/build.properties @@ -0,0 +1,7 @@ +source.. = src/,\ + resources/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.properties,\ + about.html diff --git a/org.eclipse.jgit.ssh.apache/plugin.properties b/org.eclipse.jgit.ssh.apache/plugin.properties new file mode 100644 index 0000000000..8f3540c0f0 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/plugin.properties @@ -0,0 +1,2 @@ +plugin_name=JGit SSH support based on Apache MINA sshd +provider_name=Eclipse JGit diff --git a/org.eclipse.jgit.ssh.apache/pom.xml b/org.eclipse.jgit.ssh.apache/pom.xml new file mode 100644 index 0000000000..7c62320a29 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/pom.xml @@ -0,0 +1,206 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> + and other copyright owners as documented in the project's IP log. + + This program and the accompanying materials are made available + under the terms of the Eclipse Distribution License v1.0 which + accompanies this distribution, is reproduced below, and is + available at http://www.eclipse.org/org/documents/edl-v10.php + + All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, are permitted provided that the following + conditions are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + - Neither the name of the Eclipse Foundation, Inc. nor the + names of its contributors may be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit-parent</artifactId> + <version>5.2.0-SNAPSHOT</version> + </parent> + + <artifactId>org.eclipse.jgit.ssh.apache</artifactId> + <name>JGit - Apache sshd-based SSH support</name> + + <description> + SSH support for JGit based on Apache MINA sshd + </description> + + <properties> + <translate-qualifier/> + </properties> + + <dependencies> + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>org.apache.sshd</groupId> + <artifactId>sshd-core</artifactId> + <version>${apache-sshd-version}</version> + </dependency> + + <dependency> + <groupId>org.apache.sshd</groupId> + <artifactId>sshd-sftp</artifactId> + <version>${apache-sshd-version}</version> + </dependency> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </dependency> + </dependencies> + + <build> + <sourceDirectory>src/</sourceDirectory> + + <resources> + <resource> + <directory>.</directory> + <includes> + <include>plugin.properties</include> + <include>about.html</include> + </includes> + </resource> + <resource> + <directory>resources/</directory> + </resource> + </resources> + + <plugins> + <plugin> + <artifactId>maven-jar-plugin</artifactId> + <configuration> + <archive> + <manifestFile>${bundle-manifest}</manifestFile> + </archive> + </configuration> + </plugin> + + <plugin> + <groupId>com.github.siom79.japicmp</groupId> + <artifactId>japicmp-maven-plugin</artifactId> + <version>${japicmp-version}</version> + <configuration> + <oldVersion> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>${project.artifactId}</artifactId> + <version>${jgit-last-release-version}</version> + </dependency> + </oldVersion> + <newVersion> + <file> + <path>${project.build.directory}/${project.artifactId}-${project.version}.jar</path> + </file> + </newVersion> + <parameter> + <onlyModified>true</onlyModified> + <includes> + <include>org.eclipse.jgit.*</include> + </includes> + <accessModifier>public</accessModifier> + <breakBuildOnModifications>false</breakBuildOnModifications> + <breakBuildOnBinaryIncompatibleModifications>false</breakBuildOnBinaryIncompatibleModifications> + <onlyBinaryIncompatible>false</onlyBinaryIncompatible> + <includeSynthetic>false</includeSynthetic> + <ignoreMissingClasses>false</ignoreMissingClasses> + <skipPomModules>true</skipPomModules> + </parameter> + <skip>true</skip><!-- TODO: Enable after the first release --> + </configuration> + <executions> + <execution> + <phase>verify</phase> + <goals> + <goal>cmp</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <reporting> + <plugins> + <plugin> + <groupId>com.github.siom79.japicmp</groupId> + <artifactId>japicmp-maven-plugin</artifactId> + <version>${japicmp-version}</version> + <reportSets> + <reportSet> + <reports> + <report>cmp-report</report> + </reports> + </reportSet> + </reportSets> + <configuration> + <oldVersion> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>${project.artifactId}</artifactId> + <version>${jgit-last-release-version}</version> + </dependency> + </oldVersion> + <newVersion> + <file> + <path>${project.build.directory}/${project.artifactId}-${project.version}.jar</path> + </file> + </newVersion> + <parameter> + <onlyModified>true</onlyModified> + <includes> + <include>org.eclipse.jgit.*</include> + </includes> + <accessModifier>public</accessModifier> + <breakBuildOnModifications>false</breakBuildOnModifications> + <breakBuildOnBinaryIncompatibleModifications>false</breakBuildOnBinaryIncompatibleModifications> + <onlyBinaryIncompatible>false</onlyBinaryIncompatible> + <includeSynthetic>false</includeSynthetic> + <ignoreMissingClasses>false</ignoreMissingClasses> + <skipPomModules>true</skipPomModules> + </parameter> + <skip>true</skip><!-- TODO: Enable after the first release --> + </configuration> + </plugin> + </plugins> + </reporting> +</project> diff --git a/org.eclipse.jgit.ssh.apache/resources/org/eclipse/jgit/internal/transport/sshd/SshdText.properties b/org.eclipse.jgit.ssh.apache/resources/org/eclipse/jgit/internal/transport/sshd/SshdText.properties new file mode 100644 index 0000000000..72bca6a975 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/resources/org/eclipse/jgit/internal/transport/sshd/SshdText.properties @@ -0,0 +1,36 @@ +authenticationCanceled=Authentication canceled: no password +closeListenerFailed=Ssh session close listener failed +configInvalidPath=Invalid path in ssh config key {0}: {1} +ftpCloseFailed=Closing the SFTP channel failed +keyEncryptedMsg=Key ''{0}'' is encrypted. Enter the passphrase to decrypt it. +keyEncryptedPrompt=Passphrase +keyLoadFailed=Could not load key ''{0}'' +knownHostsCouldNotUpdate=Could not update known hosts file {0} +knownHostsFileLockedRead=Could not read known hosts file (locked) {0} +knownHostsFileLockedUpdate=Could not update known hosts file (locked) {0} +knownHostsFileReadFailed=Failed to read known hosts file {0} +knownHostsInvalidLine=Known hosts file {0} contains invalid line {1} +knownHostsInvalidPath=Invalid path for known hosts file {0} +knownHostsKeyFingerprints=The {0} key''s fingerprints are: +knownHostsModifiedKeyAcceptPrompt=Accept this key and continue connecting all the same? +knownHostsModifiedKeyDenyMsg=To resolve this add the correct host key to your known hosts file {0} +knownHostsModifiedKeyStorePrompt=If so, also store the new key? +knownHostsModifiedKeyWarning=WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!\n\ +The connection might be compromised (man-in-the-middle attack).\n\ +It is also possible that the {0} key of the host has just been changed.\n\ +The expected {1} key for host ''{2}'' has the fingerprints:\n\ +{3}\n\ +{4}\n\ +The {0} key actually received has the fingerprints:\n\ +{5}\n\ +{6} +knownHostsRevokedKeyMsg=Host ''{0}'' sent a key that is marked as revoked in the known hosts file {1}. +knownHostsUnknownKeyMsg=The authenticity of host ''{0}'' cannot be established. +knownHostsUnknownKeyPrompt=Accept and store this key, and continue connecting? +knownHostsUnknownKeyType=Cannot read server key from known hosts file {0}; line {1} +knownHostsUserAskCreationMsg=File {0} does not exist. +knownHostsUserAskCreationPrompt=Create file {0} ? +sessionCloseFailed=Closing the session failed +sshClosingDown=Apache MINA sshd session factory is closing down; cannot create new ssh sessions on this factory +sshCommandTimeout={0} timed out after {1} seconds while opening the channel +sshProcessStillRunning={0} is not yet completed, cannot get exit code
\ No newline at end of file diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/CachingKeyPairProvider.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/CachingKeyPairProvider.java new file mode 100644 index 0000000000..dcd17af2ff --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/CachingKeyPairProvider.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.internal.transport.sshd; + +import static java.text.MessageFormat.format; + +import java.io.IOException; +import java.nio.file.Path; +import java.security.GeneralSecurityException; +import java.security.KeyPair; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.concurrent.CancellationException; + +import org.apache.sshd.common.keyprovider.FileKeyPairProvider; +import org.eclipse.jgit.transport.sshd.KeyCache; + +/** + * A {@link FileKeyPairProvider} that uses an external {@link KeyCache}. + */ +public class CachingKeyPairProvider extends FileKeyPairProvider { + + private final KeyCache cache; + + /** + * Creates a new {@link CachingKeyPairProvider} using the given + * {@link KeyCache}. If the cache is {@code null}, this is a simple + * {@link FileKeyPairProvider}. + * + * @param paths + * to load keys from + * @param cache + * to use, may be {@code null} if no external caching is desired + */ + public CachingKeyPairProvider(List<Path> paths, KeyCache cache) { + super(paths); + this.cache = cache; + } + + @Override + protected Iterable<KeyPair> loadKeys(Collection<? extends Path> resources) { + if (resources.isEmpty()) { + return Collections.emptyList(); + } + return () -> new CancellingKeyPairIterator(resources); + } + + @Override + protected KeyPair doLoadKey(Path resource) + throws IOException, GeneralSecurityException { + // By calling doLoadKey(String, Path, FilePasswordProvider) instead of + // super.doLoadKey(Path) we can bypass the key caching in + // AbstractResourceKeyPairProvider, over which we have no real control. + String resourceId = resource.toString(); + if (cache == null) { + return doLoadKey(resourceId, resource, getPasswordFinder()); + } + Throwable t[] = { null }; + KeyPair key = cache.get(resource, p -> { + try { + return doLoadKey(resourceId, p, getPasswordFinder()); + } catch (IOException | GeneralSecurityException e) { + t[0] = e; + return null; + } + }); + if (t[0] != null) { + if (t[0] instanceof CancellationException) { + throw (CancellationException) t[0]; + } + throw new IOException( + format(SshdText.get().keyLoadFailed, resource), t[0]); + } + return key; + } + + private class CancellingKeyPairIterator implements Iterator<KeyPair> { + + private final Iterator<Path> paths; + + private KeyPair nextItem; + + private boolean nextSet; + + public CancellingKeyPairIterator(Collection<? extends Path> resources) { + List<Path> copy = new ArrayList<>(resources.size()); + copy.addAll(resources); + paths = copy.iterator(); + } + + @Override + public boolean hasNext() { + if (nextSet) { + return nextItem != null; + } + nextSet = true; + while (nextItem == null && paths.hasNext()) { + try { + nextItem = doLoadKey(paths.next()); + } catch (CancellationException cancelled) { + throw cancelled; + } catch (Exception other) { + log.warn(other.toString()); + } + } + return nextItem != null; + } + + @Override + public KeyPair next() { + if (!nextSet && !hasNext()) { + throw new NoSuchElementException(); + } + KeyPair result = nextItem; + nextItem = null; + nextSet = false; + if (result == null) { + throw new NoSuchElementException(); + } + return result; + } + + } +} diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitClientSession.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitClientSession.java new file mode 100644 index 0000000000..2bde7e711d --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitClientSession.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.internal.transport.sshd; + +import org.apache.sshd.client.ClientFactoryManager; +import org.apache.sshd.client.config.hosts.HostConfigEntry; +import org.apache.sshd.client.session.ClientSessionImpl; +import org.apache.sshd.common.io.IoSession; +import org.eclipse.jgit.transport.CredentialsProvider; + +/** + * A {@link org.apache.sshd.client.session.ClientSession ClientSession} that can + * be associated with the {@link HostConfigEntry} the session was created for. + * The {@link JGitSshClient} creates such sessions and sets this association. + * <p> + * Also provides for associating a JGit {@link CredentialsProvider} with a + * session. + * </p> + */ +public class JGitClientSession extends ClientSessionImpl { + + private HostConfigEntry hostConfig; + + private CredentialsProvider credentialsProvider; + + /** + * @param manager + * @param session + * @throws Exception + */ + public JGitClientSession(ClientFactoryManager manager, IoSession session) + throws Exception { + super(manager, session); + } + + /** + * Retrieves the {@link HostConfigEntry} this session was created for. + * + * @return the {@link HostConfigEntry}, or {@code null} if none set + */ + public HostConfigEntry getHostConfigEntry() { + return hostConfig; + } + + /** + * Sets the {@link HostConfigEntry} this session was created for. + * + * @param hostConfig + * the {@link HostConfigEntry} + */ + public void setHostConfigEntry(HostConfigEntry hostConfig) { + this.hostConfig = hostConfig; + } + + /** + * Sets the {@link CredentialsProvider} for this session. + * + * @param provider + * to set + */ + public void setCredentialsProvider(CredentialsProvider provider) { + credentialsProvider = provider; + } + + /** + * Retrieves the {@link CredentialsProvider} set for this session. + * + * @return the provider, or {@code null}Â if none is set. + */ + public CredentialsProvider getCredentialsProvider() { + return credentialsProvider; + } + +} diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthFactory.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthFactory.java new file mode 100644 index 0000000000..0b3de4ace3 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthFactory.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.internal.transport.sshd; + +import java.util.List; + +import org.apache.sshd.client.auth.AbstractUserAuthFactory; +import org.apache.sshd.client.auth.UserAuth; +import org.apache.sshd.client.auth.pubkey.UserAuthPublicKeyFactory; +import org.apache.sshd.common.NamedFactory; +import org.apache.sshd.common.signature.Signature; +import org.apache.sshd.common.signature.SignatureFactoriesManager; + +/** + * A customized authentication factory for public key user authentication. The + * default implementation {@link UserAuthPublicKeyFactory} ends up doing some + * crazy stream "magic" that loads too many keys too early. + */ +public class JGitPublicKeyAuthFactory extends AbstractUserAuthFactory + implements SignatureFactoriesManager { + + /** The singleton {@link JGitPublicKeyAuthFactory}. */ + public static final JGitPublicKeyAuthFactory INSTANCE = new JGitPublicKeyAuthFactory(); + + private JGitPublicKeyAuthFactory() { + super(UserAuthPublicKeyFactory.NAME); + } + + @Override + public UserAuth create() { + return new JGitPublicKeyAuthentication(getSignatureFactories()); + } + + @Override + public List<NamedFactory<Signature>> getSignatureFactories() { + return null; + } + + @Override + public void setSignatureFactories(List<NamedFactory<Signature>> factories) { + throw new UnsupportedOperationException(); + } +} diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthentication.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthentication.java new file mode 100644 index 0000000000..63b3990b13 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthentication.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.internal.transport.sshd; + +import java.util.List; + +import org.apache.sshd.client.auth.pubkey.UserAuthPublicKey; +import org.apache.sshd.client.session.ClientSession; +import org.apache.sshd.common.NamedFactory; +import org.apache.sshd.common.signature.Signature; + +/** + * A specialized public key authentication handler that uses our own + * {@link JGitPublicKeyIterator}. The super class creates in + * {@link #init(ClientSession, String)} a + * {@link org.apache.sshd.client.auth.pubkey.UserAuthPublicKeyIterator}, which + * in its constructor does some strange {@link java.util.stream.Stream} "magic" + * that ends up loading keys prematurely. + */ +public class JGitPublicKeyAuthentication extends UserAuthPublicKey { + + private ClientSession clientSession; + + private String serviceName; + + /** + * Creates a new {@link JGitPublicKeyAuthentication}. + * + * @param factories + * signature factories to use + */ + public JGitPublicKeyAuthentication( + List<NamedFactory<Signature>> factories) { + super(factories); + } + + @Override + public void init(ClientSession session, String service) throws Exception { + // Do *not* call super.init(); it'll create a UserAuthPublicKeyIterator + // and that's where things then go wrong. Instead, do the whole + // initialization directly here. + clientSession = session; + serviceName = service; + releaseKeys(); + // Use our own iterator! + keys = new JGitPublicKeyIterator(session, this); + } + + @Override + public ClientSession getClientSession() { + return clientSession; + } + + @Override + public ClientSession getSession() { + return clientSession; + } + + @Override + public String getService() { + return serviceName; + } +} diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyIterator.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyIterator.java new file mode 100644 index 0000000000..cda12623d8 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyIterator.java @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.internal.transport.sshd; + +import java.io.IOException; +import java.nio.channels.Channel; +import java.security.KeyPair; +import java.security.PublicKey; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.sshd.agent.SshAgent; +import org.apache.sshd.agent.SshAgentFactory; +import org.apache.sshd.client.auth.pubkey.AbstractKeyPairIterator; +import org.apache.sshd.client.auth.pubkey.KeyAgentIdentity; +import org.apache.sshd.client.auth.pubkey.KeyPairIdentity; +import org.apache.sshd.client.auth.pubkey.PublicKeyIdentity; +import org.apache.sshd.client.config.hosts.HostConfigEntry; +import org.apache.sshd.client.session.ClientSession; +import org.apache.sshd.common.FactoryManager; +import org.apache.sshd.common.keyprovider.KeyIdentityProvider; +import org.apache.sshd.common.signature.SignatureFactoriesManager; + +/** + * A new iterator over key pairs that we use instead of the default + * {@link org.apache.sshd.client.auth.pubkey.UserAuthPublicKeyIterator}, which + * in its constructor does some strange {@link java.util.stream.Stream} "magic" + * that ends up loading keys prematurely. This class uses plain + * {@link Iterator}s instead to avoid that problem. Used in + * {@link JGitPublicKeyAuthentication}. + * + * @see <a href= + * "https://issues.apache.org/jira/projects/SSHD/issues/SSHD-860">Upstream + * issue SSHD-860</a> + */ +public class JGitPublicKeyIterator + extends AbstractKeyPairIterator<PublicKeyIdentity> implements Channel { + + // Re: the cause for the problem mentioned above has not been determined. + // It looks as if either the Apache code inadvertently calls + // GenericUtils.isEmpty() on all streams (which would load the first key + // of each stream), or the Java stream implementation does some prefetching. + // It's not entirely clear. Using Iterators we have more control over + // what happens when. + + private final AtomicBoolean open = new AtomicBoolean(true); + + private SshAgent agent; + + private final List<Iterator<PublicKeyIdentity>> keys = new ArrayList<>(3); + + private final Iterator<Iterator<PublicKeyIdentity>> keyIter; + + private Iterator<PublicKeyIdentity> current; + + private Boolean hasElement; + + /** + * Creates a new {@link JGitPublicKeyIterator}. + * + * @param session + * we're trying to authenticate + * @param signatureFactories + * to use + * @throws Exception + * if an {@link SshAgentFactory} is configured and getting + * identities from the agent fails + */ + public JGitPublicKeyIterator(ClientSession session, + SignatureFactoriesManager signatureFactories) throws Exception { + super(session); + boolean useAgent = true; + if (session instanceof JGitClientSession) { + HostConfigEntry config = ((JGitClientSession) session) + .getHostConfigEntry(); + useAgent = !config.isIdentitiesOnly(); + } + if (useAgent) { + FactoryManager manager = session.getFactoryManager(); + SshAgentFactory factory = manager == null ? null + : manager.getAgentFactory(); + if (factory != null) { + try { + agent = factory.createClient(manager); + keys.add(new AgentIdentityIterator(agent)); + } catch (IOException e) { + try { + closeAgent(); + } catch (IOException err) { + e.addSuppressed(err); + } + throw e; + } + } + } + keys.add( + new KeyPairIdentityIterator(session.getRegisteredIdentities(), + session, signatureFactories)); + keys.add(new KeyPairIdentityIterator(session.getKeyPairProvider(), + session, signatureFactories)); + keyIter = keys.iterator(); + } + + @Override + public boolean isOpen() { + return open.get(); + } + + @Override + public void close() throws IOException { + if (open.getAndSet(false)) { + closeAgent(); + } + } + + @Override + public boolean hasNext() { + if (!isOpen()) { + return false; + } + if (hasElement != null) { + return hasElement.booleanValue(); + } + while (current == null || !current.hasNext()) { + if (keyIter.hasNext()) { + current = keyIter.next(); + } else { + current = null; + hasElement = Boolean.FALSE; + return false; + } + } + hasElement = Boolean.TRUE; + return true; + } + + @Override + public PublicKeyIdentity next() { + if (!isOpen() || hasElement == null && !hasNext() + || !hasElement.booleanValue()) { + throw new NoSuchElementException(); + } + hasElement = null; + PublicKeyIdentity result; + try { + result = current.next(); + } catch (NoSuchElementException e) { + result = null; + } + return result; + } + + private void closeAgent() throws IOException { + if (agent == null) { + return; + } + try { + agent.close(); + } finally { + agent = null; + } + } + + /** + * An {@link Iterator} that maps the data obtained from an agent to + * {@link PublicKeyIdentity}. + */ + private static class AgentIdentityIterator + implements Iterator<PublicKeyIdentity> { + + private final SshAgent agent; + + private final Iterator<? extends Map.Entry<PublicKey, String>> iter; + + public AgentIdentityIterator(SshAgent agent) throws IOException { + this.agent = agent; + iter = agent == null ? null : agent.getIdentities().iterator(); + } + + @Override + public boolean hasNext() { + return iter != null && iter.hasNext(); + } + + @Override + public PublicKeyIdentity next() { + if (iter == null) { + throw new NoSuchElementException(); + } + Map.Entry<PublicKey, String> entry = iter.next(); + return new KeyAgentIdentity(agent, entry.getKey(), + entry.getValue()); + } + } + + /** + * An {@link Iterator} that maps {@link KeyPair} to + * {@link PublicKeyIdentity}. + */ + private static class KeyPairIdentityIterator + implements Iterator<PublicKeyIdentity> { + + private final Iterator<KeyPair> keyPairs; + + private final ClientSession session; + + private final SignatureFactoriesManager signatureFactories; + + public KeyPairIdentityIterator(KeyIdentityProvider provider, + ClientSession session, + SignatureFactoriesManager signatureFactories) { + this.session = session; + this.signatureFactories = signatureFactories; + keyPairs = provider == null ? null : provider.loadKeys().iterator(); + } + + @Override + public boolean hasNext() { + return keyPairs != null && keyPairs.hasNext(); + } + + @Override + public PublicKeyIdentity next() { + if (keyPairs == null) { + throw new NoSuchElementException(); + } + KeyPair key = keyPairs.next(); + return new KeyPairIdentity(signatureFactories, session, key); + } + } +} diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshClient.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshClient.java new file mode 100644 index 0000000000..98d4e3e5e5 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshClient.java @@ -0,0 +1,320 @@ +/* + * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.internal.transport.sshd; + +import static java.text.MessageFormat.format; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.file.Files; +import java.nio.file.InvalidPathException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.KeyPair; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.apache.sshd.client.SshClient; +import org.apache.sshd.client.config.hosts.HostConfigEntry; +import org.apache.sshd.client.future.ConnectFuture; +import org.apache.sshd.client.future.DefaultConnectFuture; +import org.apache.sshd.client.session.ClientSessionImpl; +import org.apache.sshd.client.session.SessionFactory; +import org.apache.sshd.common.future.SshFutureListener; +import org.apache.sshd.common.io.IoConnectFuture; +import org.apache.sshd.common.io.IoSession; +import org.apache.sshd.common.keyprovider.FileKeyPairProvider; +import org.apache.sshd.common.keyprovider.KeyPairProvider; +import org.apache.sshd.common.session.helpers.AbstractSession; +import org.apache.sshd.common.util.ValidateUtils; +import org.eclipse.jgit.transport.CredentialsProvider; +import org.eclipse.jgit.transport.SshConstants; +import org.eclipse.jgit.transport.sshd.KeyCache; + +/** + * Customized {@link SshClient} for JGit. It creates specialized + * {@link JGitClientSession}s that know about the {@link HostConfigEntry} they + * were created for, and it loads all KeyPair identities lazily. + */ +public class JGitSshClient extends SshClient { + + private KeyCache keyCache; + + private CredentialsProvider credentialsProvider; + + @Override + protected SessionFactory createSessionFactory() { + // Override the parent's default + return new JGitSessionFactory(this); + } + + @Override + public ConnectFuture connect(HostConfigEntry hostConfig) + throws IOException { + if (connector == null) { + throw new IllegalStateException("SshClient not started."); //$NON-NLS-1$ + } + Objects.requireNonNull(hostConfig, "No host configuration"); //$NON-NLS-1$ + String host = ValidateUtils.checkNotNullAndNotEmpty( + hostConfig.getHostName(), "No target host"); //$NON-NLS-1$ + int port = hostConfig.getPort(); + ValidateUtils.checkTrue(port > 0, "Invalid port: %d", port); //$NON-NLS-1$ + String userName = hostConfig.getUsername(); + InetSocketAddress address = new InetSocketAddress(host, port); + ConnectFuture connectFuture = new DefaultConnectFuture( + userName + '@' + address, null); + SshFutureListener<IoConnectFuture> listener = createConnectCompletionListener( + connectFuture, userName, address, hostConfig); + connector.connect(address).addListener(listener); + return connectFuture; + } + + private SshFutureListener<IoConnectFuture> createConnectCompletionListener( + ConnectFuture connectFuture, String username, + InetSocketAddress address, HostConfigEntry hostConfig) { + return new SshFutureListener<IoConnectFuture>() { + + @Override + public void operationComplete(IoConnectFuture future) { + if (future.isCanceled()) { + connectFuture.cancel(); + return; + } + Throwable t = future.getException(); + if (t != null) { + connectFuture.setException(t); + return; + } + IoSession ioSession = future.getSession(); + try { + JGitClientSession session = createSession(ioSession, + username, address, hostConfig); + connectFuture.setSession(session); + } catch (RuntimeException e) { + connectFuture.setException(e); + ioSession.close(true); + } + } + + @Override + public String toString() { + return "JGitSshClient$ConnectCompletionListener[" + username //$NON-NLS-1$ + + '@' + address + ']'; + } + }; + } + + private JGitClientSession createSession(IoSession ioSession, + String username, InetSocketAddress address, + HostConfigEntry hostConfig) { + AbstractSession rawSession = AbstractSession.getSession(ioSession); + if (!(rawSession instanceof JGitClientSession)) { + throw new IllegalStateException("Wrong session type: " //$NON-NLS-1$ + + rawSession.getClass().getCanonicalName()); + } + JGitClientSession session = (JGitClientSession) rawSession; + session.setUsername(username); + session.setConnectAddress(address); + session.setHostConfigEntry(hostConfig); + if (session.getCredentialsProvider() == null) { + session.setCredentialsProvider(getCredentialsProvider()); + } + FileKeyPairProvider ourConfiguredKeysProvider = null; + List<Path> identities = hostConfig.getIdentities().stream() + .map(s -> { + try { + return Paths.get(s); + } catch (InvalidPathException e) { + log.warn(format(SshdText.get().configInvalidPath, + SshConstants.IDENTITY_FILE, s), e); + return null; + } + }).filter(p -> p != null && Files.exists(p)) + .collect(Collectors.toList()); + ourConfiguredKeysProvider = new CachingKeyPairProvider(identities, + keyCache); + ourConfiguredKeysProvider.setPasswordFinder(getFilePasswordProvider()); + if (hostConfig.isIdentitiesOnly()) { + session.setKeyPairProvider(ourConfiguredKeysProvider); + } else { + KeyPairProvider defaultKeysProvider = getKeyPairProvider(); + if (defaultKeysProvider instanceof FileKeyPairProvider) { + ((FileKeyPairProvider) defaultKeysProvider) + .setPasswordFinder(getFilePasswordProvider()); + } + KeyPairProvider combinedProvider = new CombinedKeyPairProvider( + ourConfiguredKeysProvider, defaultKeysProvider); + session.setKeyPairProvider(combinedProvider); + } + return session; + } + + /** + * Set a cache for loaded keys. Newly discovered keys will be added when + * IdentityFile host entries from the ssh config file are used during + * session authentication. + * + * @param cache + * to use + */ + public void setKeyCache(KeyCache cache) { + keyCache = cache; + } + + /** + * Sets the {@link CredentialsProvider} for this client. + * + * @param provider + * to set + */ + public void setCredentialsProvider(CredentialsProvider provider) { + credentialsProvider = provider; + } + + /** + * Retrieves the {@link CredentialsProvider} set for this client. + * + * @return the provider, or {@code null}Â if none is set. + */ + public CredentialsProvider getCredentialsProvider() { + return credentialsProvider; + } + + /** + * A {@link SessionFactory} to create our own specialized + * {@link JGitClientSession}s. + */ + private static class JGitSessionFactory extends SessionFactory { + + public JGitSessionFactory(JGitSshClient client) { + super(client); + } + + @Override + protected ClientSessionImpl doCreateSession(IoSession ioSession) + throws Exception { + return new JGitClientSession(getClient(), ioSession); + } + } + + /** + * A {@link KeyPairProvider} that iterates over the {@link Iterable}s + * returned by other {@link KeyPairProvider}s. + */ + private static class CombinedKeyPairProvider implements KeyPairProvider { + + private final List<KeyPairProvider> providers; + + public CombinedKeyPairProvider(KeyPairProvider... providers) { + this(Arrays.stream(providers).filter(Objects::nonNull) + .collect(Collectors.toList())); + } + + public CombinedKeyPairProvider(List<KeyPairProvider> providers) { + this.providers = providers; + } + + @Override + public Iterable<String> getKeyTypes() { + throw new UnsupportedOperationException( + "Should not have been called in a ssh client"); //$NON-NLS-1$ + } + + @Override + public KeyPair loadKey(String type) { + throw new UnsupportedOperationException( + "Should not have been called in a ssh client"); //$NON-NLS-1$ + } + + @Override + public Iterable<KeyPair> loadKeys() { + return () -> new Iterator<KeyPair>() { + + private Iterator<KeyPairProvider> factories = providers.iterator(); + private Iterator<KeyPair> current; + + private Boolean hasElement; + + @Override + public boolean hasNext() { + if (hasElement != null) { + return hasElement.booleanValue(); + } + while (current == null || !current.hasNext()) { + if (factories.hasNext()) { + current = factories.next().loadKeys().iterator(); + } else { + current = null; + hasElement = Boolean.FALSE; + return false; + } + } + hasElement = Boolean.TRUE; + return true; + } + + @Override + public KeyPair next() { + if (hasElement == null && !hasNext() + || !hasElement.booleanValue()) { + throw new NoSuchElementException(); + } + hasElement = null; + KeyPair result; + try { + result = current.next(); + } catch (NoSuchElementException e) { + result = null; + } + return result; + } + + }; + } + + } +} diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitUserInteraction.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitUserInteraction.java new file mode 100644 index 0000000000..a96a6962cc --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitUserInteraction.java @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.internal.transport.sshd; + +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.List; + +import org.apache.sshd.client.auth.keyboard.UserInteraction; +import org.apache.sshd.client.session.ClientSession; +import org.eclipse.jgit.transport.CredentialItem; +import org.eclipse.jgit.transport.CredentialsProvider; +import org.eclipse.jgit.transport.SshConstants; +import org.eclipse.jgit.transport.URIish; + +/** + * A {@link UserInteraction} callback implementation based on a + * {@link CredentialsProvider}. + */ +public class JGitUserInteraction implements UserInteraction { + + private final CredentialsProvider provider; + + /** + * Creates a new {@link JGitUserInteraction} for interactive password input + * based on the given {@link CredentialsProvider}. + * + * @param provider + * to use + */ + public JGitUserInteraction(CredentialsProvider provider) { + this.provider = provider; + } + + @Override + public boolean isInteractionAllowed(ClientSession session) { + return provider.isInteractive(); + } + + @Override + public String[] interactive(ClientSession session, String name, + String instruction, String lang, String[] prompt, boolean[] echo) { + // This is keyboard-interactive authentication + List<CredentialItem> items = new ArrayList<>(); + int numberOfHiddenInputs = 0; + for (int i = 0; i < prompt.length; i++) { + boolean hidden = i < echo.length && !echo[i]; + if (hidden) { + numberOfHiddenInputs++; + } + } + // RFC 4256 (SSH_MSG_USERAUTH_INFO_REQUEST) says: "The language tag is + // deprecated and SHOULD be the empty string." and "[If there are no + // prompts] the client SHOULD still display the name and instruction + // fields" and "[The] client SHOULD print the name and instruction (if + // non-empty)" + if (name != null && !name.isEmpty()) { + items.add(new CredentialItem.InformationalMessage(name)); + } + if (instruction != null && !instruction.isEmpty()) { + items.add(new CredentialItem.InformationalMessage(instruction)); + } + for (int i = 0; i < prompt.length; i++) { + boolean hidden = i < echo.length && !echo[i]; + if (hidden && numberOfHiddenInputs == 1) { + // We need to somehow trigger storing the password in the + // Eclipse secure storage in EGit. Currently, this is done only + // for password fields. + items.add(new CredentialItem.Password()); + // TODO Possibly change EGit to store all hidden strings + // (keyed by the URI and the prompt?) so that we don't have to + // use this kludge here. + } else { + items.add(new CredentialItem.StringType(prompt[i], hidden)); + } + } + if (items.isEmpty()) { + // Huh? No info, no prompts? + return prompt; // Is known to have length zero here + } + URIish uri = toURI(session.getUsername(), + (InetSocketAddress) session.getIoSession().getRemoteAddress()); + if (provider.get(uri, items)) { + return items.stream().map(i -> { + if (i instanceof CredentialItem.Password) { + return new String(((CredentialItem.Password) i).getValue()); + } else if (i instanceof CredentialItem.StringType) { + return ((CredentialItem.StringType) i).getValue(); + } + return null; + }).filter(s -> s != null).toArray(String[]::new); + } + // TODO What to throw to abort the connection/authentication process? + // In UserAuthKeyboardInteractive.getUserResponses() it's clear that + // returning null is valid and signifies "an error"; we'll try the + // next authentication method. But if the user explicitly canceled, + // then we don't want to try the next methods... + // + // Probably not a serious issue with the typical order of public-key, + // keyboard-interactive, password. + return null; + } + + @Override + public String getUpdatedPassword(ClientSession session, String prompt, + String lang) { + // TODO Implement password update in password authentication? + return null; + } + + /** + * Creates a {@link URIish} from the given remote address and user name. + * + * @param userName + * for the uri + * @param remote + * address of the remote host + * @return the uri, with {@link SshConstants#SSH_SCHEME} as scheme + */ + public static URIish toURI(String userName, InetSocketAddress remote) { + String host = remote.getHostString(); + int port = remote.getPort(); + return new URIish() // + .setScheme(SshConstants.SSH_SCHEME) // + .setHost(host) // + .setPort(port) // + .setUser(userName); + } +} diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyVerifier.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyVerifier.java new file mode 100644 index 0000000000..a20ee6bb84 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyVerifier.java @@ -0,0 +1,718 @@ +/* + * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.internal.transport.sshd; + +import static java.text.MessageFormat.format; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.InvalidPathException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.GeneralSecurityException; +import java.security.PublicKey; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Supplier; + +import org.apache.sshd.client.config.hosts.HostConfigEntry; +import org.apache.sshd.client.config.hosts.KnownHostEntry; +import org.apache.sshd.client.keyverifier.KnownHostsServerKeyVerifier; +import org.apache.sshd.client.keyverifier.KnownHostsServerKeyVerifier.HostEntryPair; +import org.apache.sshd.client.keyverifier.ServerKeyVerifier; +import org.apache.sshd.client.session.ClientSession; +import org.apache.sshd.common.config.keys.AuthorizedKeyEntry; +import org.apache.sshd.common.config.keys.KeyUtils; +import org.apache.sshd.common.config.keys.PublicKeyEntryResolver; +import org.apache.sshd.common.digest.BuiltinDigests; +import org.apache.sshd.common.util.io.ModifiableFileWatcher; +import org.apache.sshd.common.util.net.SshdSocketAddress; +import org.eclipse.jgit.internal.storage.file.LockFile; +import org.eclipse.jgit.transport.CredentialItem; +import org.eclipse.jgit.transport.CredentialsProvider; +import org.eclipse.jgit.transport.SshConstants; +import org.eclipse.jgit.transport.URIish; +import org.eclipse.jgit.transport.sshd.JGitHostConfigEntry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A sever host key verifier that honors the {@code StrictHostKeyChecking} and + * {@code UserKnownHostsFile} values from the ssh configuration. + * <p> + * The verifier can be given default known_hosts files in the constructor, which + * will be used if the ssh config does not specify a {@code UserKnownHostsFile}. + * If the ssh config <em>does</em> set {@code UserKnownHostsFile}, the verifier + * uses the given files in the order given. Non-existing or unreadable files are + * ignored. + * <p> + * {@code StrictHostKeyChecking} accepts the following values: + * </p> + * <dl> + * <dt>ask</dt> + * <dd>Ask the user whether new or changed keys shall be accepted and be added + * to the known_hosts file.</dd> + * <dt>yes/true</dt> + * <dd>Accept only keys listed in the known_hosts file.</dd> + * <dt>no/false</dt> + * <dd>Silently accept all new or changed keys, add new keys to the known_hosts + * file.</dd> + * <dt>accept-new</dt> + * <dd>Silently accept keys for new hosts and add them to the known_hosts + * file.</dd> + * </dl> + * <p> + * If {@code StrictHostKeyChecking} is not set, or set to any other value, the + * default value <b>ask</b> is active. + * </p> + * <p> + * This implementation relies on the {@link ClientSession} being a + * {@link JGitClientSession}. By default Apache MINA sshd does not forward the + * config file host entry to the session, so it would be unknown here which + * entry it was and what setting of {@code StrictHostKeyChecking} should be + * used. If used with some other session type, the implementation assumes + * "<b>ask</b>". + * <p> + * <p> + * Asking the user is done via a {@link CredentialsProvider} obtained from the + * session. If none is set, the implementation falls back to strict host key + * checking ("<b>yes</b>"). + * </p> + * <p> + * Note that adding a key to the known hosts file may create the file. You can + * specify in the constructor whether the user shall be asked about that, too. + * If the the user declines updating the file, but the key was otherwise + * accepted (user confirmed for "<b>ask</b>", or "no" or "accept-new" are + * active), the key is accepted for this session only. + * </p> + * <p> + * If several known hosts files are specified, a new key is always added to the + * first file (even if it doesn't exist yet; see the note about file creation + * above). + * </p> + * + * @see <a href="http://man.openbsd.org/OpenBSD-current/man5/ssh_config.5">man + * ssh-config</a> + */ +public class OpenSshServerKeyVerifier implements ServerKeyVerifier { + + // TODO: GlobalKnownHostsFile? May need some kind of LRU caching; these + // files may be large! + + private static final Logger LOG = LoggerFactory + .getLogger(OpenSshServerKeyVerifier.class); + + /** Can be used to mark revoked known host lines. */ + private static final String MARKER_REVOKED = "revoked"; //$NON-NLS-1$ + + private final boolean askAboutNewFile; + + private final Map<Path, HostKeyFile> knownHostsFiles = new ConcurrentHashMap<>(); + + private final List<HostKeyFile> defaultFiles = new ArrayList<>(); + + private enum ModifiedKeyHandling { + DENY, ALLOW, ALLOW_AND_STORE + } + + /** + * Creates a new {@link OpenSshServerKeyVerifier}. + * + * @param askAboutNewFile + * whether to ask the user, if possible, about creating a new + * non-existing known_hosts file + * @param defaultFiles + * typically ~/.ssh/known_hosts and ~/.ssh/known_hosts2. May be + * empty or {@code null}, in which case no default files are + * installed. The files need not exist. + */ + public OpenSshServerKeyVerifier(boolean askAboutNewFile, List<File> defaultFiles) { + if (defaultFiles != null) { + for (File file : defaultFiles) { + Path p = file.toPath(); + HostKeyFile newFile = new HostKeyFile(p); + knownHostsFiles.put(p, newFile); + this.defaultFiles.add(newFile); + } + } + this.askAboutNewFile = askAboutNewFile; + } + + @Override + public boolean verifyServerKey(ClientSession clientSession, + SocketAddress remoteAddress, PublicKey serverKey) { + List<HostKeyFile> filesToUse = defaultFiles; + if (clientSession instanceof JGitClientSession) { + HostConfigEntry entry = ((JGitClientSession) clientSession) + .getHostConfigEntry(); + if (entry instanceof JGitHostConfigEntry) { + // Always true! + List<HostKeyFile> userFiles = addUserHostKeyFiles( + ((JGitHostConfigEntry) entry).getMultiValuedOptions() + .get(SshConstants.USER_KNOWN_HOSTS_FILE)); + if (!userFiles.isEmpty()) { + filesToUse = userFiles; + } + } + } + AskUser ask = new AskUser(); + HostEntryPair[] modified = { null }; + Path path = null; + HostKeyHelper helper = new HostKeyHelper(); + for (HostKeyFile file : filesToUse) { + try { + if (find(clientSession, remoteAddress, serverKey, file.get(), + modified, helper)) { + return true; + } + } catch (RevokedKeyException e) { + ask.revokedKey(clientSession, remoteAddress, serverKey, + file.getPath()); + return false; + } + if (path == null && modified[0] != null) { + // Remember the file in which we might need to update the + // entry + path = file.getPath(); + } + } + if (modified[0] != null) { + // We found an entry, but with a different key + ModifiedKeyHandling toDo = ask.acceptModifiedServerKey( + clientSession, remoteAddress, modified[0].getServerKey(), + serverKey, path); + if (toDo == ModifiedKeyHandling.ALLOW_AND_STORE) { + try { + updateModifiedServerKey(clientSession, remoteAddress, + serverKey, modified[0], path, helper); + knownHostsFiles.get(path).resetReloadAttributes(); + } catch (IOException e) { + LOG.warn(format(SshdText.get().knownHostsCouldNotUpdate, + path)); + } + } + if (toDo == ModifiedKeyHandling.DENY) { + return false; + } + // TODO: OpenSsh disables password and keyboard-interactive + // authentication in this case. Also agent and local port forwarding + // are switched off. (Plus a few other things such as X11 forwarding + // that are of no interest to a git client.) + return true; + } else if (ask.acceptUnknownKey(clientSession, remoteAddress, + serverKey)) { + if (!filesToUse.isEmpty()) { + HostKeyFile toUpdate = filesToUse.get(0); + path = toUpdate.getPath(); + try { + updateKnownHostsFile(clientSession, remoteAddress, + serverKey, path, helper); + toUpdate.resetReloadAttributes(); + } catch (IOException e) { + LOG.warn(format(SshdText.get().knownHostsCouldNotUpdate, + path)); + } + } + return true; + } + return false; + } + + private static class RevokedKeyException extends Exception { + private static final long serialVersionUID = 1L; + } + + private boolean find(ClientSession clientSession, + SocketAddress remoteAddress, PublicKey serverKey, + List<HostEntryPair> entries, HostEntryPair[] modified, + HostKeyHelper helper) throws RevokedKeyException { + Collection<SshdSocketAddress> candidates = helper + .resolveHostNetworkIdentities(clientSession, remoteAddress); + for (HostEntryPair current : entries) { + KnownHostEntry entry = current.getHostEntry(); + for (SshdSocketAddress host : candidates) { + if (entry.isHostMatch(host.getHostName(), host.getPort())) { + boolean isRevoked = MARKER_REVOKED + .equals(entry.getMarker()); + if (KeyUtils.compareKeys(serverKey, + current.getServerKey())) { + // Exact match + if (isRevoked) { + throw new RevokedKeyException(); + } + modified[0] = null; + return true; + } else if (!isRevoked) { + // Server sent a different key + modified[0] = current; + // Keep going -- maybe there's another entry for this + // host + } + } + } + } + return false; + } + + private List<HostKeyFile> addUserHostKeyFiles(List<String> fileNames) { + if (fileNames == null || fileNames.isEmpty()) { + return Collections.emptyList(); + } + List<HostKeyFile> userFiles = new ArrayList<>(); + for (String name : fileNames) { + try { + Path path = Paths.get(name); + HostKeyFile file = knownHostsFiles.computeIfAbsent(path, + p -> new HostKeyFile(path)); + userFiles.add(file); + } catch (InvalidPathException e) { + LOG.warn(format(SshdText.get().knownHostsInvalidPath, + name)); + } + } + return userFiles; + } + + private void updateKnownHostsFile(ClientSession clientSession, + SocketAddress remoteAddress, PublicKey serverKey, Path path, + HostKeyHelper updater) + throws IOException { + KnownHostEntry entry = updater.prepareKnownHostEntry(clientSession, + remoteAddress, serverKey); + if (entry == null) { + return; + } + if (!Files.exists(path)) { + if (askAboutNewFile) { + CredentialsProvider provider = getCredentialsProvider( + clientSession); + if (provider == null) { + // We can't ask, so don't create the file + return; + } + URIish uri = new URIish().setPath(path.toString()); + if (!askUser(provider, uri, // + format(SshdText.get().knownHostsUserAskCreationPrompt, + path), // + format(SshdText.get().knownHostsUserAskCreationMsg, + path))) { + return; + } + } + } + LockFile lock = new LockFile(path.toFile()); + if (lock.lockForAppend()) { + try { + try (BufferedWriter writer = new BufferedWriter( + new OutputStreamWriter(lock.getOutputStream(), + StandardCharsets.UTF_8))) { + writer.newLine(); + writer.write(entry.getConfigLine()); + writer.newLine(); + } + lock.commit(); + } catch (IOException e) { + lock.unlock(); + throw e; + } + } else { + LOG.warn(format(SshdText.get().knownHostsFileLockedUpdate, + path)); + } + } + + private void updateModifiedServerKey(ClientSession clientSession, + SocketAddress remoteAddress, PublicKey serverKey, + HostEntryPair entry, Path path, HostKeyHelper helper) + throws IOException { + KnownHostEntry hostEntry = entry.getHostEntry(); + String oldLine = hostEntry.getConfigLine(); + String newLine = helper.prepareModifiedServerKeyLine(clientSession, + remoteAddress, hostEntry, oldLine, entry.getServerKey(), + serverKey); + if (newLine == null || newLine.isEmpty()) { + return; + } + if (oldLine == null || oldLine.isEmpty() || newLine.equals(oldLine)) { + // Shouldn't happen. + return; + } + LockFile lock = new LockFile(path.toFile()); + if (lock.lock()) { + try { + try (BufferedWriter writer = new BufferedWriter( + new OutputStreamWriter(lock.getOutputStream(), + StandardCharsets.UTF_8)); + BufferedReader reader = Files.newBufferedReader(path, + StandardCharsets.UTF_8)) { + boolean done = false; + String line; + while ((line = reader.readLine()) != null) { + String toWrite = line; + if (!done) { + int pos = line.indexOf('#'); + String toTest = pos < 0 ? line + : line.substring(0, pos); + if (toTest.trim().equals(oldLine)) { + toWrite = newLine; + done = true; + } + } + writer.write(toWrite); + writer.newLine(); + } + } + lock.commit(); + } catch (IOException e) { + lock.unlock(); + throw e; + } + } else { + LOG.warn(format(SshdText.get().knownHostsFileLockedUpdate, + path)); + } + } + + private static CredentialsProvider getCredentialsProvider( + ClientSession session) { + if (session instanceof JGitClientSession) { + return ((JGitClientSession) session).getCredentialsProvider(); + } + return null; + } + + private static boolean askUser(CredentialsProvider provider, URIish uri, + String prompt, String... messages) { + List<CredentialItem> items = new ArrayList<>(messages.length + 1); + for (String message : messages) { + items.add(new CredentialItem.InformationalMessage(message)); + } + if (prompt != null) { + CredentialItem.YesNoType answer = new CredentialItem.YesNoType( + prompt); + items.add(answer); + return provider.get(uri, items) && answer.getValue(); + } else { + return provider.get(uri, items); + } + } + + private static class AskUser { + + private enum Check { + ASK, DENY, ALLOW; + } + + @SuppressWarnings("nls") + private Check checkMode(ClientSession session, + SocketAddress remoteAddress, boolean changed) { + if (!(remoteAddress instanceof InetSocketAddress)) { + return Check.DENY; + } + if (session instanceof JGitClientSession) { + HostConfigEntry entry = ((JGitClientSession) session) + .getHostConfigEntry(); + String value = entry.getProperty( + SshConstants.STRICT_HOST_KEY_CHECKING, "ask"); + switch (value.toLowerCase(Locale.ROOT)) { + case SshConstants.YES: + case SshConstants.ON: + return Check.DENY; + case SshConstants.NO: + case SshConstants.OFF: + return Check.ALLOW; + case "accept-new": + return changed ? Check.DENY : Check.ALLOW; + default: + break; + } + } + if (getCredentialsProvider(session) == null) { + // This is called only for new, unknown hosts. If we have no way + // to interact with the user, the fallback mode is to deny the + // key. + return Check.DENY; + } + return Check.ASK; + } + + public void revokedKey(ClientSession clientSession, + SocketAddress remoteAddress, PublicKey serverKey, Path path) { + CredentialsProvider provider = getCredentialsProvider( + clientSession); + if (provider == null) { + return; + } + InetSocketAddress remote = (InetSocketAddress) remoteAddress; + URIish uri = JGitUserInteraction.toURI(clientSession.getUsername(), + remote); + String sha256 = KeyUtils.getFingerPrint(BuiltinDigests.sha256, + serverKey); + String md5 = KeyUtils.getFingerPrint(BuiltinDigests.md5, serverKey); + String keyAlgorithm = serverKey.getAlgorithm(); + askUser(provider, uri, null, // + format(SshdText.get().knownHostsRevokedKeyMsg, + remote.getHostString(), path), + format(SshdText.get().knownHostsKeyFingerprints, + keyAlgorithm), + md5, sha256); + } + + public boolean acceptUnknownKey(ClientSession clientSession, + SocketAddress remoteAddress, PublicKey serverKey) { + Check check = checkMode(clientSession, remoteAddress, false); + if (check != Check.ASK) { + return check == Check.ALLOW; + } + CredentialsProvider provider = getCredentialsProvider( + clientSession); + InetSocketAddress remote = (InetSocketAddress) remoteAddress; + // Ask the user + String sha256 = KeyUtils.getFingerPrint(BuiltinDigests.sha256, + serverKey); + String md5 = KeyUtils.getFingerPrint(BuiltinDigests.md5, serverKey); + String keyAlgorithm = serverKey.getAlgorithm(); + String remoteHost = remote.getHostString(); + URIish uri = JGitUserInteraction.toURI(clientSession.getUsername(), + remote); + String prompt = SshdText.get().knownHostsUnknownKeyPrompt; + return askUser(provider, uri, prompt, // + format(SshdText.get().knownHostsUnknownKeyMsg, + remoteHost), + format(SshdText.get().knownHostsKeyFingerprints, + keyAlgorithm), + md5, sha256); + } + + public ModifiedKeyHandling acceptModifiedServerKey( + ClientSession clientSession, + SocketAddress remoteAddress, PublicKey expected, + PublicKey actual, Path path) { + Check check = checkMode(clientSession, remoteAddress, true); + if (check == Check.ALLOW) { + // Never auto-store on CHECK.ALLOW + return ModifiedKeyHandling.ALLOW; + } + InetSocketAddress remote = (InetSocketAddress) remoteAddress; + String keyAlgorithm = actual.getAlgorithm(); + String remoteHost = remote.getHostString(); + URIish uri = JGitUserInteraction.toURI(clientSession.getUsername(), + remote); + List<String> messages = new ArrayList<>(); + String warning = format( + SshdText.get().knownHostsModifiedKeyWarning, + keyAlgorithm, expected.getAlgorithm(), remoteHost, + KeyUtils.getFingerPrint(BuiltinDigests.md5, expected), + KeyUtils.getFingerPrint(BuiltinDigests.sha256, expected), + KeyUtils.getFingerPrint(BuiltinDigests.md5, actual), + KeyUtils.getFingerPrint(BuiltinDigests.sha256, actual)); + for (String line : warning.split("\n")) { //$NON-NLS-1$ + messages.add(line); + } + + CredentialsProvider provider = getCredentialsProvider( + clientSession); + if (check == Check.DENY) { + if (provider != null) { + messages.add(format( + SshdText.get().knownHostsModifiedKeyDenyMsg, path)); + askUser(provider, uri, null, + messages.toArray(new String[0])); + } + return ModifiedKeyHandling.DENY; + } + // ASK -- two questions: procceed? and store? + List<CredentialItem> items = new ArrayList<>(messages.size() + 2); + for (String message : messages) { + items.add(new CredentialItem.InformationalMessage(message)); + } + CredentialItem.YesNoType proceed = new CredentialItem.YesNoType( + SshdText.get().knownHostsModifiedKeyAcceptPrompt); + CredentialItem.YesNoType store = new CredentialItem.YesNoType( + SshdText.get().knownHostsModifiedKeyStorePrompt); + items.add(proceed); + items.add(store); + if (provider.get(uri, items) && proceed.getValue()) { + return store.getValue() ? ModifiedKeyHandling.ALLOW_AND_STORE + : ModifiedKeyHandling.ALLOW; + } + return ModifiedKeyHandling.DENY; + } + + } + + private static class HostKeyFile extends ModifiableFileWatcher + implements Supplier<List<HostEntryPair>> { + + private List<HostEntryPair> entries = Collections.emptyList(); + + public HostKeyFile(Path path) { + super(path); + } + + @Override + public List<HostEntryPair> get() { + Path path = getPath(); + try { + if (checkReloadRequired()) { + if (!Files.exists(path)) { + // Has disappeared. + resetReloadAttributes(); + return Collections.emptyList(); + } + LockFile lock = new LockFile(path.toFile()); + if (lock.lock()) { + try { + entries = reload(getPath()); + } finally { + lock.unlock(); + } + } else { + LOG.warn(format(SshdText.get().knownHostsFileLockedRead, + path)); + } + } + } catch (IOException e) { + LOG.warn(format(SshdText.get().knownHostsFileReadFailed, path)); + } + return Collections.unmodifiableList(entries); + } + + private List<HostEntryPair> reload(Path path) throws IOException { + try { + List<KnownHostEntry> rawEntries = KnownHostEntry + .readKnownHostEntries(path); + updateReloadAttributes(); + if (rawEntries == null || rawEntries.isEmpty()) { + return Collections.emptyList(); + } + List<HostEntryPair> newEntries = new LinkedList<>(); + for (KnownHostEntry entry : rawEntries) { + AuthorizedKeyEntry keyPart = entry.getKeyEntry(); + if (keyPart == null) { + continue; + } + try { + PublicKey serverKey = keyPart.resolvePublicKey( + PublicKeyEntryResolver.IGNORING); + if (serverKey == null) { + LOG.warn(format( + SshdText.get().knownHostsUnknownKeyType, + getPath(), entry.getConfigLine())); + } else { + newEntries.add(new HostEntryPair(entry, serverKey)); + } + } catch (GeneralSecurityException e) { + LOG.warn(format(SshdText.get().knownHostsInvalidLine, + getPath(), entry.getConfigLine())); + } + } + return newEntries; + } catch (FileNotFoundException e) { + resetReloadAttributes(); + return Collections.emptyList(); + } + } + } + + // The stuff below is just a hack to avoid having to copy a lot of code from + // KnownHostsServerKeyVerifier + + private static class HostKeyHelper extends KnownHostsServerKeyVerifier { + + public HostKeyHelper() { + // These two arguments will never be used in any way. + super((c, r, s) -> false, new File(".").toPath()); //$NON-NLS-1$ + } + + @Override + protected KnownHostEntry prepareKnownHostEntry( + ClientSession clientSession, SocketAddress remoteAddress, + PublicKey serverKey) throws IOException { + // Make this method accessible + try { + return super.prepareKnownHostEntry(clientSession, remoteAddress, + serverKey); + } catch (Exception e) { + throw new IOException(e.getMessage(), e); + } + } + + @Override + protected String prepareModifiedServerKeyLine( + ClientSession clientSession, SocketAddress remoteAddress, + KnownHostEntry entry, String curLine, PublicKey expected, + PublicKey actual) throws IOException { + // Make this method accessible + try { + return super.prepareModifiedServerKeyLine(clientSession, + remoteAddress, entry, curLine, expected, actual); + } catch (Exception e) { + throw new IOException(e.getMessage(), e); + } + } + + @Override + protected Collection<SshdSocketAddress> resolveHostNetworkIdentities( + ClientSession clientSession, SocketAddress remoteAddress) { + // Make this method accessible + return super.resolveHostNetworkIdentities(clientSession, + remoteAddress); + } + } + +} diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/SshdText.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/SshdText.java new file mode 100644 index 0000000000..7f08f72f25 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/SshdText.java @@ -0,0 +1,50 @@ +package org.eclipse.jgit.internal.transport.sshd; + +import org.eclipse.jgit.nls.NLS; +import org.eclipse.jgit.nls.TranslationBundle; + +/** + * Externalized text messages for localization. + */ +public final class SshdText extends TranslationBundle { + + /** + * Get an instance of this translation bundle. + * + * @return an instance of this translation bundle + */ + public static SshdText get() { + return NLS.getBundleFor(SshdText.class); + } + + // @formatter:off + /***/ public String authenticationCanceled; + /***/ public String closeListenerFailed; + /***/ public String configInvalidPath; + /***/ public String ftpCloseFailed; + /***/ public String keyEncryptedMsg; + /***/ public String keyEncryptedPrompt; + /***/ public String keyLoadFailed; + /***/ public String knownHostsCouldNotUpdate; + /***/ public String knownHostsFileLockedRead; + /***/ public String knownHostsFileLockedUpdate; + /***/ public String knownHostsFileReadFailed; + /***/ public String knownHostsInvalidLine; + /***/ public String knownHostsInvalidPath; + /***/ public String knownHostsKeyFingerprints; + /***/ public String knownHostsModifiedKeyAcceptPrompt; + /***/ public String knownHostsModifiedKeyDenyMsg; + /***/ public String knownHostsModifiedKeyStorePrompt; + /***/ public String knownHostsModifiedKeyWarning; + /***/ public String knownHostsRevokedKeyMsg; + /***/ public String knownHostsUnknownKeyMsg; + /***/ public String knownHostsUnknownKeyPrompt; + /***/ public String knownHostsUnknownKeyType; + /***/ public String knownHostsUserAskCreationMsg; + /***/ public String knownHostsUserAskCreationPrompt; + /***/ public String sessionCloseFailed; + /***/ public String sshClosingDown; + /***/ public String sshCommandTimeout; + /***/ public String sshProcessStillRunning; + +} diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/IdentityPasswordProvider.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/IdentityPasswordProvider.java new file mode 100644 index 0000000000..5a0bd7fdc8 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/IdentityPasswordProvider.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.transport.sshd; + +import static java.text.MessageFormat.format; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CancellationException; + +import org.apache.sshd.common.config.keys.FilePasswordProvider; +import org.eclipse.jgit.internal.transport.sshd.SshdText; +import org.eclipse.jgit.transport.CredentialItem; +import org.eclipse.jgit.transport.CredentialsProvider; +import org.eclipse.jgit.transport.URIish; + +/** + * A {@link FilePasswordProvider} based on a {@link CredentialsProvider}. + * + * @since 5.2 + */ +public class IdentityPasswordProvider implements FilePasswordProvider { + + private CredentialsProvider provider; + + /** + * Creates a new {@link IdentityPasswordProvider} to get the passphrase for + * an encrypted identity. + * + * @param provider + * to use + */ + public IdentityPasswordProvider(CredentialsProvider provider) { + this.provider = provider; + } + + /** + * Creates a {@link URIish} from a given string. The + * {@link CredentialsProvider} uses uris as resource identifications. + * + * @param resourceKey + * to convert + * @return the uri + */ + protected URIish toUri(String resourceKey) { + try { + return new URIish(resourceKey); + } catch (URISyntaxException e) { + return new URIish().setPath(resourceKey); // Doesn't check!! + } + } + + @Override + public String getPassword(String resourceKey) throws IOException { + if (provider == null) { + return null; + } + URIish file = toUri(resourceKey); + List<CredentialItem> items = new ArrayList<>(2); + items.add(new CredentialItem.InformationalMessage( + format(SshdText.get().keyEncryptedMsg, resourceKey))); + CredentialItem.Password password = new CredentialItem.Password( + SshdText.get().keyEncryptedPrompt); + items.add(password); + try { + provider.get(file, items); + char[] pass = password.getValue(); + if (pass == null) { + throw new CancellationException( + SshdText.get().authenticationCanceled); + } + return new String(pass); + } finally { + password.clear(); + } + } + +} diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/JGitHostConfigEntry.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/JGitHostConfigEntry.java new file mode 100644 index 0000000000..6bffa2e3ee --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/JGitHostConfigEntry.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.transport.sshd; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.apache.sshd.client.config.hosts.HostConfigEntry; +import org.eclipse.jgit.annotations.NonNull; + +/** + * A {@link HostConfigEntry} that provides access to the multi-valued keys as + * lists of strings. The super class treats them as single strings containing + * comma-separated lists. + * + * @since 5.2 + */ +public class JGitHostConfigEntry extends HostConfigEntry { + + private Map<String, List<String>> multiValuedOptions; + + /** + * Sets the multi-valued options. + * + * @param options + * to set, may be {@code null} to set an empty map + */ + public void setMultiValuedOptions(Map<String, List<String>> options) { + multiValuedOptions = options; + } + + /** + * Retrieves all multi-valued options. + * + * @return an unmodifiable map + */ + @NonNull + public Map<String, List<String>> getMultiValuedOptions() { + Map<String, List<String>> options = multiValuedOptions; + if (options == null) { + return Collections.emptyMap(); + } + return Collections.unmodifiableMap(options); + } + +} diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/JGitKeyCache.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/JGitKeyCache.java new file mode 100644 index 0000000000..52325c6780 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/JGitKeyCache.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.transport.sshd; + +import java.nio.file.Path; +import java.security.KeyPair; +import java.security.PrivateKey; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Function; + +import javax.security.auth.DestroyFailedException; + +/** + * A simple {@link KeyCache}. JGit uses one such cache in its + * {@link SshdSessionFactory} to avoid loading keys multiple times. + * + * @since 5.2 + */ +public class JGitKeyCache implements KeyCache { + + private AtomicReference<Map<Path, KeyPair>> cache = new AtomicReference<>( + new ConcurrentHashMap<>()); + + @Override + public KeyPair get(Path path, + Function<? super Path, ? extends KeyPair> loader) { + return cache.get().computeIfAbsent(path, loader); + } + + @Override + public void close() { + Map<Path, KeyPair> map = cache.getAndSet(null); + if (map == null) { + return; + } + for (KeyPair k : map.values()) { + PrivateKey p = k.getPrivate(); + try { + p.destroy(); + } catch (DestroyFailedException e) { + // Ignore here. We did our best. + } + } + map.clear(); + } +} diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/JGitSshConfig.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/JGitSshConfig.java new file mode 100644 index 0000000000..9638374251 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/JGitSshConfig.java @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.transport.sshd; + +import static org.eclipse.jgit.internal.transport.ssh.OpenSshConfigFile.flag; +import static org.eclipse.jgit.internal.transport.ssh.OpenSshConfigFile.positive; + +import java.io.File; +import java.io.IOException; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.sshd.client.config.hosts.HostConfigEntry; +import org.apache.sshd.client.config.hosts.HostConfigEntryResolver; +import org.apache.sshd.common.util.net.SshdSocketAddress; +import org.eclipse.jgit.annotations.NonNull; +import org.eclipse.jgit.internal.transport.ssh.OpenSshConfigFile; +import org.eclipse.jgit.internal.transport.ssh.OpenSshConfigFile.HostEntry; +import org.eclipse.jgit.transport.SshConstants; + +/** + * A {@link HostConfigEntryResolver} adapted specifically for JGit. + * <p> + * We use our own config file parser and entry resolution since the default + * {@link org.apache.sshd.client.config.hosts.ConfigFileHostEntryResolver + * ConfigFileHostEntryResolver} has a number of problems: + * </p> + * <ul> + * <li>It does case-insensitive pattern matching. Matching in OpenSsh is + * case-sensitive! Compare also bug 531118.</li> + * <li>It only merges values from the global items (before the first "Host" + * line) into the host entries. Otherwise it selects the most specific match. + * OpenSsh processes <em>all</em> entries in the order they appear in the file + * and whenever one matches, it updates values as appropriate.</li> + * <li>We have to ensure that ~ replacement uses the same HOME directory as + * JGit. Compare bug bug 526175.</li> + * </ul> + * Therefore, this re-uses the parsing and caching from + * {@link OpenSshConfigFile}. + * + * @since 5.2 + */ +public class JGitSshConfig implements HostConfigEntryResolver { + + private OpenSshConfigFile configFile; + + /** + * Creates a new {@link OpenSshConfigFile} that will read the config from + * file {@code config} use the given file {@code home} as "home" directory. + * + * @param home + * user's home directory for the purpose of ~ replacement + * @param config + * file to load. + * @param localUserName + * user name of the current user on the local host OS + */ + public JGitSshConfig(@NonNull File home, @NonNull File config, + @NonNull String localUserName) { + configFile = new OpenSshConfigFile(home, config, localUserName); + } + + @Override + public HostConfigEntry resolveEffectiveHost(String host, int port, + String username) throws IOException { + HostEntry entry = configFile.lookup(host, port, username); + JGitHostConfigEntry config = new JGitHostConfigEntry(); + String hostName = entry.getValue(SshConstants.HOST_NAME); + if (hostName == null || hostName.isEmpty()) { + hostName = host; + } + config.setHostName(hostName); + config.setHost(SshdSocketAddress.isIPv6Address(hostName) ? "" : hostName); //$NON-NLS-1$ + String user = username != null && !username.isEmpty() ? username + : entry.getValue(SshConstants.USER); + if (user == null || user.isEmpty()) { + user = configFile.getLocalUserName(); + } + config.setUsername(user); + int p = port >= 0 ? port : positive(entry.getValue(SshConstants.PORT)); + config.setPort(p >= 0 ? p : SshConstants.SSH_DEFAULT_PORT); + config.setIdentities(entry.getValues(SshConstants.IDENTITY_FILE)); + config.setIdentitiesOnly( + flag(entry.getValue(SshConstants.IDENTITIES_ONLY))); + // Apache MINA conflates all keys, even multi-valued ones, in one map + // and puts multiple values separated by commas in one string. See + // the javadoc on HostConfigEntry. + Map<String, String> allOptions = new TreeMap<>( + String.CASE_INSENSITIVE_ORDER); + allOptions.putAll(entry.getOptions()); + // And what if a value contains a comma?? + entry.getMultiValuedOptions().entrySet().stream() + .forEach(e -> allOptions.put(e.getKey(), + String.join(",", e.getValue()))); //$NON-NLS-1$ + config.setProperties(allOptions); + // The following is an extension from JGitHostConfigEntry + config.setMultiValuedOptions(entry.getMultiValuedOptions()); + return config; + } + +} diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/KeyCache.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/KeyCache.java new file mode 100644 index 0000000000..d1865d9f73 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/KeyCache.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.transport.sshd; + +import java.nio.file.Path; +import java.security.KeyPair; +import java.util.function.Function; + +/** + * A cache for {@link KeyPair}s. + * + * @since 5.2 + */ +public interface KeyCache { + + /** + * Obtains a {@link KeyPair} from the cache. Implementations must be + * thread-safe. + * + * @param path + * of the key + * @param loader + * to load the key if it isn't present in the cache yet + * @return the {@link KeyPair}, or {@code null} if not present and could not + * be loaded + */ + KeyPair get(Path path, Function<? super Path, ? extends KeyPair> loader); + + /** + * Removes all {@link KeyPair} from this cache and destroys their private + * keys. This cache instance must not be used anymore thereafter. + */ + public void close(); +} diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SessionCloseListener.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SessionCloseListener.java new file mode 100644 index 0000000000..1707c7079d --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SessionCloseListener.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.transport.sshd; + +/** + * A {@code SessionCloseListener} is invoked when a {@link SshdSession} is + * closed. + */ +@FunctionalInterface +public interface SessionCloseListener { + + /** + * Invoked when a {@link SshdSession} has been closed. + * + * @param session + * that was closed. + */ + void sessionClosed(SshdSession session); +} diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSession.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSession.java new file mode 100644 index 0000000000..7d0e686a28 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSession.java @@ -0,0 +1,485 @@ +/* + * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.transport.sshd; + +import static java.text.MessageFormat.format; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InterruptedIOException; +import java.io.OutputStream; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Collection; +import java.util.EnumSet; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Supplier; + +import org.apache.sshd.client.SshClient; +import org.apache.sshd.client.channel.ChannelExec; +import org.apache.sshd.client.channel.ClientChannelEvent; +import org.apache.sshd.client.session.ClientSession; +import org.apache.sshd.client.subsystem.sftp.SftpClient; +import org.apache.sshd.client.subsystem.sftp.SftpClient.CloseableHandle; +import org.apache.sshd.client.subsystem.sftp.SftpClient.CopyMode; +import org.apache.sshd.client.subsystem.sftp.SftpClientFactory; +import org.apache.sshd.common.session.Session; +import org.apache.sshd.common.session.SessionListener; +import org.apache.sshd.common.subsystem.sftp.SftpException; +import org.eclipse.jgit.annotations.NonNull; +import org.eclipse.jgit.internal.transport.sshd.SshdText; +import org.eclipse.jgit.transport.FtpChannel; +import org.eclipse.jgit.transport.RemoteSession; +import org.eclipse.jgit.transport.URIish; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * An implementation of {@link RemoteSession}Â based on Apache MINA sshd. + * + * @since 5.2 + */ +public class SshdSession implements RemoteSession { + + private static final Logger LOG = LoggerFactory + .getLogger(SshdSession.class); + + private final CopyOnWriteArrayList<SessionCloseListener> listeners = new CopyOnWriteArrayList<>(); + + private final URIish uri; + + private SshClient client; + + private ClientSession session; + + SshdSession(URIish uri, Supplier<SshClient> clientFactory) { + this.uri = uri; + this.client = clientFactory.get(); + } + + void connect(Duration timeout) throws IOException { + if (!client.isStarted()) { + client.start(); + } + try { + String username = uri.getUser(); + String host = uri.getHost(); + int port = uri.getPort(); + long t = timeout.toMillis(); + if (t <= 0) { + session = client.connect(username, host, port).verify() + .getSession(); + } else { + session = client.connect(username, host, port) + .verify(timeout.toMillis()).getSession(); + } + session.addSessionListener(new SessionListener() { + + @Override + public void sessionClosed(Session s) { + notifyCloseListeners(); + } + }); + // Authentication timeout is by default 2 minutes. + session.auth().verify(session.getAuthTimeout()); + } catch (IOException e) { + disconnect(e); + throw e; + } + } + + /** + * Adds a {@link SessionCloseListener} to this session. Has no effect if the + * given {@code listener} is already registered with this session. + * + * @param listener + * to add + */ + public void addCloseListener(@NonNull SessionCloseListener listener) { + listeners.addIfAbsent(listener); + } + + /** + * Removes the given {@code listener}; has no effect if the listener is not + * currently registered with this session. + * + * @param listener + * to remove + */ + public void removeCloseListener(@NonNull SessionCloseListener listener) { + listeners.remove(listener); + } + + private void notifyCloseListeners() { + for (SessionCloseListener l : listeners) { + try { + l.sessionClosed(this); + } catch (RuntimeException e) { + LOG.warn(SshdText.get().closeListenerFailed, e); + } + } + } + + @Override + public Process exec(String commandName, int timeout) throws IOException { + @SuppressWarnings("resource") + ChannelExec exec = session.createExecChannel(commandName); + long timeoutMillis = TimeUnit.SECONDS.toMillis(timeout); + try { + if (timeout <= 0) { + exec.open().verify(); + } else { + long start = System.nanoTime(); + exec.open().verify(timeoutMillis); + timeoutMillis -= TimeUnit.NANOSECONDS + .toMillis(System.nanoTime() - start); + } + } catch (IOException e) { + exec.close(true); + throw e; + } catch (RuntimeException e) { + exec.close(true); + throw e; + } + if (timeout > 0 && timeoutMillis <= 0) { + // We have used up the whole timeout for opening the channel + exec.close(true); + throw new InterruptedIOException( + format(SshdText.get().sshCommandTimeout, commandName, + Integer.valueOf(timeout))); + } + return new SshdExecProcess(exec, commandName, timeoutMillis); + } + + /** + * Obtain an {@link FtpChannel} to perform SFTP operations in this + * {@link SshdSession}. + */ + @Override + @NonNull + public FtpChannel getFtpChannel() { + return new SshdFtpChannel(); + } + + @Override + public void disconnect() { + disconnect(null); + } + + private void disconnect(Throwable reason) { + try { + if (session != null) { + session.close(); + session = null; + } + } catch (IOException e) { + if (reason != null) { + reason.addSuppressed(e); + } else { + LOG.error(SshdText.get().sessionCloseFailed, e); + } + } finally { + client.stop(); + client = null; + } + } + + private static class SshdExecProcess extends Process { + + private final ChannelExec channel; + + private final long timeoutMillis; + + private final String commandName; + + public SshdExecProcess(ChannelExec channel, String commandName, + long timeoutMillis) { + this.channel = channel; + this.timeoutMillis = timeoutMillis > 0 ? timeoutMillis : -1L; + this.commandName = commandName; + } + + @Override + public OutputStream getOutputStream() { + return channel.getInvertedIn(); + } + + @Override + public InputStream getInputStream() { + return channel.getInvertedOut(); + } + + @Override + public InputStream getErrorStream() { + return channel.getInvertedErr(); + } + + @Override + public int waitFor() throws InterruptedException { + if (waitFor(timeoutMillis, TimeUnit.MILLISECONDS)) { + return exitValue(); + } + return -1; + } + + @Override + public boolean waitFor(long timeout, TimeUnit unit) + throws InterruptedException { + long millis = timeout >= 0 ? unit.toMillis(timeout) : -1L; + return channel + .waitFor(EnumSet.of(ClientChannelEvent.CLOSED), millis) + .contains(ClientChannelEvent.CLOSED); + } + + @Override + public int exitValue() { + Integer exitCode = channel.getExitStatus(); + if (exitCode == null) { + throw new IllegalThreadStateException( + format(SshdText.get().sshProcessStillRunning, + commandName)); + } + return exitCode.intValue(); + } + + @Override + public void destroy() { + if (channel.isOpen()) { + channel.close(true); + } + } + } + + /** + * Helper interface like {@link Supplier}, but possibly raising an + * {@link IOException}. + * + * @param <T> + * return type + */ + @FunctionalInterface + private interface FtpOperation<T> { + + T call() throws IOException; + + } + + private class SshdFtpChannel implements FtpChannel { + + private SftpClient ftp; + + /** Current working directory. */ + private String cwd = ""; //$NON-NLS-1$ + + @Override + public void connect(int timeout, TimeUnit unit) throws IOException { + if (timeout <= 0) { + session.getProperties().put( + SftpClient.SFTP_CHANNEL_OPEN_TIMEOUT, + Long.valueOf(Long.MAX_VALUE)); + } else { + session.getProperties().put( + SftpClient.SFTP_CHANNEL_OPEN_TIMEOUT, + Long.valueOf(unit.toMillis(timeout))); + } + ftp = SftpClientFactory.instance().createSftpClient(session); + try { + cd(cwd); + } catch (IOException e) { + ftp.close(); + } + } + + @Override + public void disconnect() { + try { + ftp.close(); + } catch (IOException e) { + LOG.error(SshdText.get().ftpCloseFailed, e); + } + } + + @Override + public boolean isConnected() { + return session.isAuthenticated() && ftp.isOpen(); + } + + private String absolute(String path) { + if (path.isEmpty()) { + return cwd; + } + // Note: there is no path injection vulnerability here. If + // path has too many ".." components, we rely on the server + // catching it and returning an error. + if (path.charAt(0) != '/') { + if (cwd.charAt(cwd.length() - 1) == '/') { + return cwd + path; + } else { + return cwd + '/' + path; + } + } + return path; + } + + private <T> T map(FtpOperation<T> op) throws IOException { + try { + return op.call(); + } catch (IOException e) { + if (e instanceof SftpException) { + throw new FtpChannel.FtpException(e.getLocalizedMessage(), + ((SftpException) e).getStatus(), e); + } + throw e; + } + } + + @Override + public void cd(String path) throws IOException { + cwd = map(() -> ftp.canonicalPath(absolute(path))); + if (cwd.isEmpty()) { + cwd += '/'; + } + } + + @Override + public String pwd() throws IOException { + return cwd; + } + + @Override + public Collection<DirEntry> ls(String path) throws IOException { + return map(() -> { + List<DirEntry> result = new ArrayList<>(); + try (CloseableHandle handle = ftp.openDir(absolute(path))) { + AtomicReference<Boolean> atEnd = new AtomicReference<>( + Boolean.FALSE); + while (!atEnd.get().booleanValue()) { + List<SftpClient.DirEntry> chunk = ftp.readDir(handle, + atEnd); + if (chunk == null) { + break; + } + for (SftpClient.DirEntry remote : chunk) { + result.add(new DirEntry() { + + @Override + public String getFilename() { + return remote.getFilename(); + } + + @Override + public long getModifiedTime() { + return remote.getAttributes() + .getModifyTime().toMillis(); + } + + @Override + public boolean isDirectory() { + return remote.getAttributes().isDirectory(); + } + + }); + } + } + } + return result; + }); + } + + @Override + public void rmdir(String path) throws IOException { + map(() -> { + ftp.rmdir(absolute(path)); + return null; + }); + + } + + @Override + public void mkdir(String path) throws IOException { + map(() -> { + ftp.mkdir(absolute(path)); + return null; + }); + } + + @Override + public InputStream get(String path) throws IOException { + return map(() -> ftp.read(absolute(path))); + } + + @Override + public OutputStream put(String path) throws IOException { + return map(() -> ftp.write(absolute(path))); + } + + @Override + public void rm(String path) throws IOException { + map(() -> { + ftp.remove(absolute(path)); + return null; + }); + } + + @Override + public void rename(String from, String to) throws IOException { + map(() -> { + String src = absolute(from); + String dest = absolute(to); + try { + ftp.rename(src, dest, CopyMode.Atomic, CopyMode.Overwrite); + } catch (UnsupportedOperationException e) { + // Older server cannot do POSIX rename... + if (!src.equals(dest)) { + delete(dest); + ftp.rename(src, dest); + } + } + return null; + }); + } + } +} diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSessionFactory.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSessionFactory.java new file mode 100644 index 0000000000..862b5590e9 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSessionFactory.java @@ -0,0 +1,436 @@ +/* + * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.transport.sshd; + +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; + +import org.apache.sshd.client.ClientBuilder; +import org.apache.sshd.client.SshClient; +import org.apache.sshd.client.auth.UserAuth; +import org.apache.sshd.client.auth.keyboard.UserAuthKeyboardInteractiveFactory; +import org.apache.sshd.client.auth.password.UserAuthPasswordFactory; +import org.apache.sshd.client.config.hosts.HostConfigEntryResolver; +import org.apache.sshd.client.keyverifier.ServerKeyVerifier; +import org.apache.sshd.common.NamedFactory; +import org.apache.sshd.common.compression.BuiltinCompressions; +import org.apache.sshd.common.config.keys.FilePasswordProvider; +import org.apache.sshd.common.keyprovider.FileKeyPairProvider; +import org.apache.sshd.common.keyprovider.KeyPairProvider; +import org.eclipse.jgit.annotations.NonNull; +import org.eclipse.jgit.errors.TransportException; +import org.eclipse.jgit.internal.transport.sshd.CachingKeyPairProvider; +import org.eclipse.jgit.internal.transport.sshd.JGitPublicKeyAuthFactory; +import org.eclipse.jgit.internal.transport.sshd.JGitSshClient; +import org.eclipse.jgit.internal.transport.sshd.JGitUserInteraction; +import org.eclipse.jgit.internal.transport.sshd.OpenSshServerKeyVerifier; +import org.eclipse.jgit.internal.transport.sshd.SshdText; +import org.eclipse.jgit.transport.CredentialsProvider; +import org.eclipse.jgit.transport.SshConstants; +import org.eclipse.jgit.transport.SshSessionFactory; +import org.eclipse.jgit.transport.URIish; +import org.eclipse.jgit.util.FS; + +/** + * A {@link SshSessionFactory} that uses Apache MINA sshd. + * + * @since 5.2 + */ +public class SshdSessionFactory extends SshSessionFactory implements Closeable { + + private final AtomicBoolean closing = new AtomicBoolean(); + + private final Set<SshdSession> sessions = new HashSet<>(); + + private final Map<Tuple, HostConfigEntryResolver> defaultHostConfigEntryResolver = new ConcurrentHashMap<>(); + + private final Map<Tuple, ServerKeyVerifier> defaultServerKeyVerifier = new ConcurrentHashMap<>(); + + private final Map<Tuple, FileKeyPairProvider> defaultKeys = new ConcurrentHashMap<>(); + + private final KeyCache keyCache; + + private File sshDirectory; + + private File homeDirectory; + + /** + * Creates a new {@link SshdSessionFactory} without {@link KeyCache}. + */ + public SshdSessionFactory() { + this(null); + } + + /** + * Creates a new {@link SshdSessionFactory} using the given + * {@link KeyCache}. The {@code keyCache} is used for all sessions created + * through this session factory; cached keys are destroyed when the session + * factory is {@link #close() closed}. + * <p> + * Caching ssh keys in memory for an extended period of time is generally + * considered bad practice, but there may be circumstances where using a + * {@link KeyCache} is still the right choice, for instance to avoid that a + * user gets prompted several times for the same password for the same key. + * In general, however, it is preferable <em>not</em> to use a key cache but + * to use a {@link #createFilePasswordProvider(CredentialsProvider) + * FilePasswordProvider} that has access to some secure storage and can save + * and retrieve passwords from there without user interaction. Another + * approach is to use an ssh agent. + * </p> + * <p> + * Note that the underlying ssh library (Apache MINA sshd) may or may not + * keep ssh keys in memory for unspecified periods of time irrespective of + * the use of a {@link KeyCache}. + * </p> + * + * @param keyCache + * {@link KeyCache} to use for caching ssh keys, or {@code null} + * to not use a key cache + */ + public SshdSessionFactory(KeyCache keyCache) { + super(); + this.keyCache = keyCache; + } + + /** A simple general map key. */ + private static final class Tuple { + private Object[] objects; + + public Tuple(Object... objects) { + this.objects = objects; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj != null && obj.getClass() == Tuple.class) { + Tuple other = (Tuple) obj; + return Arrays.equals(objects, other.objects); + } + return false; + } + + @Override + public int hashCode() { + return Arrays.hashCode(objects); + } + } + + // We can't really use a single client. Clients need to be stopped + // properly, and we don't really know when to do that. Instead we use + // a dedicated SshClient instance per session. We need a bit of caching to + // avoid re-loading the ssh config and keys repeatedly. + + @Override + public SshdSession getSession(URIish uri, + CredentialsProvider credentialsProvider, FS fs, int tms) + throws TransportException { + SshdSession session = null; + try { + session = new SshdSession(uri, () -> { + File home = getHomeDirectory(); + if (home == null) { + // Always use the detected filesystem for the user home! + // It makes no sense to have different "user home" + // directories depending on what file system a repository + // is. + home = FS.DETECTED.userHome(); + } + File sshDir = getSshDirectory(); + if (sshDir == null) { + sshDir = new File(home, SshConstants.SSH_DIR); + } + HostConfigEntryResolver configFile = getHostConfigEntryResolver( + home, sshDir); + KeyPairProvider defaultKeysProvider = getDefaultKeysProvider( + sshDir); + SshClient client = ClientBuilder.builder() + .factory(JGitSshClient::new) + .filePasswordProvider( + createFilePasswordProvider(credentialsProvider)) + .hostConfigEntryResolver(configFile) + .serverKeyVerifier(getServerKeyVerifier(home, sshDir)) + .compressionFactories( + new ArrayList<>(BuiltinCompressions.VALUES)) + .build(); + client.setUserInteraction( + new JGitUserInteraction(credentialsProvider)); + client.setUserAuthFactories(getUserAuthFactories()); + client.setKeyPairProvider(defaultKeysProvider); + // JGit-specific things: + JGitSshClient jgitClient = (JGitSshClient) client; + jgitClient.setKeyCache(getKeyCache()); + jgitClient.setCredentialsProvider(credentialsProvider); + // Other things? + return client; + }); + session.addCloseListener(s -> unregister(s)); + register(session); + session.connect(Duration.ofMillis(tms)); + return session; + } catch (Exception e) { + unregister(session); + throw new TransportException(uri, e.getMessage(), e); + } + } + + @Override + public void close() { + closing.set(true); + boolean cleanKeys = false; + synchronized (this) { + cleanKeys = sessions.isEmpty(); + } + if (cleanKeys) { + KeyCache cache = getKeyCache(); + if (cache != null) { + cache.close(); + } + } + } + + private void register(SshdSession newSession) throws IOException { + if (newSession == null) { + return; + } + if (closing.get()) { + throw new IOException(SshdText.get().sshClosingDown); + } + synchronized (this) { + sessions.add(newSession); + } + } + + private void unregister(SshdSession oldSession) { + boolean cleanKeys = false; + synchronized (this) { + sessions.remove(oldSession); + cleanKeys = closing.get() && sessions.isEmpty(); + } + if (cleanKeys) { + KeyCache cache = getKeyCache(); + if (cache != null) { + cache.close(); + } + } + } + + /** + * Set a global directory to use as the user's home directory + * + * @param homeDir + * to use + */ + public void setHomeDirectory(@NonNull File homeDir) { + if (homeDir.isAbsolute()) { + homeDirectory = homeDir; + } else { + homeDirectory = homeDir.getAbsoluteFile(); + } + } + + /** + * Retrieves the global user home directory + * + * @return the directory, or {@code null} if not set + */ + public File getHomeDirectory() { + return homeDirectory; + } + + /** + * Set a global directory to use as the .ssh directory + * + * @param sshDir + * to use + */ + public void setSshDirectory(@NonNull File sshDir) { + if (sshDir.isAbsolute()) { + sshDirectory = sshDir; + } else { + sshDirectory = sshDir.getAbsoluteFile(); + } + } + + /** + * Retrieves the global .ssh directory + * + * @return the directory, or {@code null} if not set + */ + public File getSshDirectory() { + return sshDirectory; + } + + /** + * Obtain a {@link HostConfigEntryResolver} to read the ssh config file and + * to determine host entries for connections. + * + * @param homeDir + * home directory to use for ~ replacement + * @param sshDir + * to use for looking for the config file + * @return the resolver + */ + @NonNull + protected HostConfigEntryResolver getHostConfigEntryResolver( + @NonNull File homeDir, @NonNull File sshDir) { + return defaultHostConfigEntryResolver.computeIfAbsent( + new Tuple(homeDir, sshDir), + t -> new JGitSshConfig(homeDir, + new File(sshDir, SshConstants.CONFIG), + getLocalUserName())); + } + + /** + * Obtain a {@link ServerKeyVerifier} to read known_hosts files and to + * verify server host keys. The default implementation returns a + * {@link ServerKeyVerifier} that recognizes the two openssh standard files + * {@code ~/.ssh/known_hosts} and {@code ~/.ssh/known_hosts2} as well as any + * files configured via the {@code UserKnownHostsFile} option in the ssh + * config file. + * + * @param homeDir + * home directory to use for ~ replacement + * @param sshDir + * representing ~/.ssh/ + * @return the resolver + */ + @NonNull + protected ServerKeyVerifier getServerKeyVerifier(@NonNull File homeDir, + @NonNull File sshDir) { + return defaultServerKeyVerifier.computeIfAbsent( + new Tuple(homeDir, sshDir), + t -> new OpenSshServerKeyVerifier(true, + Arrays.asList( + new File(sshDir, SshConstants.KNOWN_HOSTS), + new File(sshDir, + SshConstants.KNOWN_HOSTS + '2')))); + } + + /** + * Determines a {@link KeyPairProvider} to use to load the default keys. + * + * @param sshDir + * to look in for keys + * @return the {@link KeyPairProvider} + */ + @NonNull + protected KeyPairProvider getDefaultKeysProvider(@NonNull File sshDir) { + return defaultKeys.computeIfAbsent(new Tuple(sshDir), + t -> new CachingKeyPairProvider(getDefaultIdentities(sshDir), + getKeyCache())); + } + + /** + * Gets a list of default identities, i.e., private key files that shall + * always be tried for public key authentication. Typically those are + * ~/.ssh/id_dsa, ~/.ssh/id_rsa, and so on. The default implementation + * returns the files defined in {@link SshConstants#DEFAULT_IDENTITIES}. + * + * @param sshDir + * the directory that represents ~/.ssh/ + * @return a possibly empty list of paths containing default identities + * (private keys) + */ + @NonNull + protected List<Path> getDefaultIdentities(@NonNull File sshDir) { + return Arrays + .asList(SshConstants.DEFAULT_IDENTITIES).stream() + .map(s -> new File(sshDir, s).toPath()).filter(Files::exists) + .collect(Collectors.toList()); + } + + /** + * Obtains the {@link KeyCache} to use to cache loaded keys. + * + * @return the {@link KeyCache}, or {@code null} if none. + */ + protected final KeyCache getKeyCache() { + return keyCache; + } + + /** + * Creates a {@link FilePasswordProvider} for a new session. + * + * @param provider + * the {@link CredentialsProvider} to delegate for for user + * interactions + * @return a new {@link FilePasswordProvider} + */ + @NonNull + protected FilePasswordProvider createFilePasswordProvider( + CredentialsProvider provider) { + return new IdentityPasswordProvider(provider); + } + + /** + * Gets the user authentication mechanisms (or rather, factories for them). + * By default this returns public-key, keyboard-interactive, and password, + * in that order. (I.e., we don't do gssapi-with-mic or hostbased (yet)). + * + * @return the non-empty list of factories. + */ + @NonNull + protected List<NamedFactory<UserAuth>> getUserAuthFactories() { + return Collections.unmodifiableList( + Arrays.asList(JGitPublicKeyAuthFactory.INSTANCE, + UserAuthKeyboardInteractiveFactory.INSTANCE, + UserAuthPasswordFactory.INSTANCE)); + } +} diff --git a/org.eclipse.jgit.test/.classpath b/org.eclipse.jgit.test/.classpath index 3a0a10e33c..7cc18cca34 100644 --- a/org.eclipse.jgit.test/.classpath +++ b/org.eclipse.jgit.test/.classpath @@ -16,6 +16,7 @@ <attribute name="test" value="true"/> </attributes> </classpathentry> + <classpathentry kind="src" path="resources"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> <classpathentry kind="output" path="bin"/> diff --git a/org.eclipse.jgit.test/BUILD b/org.eclipse.jgit.test/BUILD index 2082e7eac0..7165651496 100644 --- a/org.eclipse.jgit.test/BUILD +++ b/org.eclipse.jgit.test/BUILD @@ -6,7 +6,10 @@ load( PKG = "tst/org/eclipse/jgit/" -HELPERS = glob(["src/**/*.java"]) + [PKG + c for c in [ +HELPERS = glob( + ["src/**/*.java"], + exclude = ["src/org/eclipse/jgit/transport/ssh/*.java"] + ) + [PKG + c for c in [ "api/AbstractRemoteCommandTest.java", "diff/AbstractDiffTestCase.java", "internal/storage/file/GcTestCase.java", @@ -20,8 +23,6 @@ HELPERS = glob(["src/**/*.java"]) + [PKG + c for c in [ "revwalk/RevWalkTestCase.java", "transport/ObjectIdMatcher.java", "transport/SpiTransport.java", - "transport/ssh/SshTestBase.java", - "transport/ssh/SshTestHarness.java", "treewalk/FileTreeIteratorWithTimeControl.java", "treewalk/filter/AlwaysCloneTreeFilter.java", "test/resources/SampleDataRepositoryTestCase.java", @@ -34,6 +35,8 @@ DATA = [ PKG + "lib/sorttest.gitindex.dat", ] +RESOURCES = glob(["resources/**"]) + tests(glob( ["tst/**/*.java"], exclude = HELPERS + DATA, @@ -54,6 +57,25 @@ java_library( ], ) +java_library( + name = "sshd-helpers", + testonly = 1, + srcs = glob(["src/org/eclipse/jgit/transport/ssh/*.java"]), + resource_strip_prefix = "org.eclipse.jgit.test/resources", + resources = RESOURCES, + deps = [ + "//lib:junit", + "//org.eclipse.jgit:jgit", + "//org.eclipse.jgit.junit:junit", + "//lib:jsch", + "//lib:sshd-core", + "//lib:sshd-sftp", + ], + visibility = [ + "//org.eclipse.jgit.ssh.apache.test:__pkg__", + ], +) + java_import( name = "tst_rsrc", jars = [":tst_rsrc_jar"], diff --git a/org.eclipse.jgit.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.test/META-INF/MANIFEST.MF index 6514277ac5..94681178e7 100644 --- a/org.eclipse.jgit.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.test/META-INF/MANIFEST.MF @@ -66,3 +66,4 @@ Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)", org.slf4j;version="[1.7.0,2.0.0)" Require-Bundle: org.hamcrest.core;bundle-version="[1.1.0,2.0.0)", org.hamcrest.library;bundle-version="[1.1.0,2.0.0)" +Export-Package: org.eclipse.jgit.transport.ssh;version="5.2.0";x-friends:="org.eclipse.jgit.ssh.apache.test" diff --git a/org.eclipse.jgit.test/build.properties b/org.eclipse.jgit.test/build.properties index 7dc26c0b0d..78c8f55f3a 100644 --- a/org.eclipse.jgit.test/build.properties +++ b/org.eclipse.jgit.test/build.properties @@ -1,7 +1,8 @@ source.. = tst/,\ tst-rsrc/,\ exttst/,\ - src/ + src/,\ + resources/ bin.includes = META-INF/,\ .,\ plugin.properties,\ diff --git a/org.eclipse.jgit.test/pom.xml b/org.eclipse.jgit.test/pom.xml index 3d5df9a68a..4099c89c09 100644 --- a/org.eclipse.jgit.test/pom.xml +++ b/org.eclipse.jgit.test/pom.xml @@ -154,6 +154,18 @@ </testResource> </testResources> + <resources> + <resource> + <directory>.</directory> + <includes> + <include>plugin.properties</include> + </includes> + </resource> + <resource> + <directory>resources/</directory> + </resource> + </resources> + <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_dsa b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_dsa index f097516df2..f097516df2 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_dsa +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_dsa diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_dsa.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_dsa.pub index 676685332e..676685332e 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_dsa.pub +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_dsa.pub diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_dsa_testpass b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_dsa_testpass index 375d38fe43..375d38fe43 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_dsa_testpass +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_dsa_testpass diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_dsa_testpass.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_dsa_testpass.pub index 676685332e..676685332e 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_dsa_testpass.pub +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_dsa_testpass.pub diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_256 b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_256 index 8a4c864afa..8a4c864afa 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_256 +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_256 diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_256.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_256.pub index 43540ec0ec..43540ec0ec 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_256.pub +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_256.pub diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_256_testpass b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_256_testpass index b767c8e99a..b767c8e99a 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_256_testpass +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_256_testpass diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_256_testpass.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_256_testpass.pub index 43540ec0ec..43540ec0ec 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_256_testpass.pub +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_256_testpass.pub diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_384 b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_384 index dc2ac86508..dc2ac86508 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_384 +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_384 diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_384.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_384.pub index 3e813a5e48..3e813a5e48 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_384.pub +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_384.pub diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_384_testpass b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_384_testpass index 06032d049f..06032d049f 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_384_testpass +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_384_testpass diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_384_testpass.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_384_testpass.pub index 3e813a5e48..3e813a5e48 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_384_testpass.pub +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_384_testpass.pub diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_521 b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_521 index c28151e5ab..c28151e5ab 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_521 +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_521 diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_521.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_521.pub index 9bac1e80f0..9bac1e80f0 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_521.pub +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_521.pub diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_521_testpass b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_521_testpass index c1c1bbaced..c1c1bbaced 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_521_testpass +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_521_testpass diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_521_testpass.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_521_testpass.pub index 9bac1e80f0..9bac1e80f0 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ecdsa_521_testpass.pub +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ecdsa_521_testpass.pub diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ed25519 b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519 index 02afa54788..02afa54788 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ed25519 +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519 diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ed25519.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519.pub index 7857db5602..7857db5602 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ed25519.pub +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519.pub diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ed25519_testpass b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519_testpass index 7ad4a77056..7ad4a77056 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ed25519_testpass +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519_testpass diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ed25519_testpass.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519_testpass.pub index 7857db5602..7857db5602 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_ed25519_testpass.pub +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_ed25519_testpass.pub diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_1024 b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_1024 index 0b403674fa..0b403674fa 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_1024 +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_1024 diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_1024.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_1024.pub index 4aded97ab6..4aded97ab6 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_1024.pub +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_1024.pub diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_1024_testpass b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_1024_testpass index 0b66dc0aa9..0b66dc0aa9 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_1024_testpass +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_1024_testpass diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_1024_testpass.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_1024_testpass.pub index 4aded97ab6..4aded97ab6 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_1024_testpass.pub +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_1024_testpass.pub diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_2048 b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_2048 index a2d7d62310..a2d7d62310 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_2048 +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_2048 diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_2048.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_2048.pub index b787e36483..b787e36483 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_2048.pub +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_2048.pub diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_2048_testpass b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_2048_testpass index 7b3a3f4e58..7b3a3f4e58 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_2048_testpass +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_2048_testpass diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_2048_testpass.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_2048_testpass.pub index b787e36483..b787e36483 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_2048_testpass.pub +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_2048_testpass.pub diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_3072 b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_3072 index 10d622c905..10d622c905 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_3072 +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_3072 diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_3072.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_3072.pub index 686d3b06b1..686d3b06b1 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_3072.pub +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_3072.pub diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_3072_testpass b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_3072_testpass index 353a24c206..353a24c206 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_3072_testpass +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_3072_testpass diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_3072_testpass.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_3072_testpass.pub index 686d3b06b1..686d3b06b1 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_3072_testpass.pub +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_3072_testpass.pub diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_4096 b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_4096 index 1a10b388e6..1a10b388e6 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_4096 +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_4096 diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_4096.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_4096.pub index 3c3c16feeb..3c3c16feeb 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_4096.pub +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_4096.pub diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_4096_testpass b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_4096_testpass index 96e29fc15c..96e29fc15c 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_4096_testpass +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_4096_testpass diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_4096_testpass.pub b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_4096_testpass.pub index 3c3c16feeb..3c3c16feeb 100644 --- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/transport/ssh/id_rsa_4096_testpass.pub +++ b/org.eclipse.jgit.test/resources/org/eclipse/jgit/transport/ssh/id_rsa_4096_testpass.pub diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ssh/SshTestBase.java b/org.eclipse.jgit.test/src/org/eclipse/jgit/transport/ssh/SshTestBase.java index 4afe6e2422..2f623e3305 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ssh/SshTestBase.java +++ b/org.eclipse.jgit.test/src/org/eclipse/jgit/transport/ssh/SshTestBase.java @@ -174,8 +174,14 @@ public abstract class SshTestBase extends SshTestHarness { @Test public void testSshWithConfigEncryptedUnusedKeyInConfigFirst() throws Exception { - // Test cannot pass with JSch; it handles only one IdentityFile - assumeTrue(!(getSessionFactory() instanceof JschConfigSessionFactory)); + // Test cannot pass with JSch; it handles only one IdentityFile. + // assumeTrue(!(getSessionFactory() instanceof + // JschConfigSessionFactory)); gives in bazel a failure with "Never + // found parameters that satisfied method assumptions." + // In maven it's fine!? + if (getSessionFactory() instanceof JschConfigSessionFactory) { + return; + } // Copy the encrypted test key from the bundle. File encryptedKey = new File(sshDir, "id_dsa_test_key"); copyTestResource("id_dsa_testpass", encryptedKey); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ssh/SshTestHarness.java b/org.eclipse.jgit.test/src/org/eclipse/jgit/transport/ssh/SshTestHarness.java index 347c72b3d7..347c72b3d7 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ssh/SshTestHarness.java +++ b/org.eclipse.jgit.test/src/org/eclipse/jgit/transport/ssh/SshTestHarness.java diff --git a/org.eclipse.jgit.test/tests.bzl b/org.eclipse.jgit.test/tests.bzl index b9ad8b2126..48c3bc36c8 100644 --- a/org.eclipse.jgit.test/tests.bzl +++ b/org.eclipse.jgit.test/tests.bzl @@ -47,6 +47,7 @@ def tests(tests): "//lib:jzlib", "//lib:sshd-core", "//lib:sshd-sftp", + ":sshd-helpers", ] heap_size = "-Xmx256m" if src.endswith("HugeCommitMessageTest.java"): diff --git a/org.eclipse.jgit/META-INF/MANIFEST.MF b/org.eclipse.jgit/META-INF/MANIFEST.MF index aec1dd890e..6fbb0e548e 100644 --- a/org.eclipse.jgit/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit/META-INF/MANIFEST.MF @@ -75,15 +75,19 @@ Export-Package: org.eclipse.jgit.annotations;version="5.2.0", org.eclipse.jgit.http.server, org.eclipse.jgit.lfs, org.eclipse.jgit.pgm, - org.eclipse.jgit.pgm.test", + org.eclipse.jgit.pgm.test, + org.eclipse.jgit.ssh.apache", org.eclipse.jgit.internal.storage.io;version="5.2.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm", org.eclipse.jgit.internal.storage.pack;version="5.2.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm", org.eclipse.jgit.internal.storage.reftable;version="5.2.0"; - x-friends:="org.eclipse.jgit.http.test,org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm", + x-friends:="org.eclipse.jgit.http.test, + org.eclipse.jgit.junit, + org.eclipse.jgit.test, + org.eclipse.jgit.pgm", org.eclipse.jgit.internal.storage.reftree;version="5.2.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm", org.eclipse.jgit.internal.submodule;version="5.2.0";x-internal:=true, org.eclipse.jgit.internal.transport.parser;version="5.2.0";x-friends:="org.eclipse.jgit.test", - org.eclipse.jgit.internal.transport.ssh;version="5.2.0";x-internal:=true, + org.eclipse.jgit.internal.transport.ssh;version="5.2.0";x-friends:="org.eclipse.jgit.ssh.apache", org.eclipse.jgit.lib;version="5.2.0"; uses:="org.eclipse.jgit.revwalk, org.eclipse.jgit.treewalk.filter, @@ -934,6 +934,7 @@ <module>org.eclipse.jgit.ui</module> <module>org.eclipse.jgit.http.apache</module> <module>org.eclipse.jgit.http.server</module> + <module>org.eclipse.jgit.ssh.apache</module> <module>org.eclipse.jgit.pgm</module> <module>org.eclipse.jgit.lfs</module> <module>org.eclipse.jgit.lfs.server</module> @@ -946,6 +947,7 @@ <module>org.eclipse.jgit.pgm.test</module> <module>org.eclipse.jgit.lfs.test</module> <module>org.eclipse.jgit.lfs.server.test</module> + <module>org.eclipse.jgit.ssh.apache.test</module> </modules> </project> |