pax_global_header00006660000000000000000000000064147757734730014542gustar00rootroot0000000000000052 comment=b502a82fb1175491d88c1c00d63e8607d97a9dd9 voms-api-java-3.3.5/000077500000000000000000000000001477577347300142245ustar00rootroot00000000000000voms-api-java-3.3.5/.github/000077500000000000000000000000001477577347300155645ustar00rootroot00000000000000voms-api-java-3.3.5/.github/workflows/000077500000000000000000000000001477577347300176215ustar00rootroot00000000000000voms-api-java-3.3.5/.github/workflows/build-rpm.yaml000066400000000000000000000107511477577347300224040ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare # # SPDX-License-Identifier: Apache-2.0 name: Build RPM on: push env: NIGHTLY_BRANCH: develop jobs: build-rpm: if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name strategy: fail-fast: false matrix: os: [almalinux] version: [8, 9] outputs: repo: ${{ steps.info.outputs.repo }} version_pom: ${{ steps.info.outputs.version_pom }} runs-on: ubuntu-latest container: '${{ matrix.os }}:${{ matrix.version }}' steps: - name: Install dependencies run: | dnf upgrade -y [[ "${{ matrix.version }}" = 8 ]] && dnf module enable -y maven:3.8/common dnf install -y git rpmdevtools rpmlint maven-openjdk17 - name: Setup build tree run: | echo "%_topdir $(pwd)/rpmbuild" >> ~/.rpmmacros rpmdev-setuptree - uses: actions/checkout@v4 with: path: 'rpmbuild/BUILD' fetch-depth: 0 - name: Calculate version and repo id: info run: | cd rpmbuild/BUILD VERSION_POM=$(mvn org.apache.maven.plugins:maven-help-plugin:evaluate -Dexpression=project.version -q -DforceStdout) # Maven uses -SNAPSHOT for pre-releases, change the - to ~ in the RPM VERSION_RPM=$(echo ${VERSION_POM} | sed 's/-/~/') if [[ ${{ github.ref_type }} = 'tag' ]]; then # In case is a tag, get the tag value GITHUB_REF=${{ github.ref }} TAG_NAME=${GITHUB_REF#refs/tags/} # Check if the tag matches v.. if [[ ${TAG_NAME} =~ ^v([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then REPO='stable' VERSION="${BASH_REMATCH[1]}" if [[ ${VERSION} != ${VERSION_POM} ]]; then echo "Version mismatch between tag (${VERSION}) and POM file (${VERSION_POM})" exit 1 fi fi elif [[ ${GITHUB_REF} = "refs/heads/${NIGHTLY_BRANCH}" ]]; then # Check if the version in POM file matches ..-SNAPSHOT if [[ ${VERSION_POM} =~ ^[0-9]+\.[0-9]+\.[0-9]+-SNAPSHOT$ ]]; then REPO='nightly' fi fi echo "REPO=${REPO}" >> "${GITHUB_ENV}" echo "repo=${REPO}" >> "${GITHUB_OUTPUT}" echo "VERSION_POM=${VERSION_POM}" >> "${GITHUB_ENV}" echo "version_pom=${VERSION_POM}" >> "${GITHUB_OUTPUT}" echo "VERSION_RPM=${VERSION_RPM}" >> "${GITHUB_ENV}" echo "Version POM: ${VERSION_POM}" echo "Version RPM: ${VERSION_RPM}" echo "Repo: ${REPO:-none}" - name: Build RPM run: | cp rpmbuild/BUILD/voms-api-java.spec rpmbuild/SPECS/voms-api-java.spec rpmlint rpmbuild/SPECS/voms-api-java.spec rpmbuild --define "base_version ${VERSION_RPM}" --define "version_pom ${VERSION_POM}" -ba rpmbuild/SPECS/voms-api-java.spec - uses: actions/upload-artifact@v4 with: name: build-rpm-${{ matrix.os }}-${{ matrix.version }} path: | rpmbuild/RPMS/noarch/*.rpm - name: Upload release to repo if: env.REPO != '' run: | for file in rpmbuild/RPMS/noarch/*.rpm; do curl --fail --user "${{ vars.NEXUS_USERNAME }}:${{ secrets.NEXUS_PASSWORD }}" --upload-file "${file}" https://repo.cloud.cnaf.infn.it/repository/voms-rpm-${REPO}/redhat${{ matrix.version }}/ done create-release: needs: build-rpm runs-on: ubuntu-latest env: GH_TOKEN: ${{ github.token }} VERSION_POM: ${{ needs.build-rpm.outputs.version_pom }} if: needs.build-rpm.outputs.repo == 'stable' steps: - name: Check out repository code uses: actions/checkout@v4 - uses: actions/download-artifact@v4 - name: Create release run: | # Get from the changelog file only the part related to the tagged release, in particular: # - Delete lines up to the one beginning with "## .." (inclusive) # - Delete lines from the next one beginning with "## " until the end of the file # - Change all the "### " to "## " to use heading level 2 instead of level 3 sed -e "1,/^## ${VERSION_POM}/d;/^## /,\$d;s/^### /## /g" CHANGELOG.md > RELEASE-CHANGELOG.md gh release create v${VERSION_POM} --title "VOMS API Java ${VERSION_POM}" --notes-file RELEASE-CHANGELOG.md build-*/* voms-api-java-3.3.5/.github/workflows/maven.yaml000066400000000000000000000056721477577347300216250ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare # # SPDX-License-Identifier: Apache-2.0 name: Maven build on: push: env: SNAPSHOT_BRANCH: develop jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up JDK 17 uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: 17 server-id: central server-username: MAVEN_CENTRAL_USERNAME server-password: MAVEN_CENTRAL_PASSWORD gpg-private-key: ${{ secrets.MAVEN_GPG_KEY }} gpg-passphrase: MAVEN_GPG_PASSPHRASE - name: Install libfaketime on Ubuntu run: | sudo apt update sudo apt install -y faketime - name: Clone remote repository run: | git clone https://baltig.infn.it/mw-devel/helper-scripts.git $GITHUB_WORKSPACE/helper-scripts echo "Repo cloned to $GITHUB_WORKSPACE/helper-scripts" - name: Add to PATH run: | echo "$GITHUB_WORKSPACE/helper-scripts/x509-scripts/scripts" >> $GITHUB_PATH echo "Updated PATH with $GITHUB_WORKSPACE/helper-scripts/x509-scripts/scripts" - name: Verify PATH run: | echo "Current PATH: $PATH" ls -la $GITHUB_WORKSPACE/helper-scripts/x509-scripts/scripts - name: Create CA files run: | echo "Create CA files ..." cd src/test/resources ./setup.sh || { echo "setup.sh failed"; exit 1; } cd ../../../ - name: Cache Maven packages uses: actions/cache@v4 with: path: ~/.m2 key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} restore-keys: ${{ runner.os }}-m2 - name: Build with Maven run: mvn -B clean package - name: Deploy to Maven Central env: MAVEN_CENTRAL_USERNAME: ${{ vars.MAVEN_CENTRAL_USERNAME }} MAVEN_CENTRAL_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} run: | VERSION_POM=$(mvn org.apache.maven.plugins:maven-help-plugin:evaluate -Dexpression=project.version -q -DforceStdout) if [[ ${{ github.ref_type }} = 'tag' ]]; then # In case is a tag, get the tag value GITHUB_REF=${{ github.ref }} TAG_NAME=${GITHUB_REF#refs/tags/} # Check if the tag matches v.. if [[ ${TAG_NAME} =~ ^v([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then VERSION="${BASH_REMATCH[1]}" if [[ ${VERSION} != ${VERSION_POM} ]]; then echo "Version mismatch between tag (${VERSION}) and POM file (${VERSION_POM})" exit 1 fi mvn deploy -P central-staging fi elif [[ ${GITHUB_REF} = "refs/heads/${SNAPSHOT_BRANCH}" ]]; then # Check if the version in POM file matches ..-SNAPSHOT if [[ ${VERSION_POM} =~ ^[0-9]+\.[0-9]+\.[0-9]+-SNAPSHOT$ ]]; then mvn deploy -P central-staging fi fi voms-api-java-3.3.5/.github/workflows/reuse.yaml000066400000000000000000000004751477577347300216360ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2020 Free Software Foundation Europe e.V. # SPDX-License-Identifier: CC0-1.0 name: REUSE Compliance Check on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: REUSE Compliance Check uses: fsfe/reuse-action@v4 voms-api-java-3.3.5/.gitignore000066400000000000000000000012201477577347300162070ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare # # SPDX-License-Identifier: Apache-2.0 /.settings /bin /dist /target /.classpath /.project /spec/voms-api-java.spec /rpmbuild /debbuild /RPMS /tgz /target /src/test/resources/certs /src/test/resources/homes /src/test/resources/vomsdir-expired-aa-cert /src/test/resources/vomsdir-fake-aa-cert /src/test/resources/vomsdir/test.vo.2/test-host.cnaf.infn.it.pem /src/test/resources/vomsdir/test-host.cnaf.infn.it.pem /src/test/resources/trust-anchors /src/test/resources/md5-trust-anchors /src/test/resources/perm-test /src/test/resources/sha1-trust-anchors /src/test/resources/igi_test_ca voms-api-java-3.3.5/AUTHORS000066400000000000000000000003761477577347300153020ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare # # SPDX-License-Identifier: Apache-2.0 Andrea Ceccanti Valerio Venturi Daniele Andreotti voms-api-java-3.3.5/CHANGELOG.md000066400000000000000000000005331477577347300160360ustar00rootroot00000000000000 # Changelog ## 3.3.5 (2025-04-10) ### Changed * Bump to CANL 2.8.3 and BC 1.80 ## 3.3.4 (2025-04-04) ### Changed * Bump to Java 17, CANL 2.7.0 and BC 1.69 ### Fixed * Fix multi-chain LSC files by reading only the first chain voms-api-java-3.3.5/LICENSE000066400000000000000000000261361477577347300152410ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. voms-api-java-3.3.5/LICENSES/000077500000000000000000000000001477577347300154315ustar00rootroot00000000000000voms-api-java-3.3.5/LICENSES/Apache-2.0.txt000066400000000000000000000240501477577347300176510ustar00rootroot00000000000000Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. voms-api-java-3.3.5/LICENSES/CC0-1.0.txt000066400000000000000000000156101477577347300170360ustar00rootroot00000000000000Creative Commons Legal Code CC0 1.0 Universal CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER. Statement of Purpose The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work"). Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others. For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights. 1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following: i. the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; ii. moral rights retained by the original author(s) and/or performer(s); iii. publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; iv. rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below; v. rights protecting the extraction, dissemination, use and reuse of data in a Work; vi. database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and vii. other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. 2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose. 3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose. 4. Limitations and Disclaimers. a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document. b. Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law. c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. voms-api-java-3.3.5/LICENSES/EUPL-1.2.txt000066400000000000000000000327401477577347300172430ustar00rootroot00000000000000EUROPEAN UNION PUBLIC LICENCE v. 1.2 EUPL © the European Union 2007, 2016 This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined below) which is provided under the terms of this Licence. Any use of the Work, other than as authorised under this Licence is prohibited (to the extent such use is covered by a right of the copyright holder of the Work). The Work is provided under the terms of this Licence when the Licensor (as defined below) has placed the following notice immediately following the copyright notice for the Work: Licensed under the EUPL or has expressed by any other means his willingness to license under the EUPL. 1.Definitions In this Licence, the following terms have the following meaning: — ‘The Licence’:this Licence. — ‘The Original Work’:the work or software distributed or communicated by the Licensor under this Licence, available as Source Code and also as Executable Code as the case may be. — ‘Derivative Works’:the works or software that could be created by the Licensee, based upon the Original Work or modifications thereof. This Licence does not define the extent of modification or dependence on the Original Work required in order to classify a work as a Derivative Work; this extent is determined by copyright law applicable in the country mentioned in Article 15. — ‘The Work’:the Original Work or its Derivative Works. — ‘The Source Code’:the human-readable form of the Work which is the most convenient for people to study and modify. — ‘The Executable Code’:any code which has generally been compiled and which is meant to be interpreted by a computer as a program. — ‘The Licensor’:the natural or legal person that distributes or communicates the Work under the Licence. — ‘Contributor(s)’:any natural or legal person who modifies the Work under the Licence, or otherwise contributes to the creation of a Derivative Work. — ‘The Licensee’ or ‘You’:any natural or legal person who makes any usage of the Work under the terms of the Licence. — ‘Distribution’ or ‘Communication’:any act of selling, giving, lending, renting, distributing, communicating, transmitting, or otherwise making available, online or offline, copies of the Work or providing access to its essential functionalities at the disposal of any other natural or legal person. 2.Scope of the rights granted by the Licence The Licensor hereby grants You a worldwide, royalty-free, non-exclusive, sublicensable licence to do the following, for the duration of copyright vested in the Original Work: — use the Work in any circumstance and for all usage, — reproduce the Work, — modify the Work, and make Derivative Works based upon the Work, — communicate to the public, including the right to make available or display the Work or copies thereof to the public and perform publicly, as the case may be, the Work, — distribute the Work or copies thereof, — lend and rent the Work or copies thereof, — sublicense rights in the Work or copies thereof. Those rights can be exercised on any media, supports and formats, whether now known or later invented, as far as the applicable law permits so. In the countries where moral rights apply, the Licensor waives his right to exercise his moral right to the extent allowed by law in order to make effective the licence of the economic rights here above listed. The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to any patents held by the Licensor, to the extent necessary to make use of the rights granted on the Work under this Licence. 3.Communication of the Source Code The Licensor may provide the Work either in its Source Code form, or as Executable Code. If the Work is provided as Executable Code, the Licensor provides in addition a machine-readable copy of the Source Code of the Work along with each copy of the Work that the Licensor distributes or indicates, in a notice following the copyright notice attached to the Work, a repository where the Source Code is easily and freely accessible for as long as the Licensor continues to distribute or communicate the Work. 4.Limitations on copyright Nothing in this Licence is intended to deprive the Licensee of the benefits from any exception or limitation to the exclusive rights of the rights owners in the Work, of the exhaustion of those rights or of other applicable limitations thereto. 5.Obligations of the Licensee The grant of the rights mentioned above is subject to some restrictions and obligations imposed on the Licensee. Those obligations are the following: Attribution right: The Licensee shall keep intact all copyright, patent or trademarks notices and all notices that refer to the Licence and to the disclaimer of warranties. The Licensee must include a copy of such notices and a copy of the Licence with every copy of the Work he/she distributes or communicates. The Licensee must cause any Derivative Work to carry prominent notices stating that the Work has been modified and the date of modification. Copyleft clause: If the Licensee distributes or communicates copies of the Original Works or Derivative Works, this Distribution or Communication will be done under the terms of this Licence or of a later version of this Licence unless the Original Work is expressly distributed only under this version of the Licence — for example by communicating ‘EUPL v. 1.2 only’. The Licensee (becoming Licensor) cannot offer or impose any additional terms or conditions on the Work or Derivative Work that alter or restrict the terms of the Licence. Compatibility clause: If the Licensee Distributes or Communicates Derivative Works or copies thereof based upon both the Work and another work licensed under a Compatible Licence, this Distribution or Communication can be done under the terms of this Compatible Licence. For the sake of this clause, ‘Compatible Licence’ refers to the licences listed in the appendix attached to this Licence. Should the Licensee's obligations under the Compatible Licence conflict with his/her obligations under this Licence, the obligations of the Compatible Licence shall prevail. Provision of Source Code: When distributing or communicating copies of the Work, the Licensee will provide a machine-readable copy of the Source Code or indicate a repository where this Source will be easily and freely available for as long as the Licensee continues to distribute or communicate the Work. Legal Protection: This Licence does not grant permission to use the trade names, trademarks, service marks, or names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the copyright notice. 6.Chain of Authorship The original Licensor warrants that the copyright in the Original Work granted hereunder is owned by him/her or licensed to him/her and that he/she has the power and authority to grant the Licence. Each Contributor warrants that the copyright in the modifications he/she brings to the Work are owned by him/her or licensed to him/her and that he/she has the power and authority to grant the Licence. Each time You accept the Licence, the original Licensor and subsequent Contributors grant You a licence to their contributions to the Work, under the terms of this Licence. 7.Disclaimer of Warranty The Work is a work in progress, which is continuously improved by numerous Contributors. It is not a finished work and may therefore contain defects or ‘bugs’ inherent to this type of development. For the above reason, the Work is provided under the Licence on an ‘as is’ basis and without warranties of any kind concerning the Work, including without limitation merchantability, fitness for a particular purpose, absence of defects or errors, accuracy, non-infringement of intellectual property rights other than copyright as stated in Article 6 of this Licence. This disclaimer of warranty is an essential part of the Licence and a condition for the grant of any rights to the Work. 8.Disclaimer of Liability Except in the cases of wilful misconduct or damages directly caused to natural persons, the Licensor will in no event be liable for any direct or indirect, material or moral, damages of any kind, arising out of the Licence or of the use of the Work, including without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, loss of data or any commercial damage, even if the Licensor has been advised of the possibility of such damage. However, the Licensor will be liable under statutory product liability laws as far such laws apply to the Work. 9.Additional agreements While distributing the Work, You may choose to conclude an additional agreement, defining obligations or services consistent with this Licence. However, if accepting obligations, You may act only on your own behalf and on your sole responsibility, not on behalf of the original Licensor or any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against such Contributor by the fact You have accepted any warranty or additional liability. 10.Acceptance of the Licence The provisions of this Licence can be accepted by clicking on an icon ‘I agree’ placed under the bottom of a window displaying the text of this Licence or by affirming consent in any other similar way, in accordance with the rules of applicable law. Clicking on that icon indicates your clear and irrevocable acceptance of this Licence and all of its terms and conditions. Similarly, you irrevocably accept this Licence and all of its terms and conditions by exercising any rights granted to You by Article 2 of this Licence, such as the use of the Work, the creation by You of a Derivative Work or the Distribution or Communication by You of the Work or copies thereof. 11.Information to the public In case of any Distribution or Communication of the Work by means of electronic communication by You (for example, by offering to download the Work from a remote location) the distribution channel or media (for example, a website) must at least provide to the public the information requested by the applicable law regarding the Licensor, the Licence and the way it may be accessible, concluded, stored and reproduced by the Licensee. 12.Termination of the Licence The Licence and the rights granted hereunder will terminate automatically upon any breach by the Licensee of the terms of the Licence. Such a termination will not terminate the licences of any person who has received the Work from the Licensee under the Licence, provided such persons remain in full compliance with the Licence. 13.Miscellaneous Without prejudice of Article 9 above, the Licence represents the complete agreement between the Parties as to the Work. If any provision of the Licence is invalid or unenforceable under applicable law, this will not affect the validity or enforceability of the Licence as a whole. Such provision will be construed or reformed so as necessary to make it valid and enforceable. The European Commission may publish other linguistic versions or new versions of this Licence or updated versions of the Appendix, so far this is required and reasonable, without reducing the scope of the rights granted by the Licence. New versions of the Licence will be published with a unique version number. All linguistic versions of this Licence, approved by the European Commission, have identical value. Parties can take advantage of the linguistic version of their choice. 14.Jurisdiction Without prejudice to specific agreement between parties, — any litigation resulting from the interpretation of this License, arising between the European Union institutions, bodies, offices or agencies, as a Licensor, and any Licensee, will be subject to the jurisdiction of the Court of Justice of the European Union, as laid down in article 272 of the Treaty on the Functioning of the European Union, — any litigation arising between other parties and resulting from the interpretation of this License, will be subject to the exclusive jurisdiction of the competent court where the Licensor resides or conducts its primary business. 15.Applicable Law Without prejudice to specific agreement between parties, — this Licence shall be governed by the law of the European Union Member State where the Licensor has his seat, resides or has his registered office, — this licence shall be governed by Belgian law if the Licensor has no seat, residence or registered office inside a European Union Member State. Appendix ‘Compatible Licences’ according to Article 5 EUPL are: — GNU General Public License (GPL) v. 2, v. 3 — GNU Affero General Public License (AGPL) v. 3 — Open Software License (OSL) v. 2.1, v. 3.0 — Eclipse Public License (EPL) v. 1.0 — CeCILL v. 2.0, v. 2.1 — Mozilla Public Licence (MPL) v. 2 — GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3 — Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for works other than software — European Union Public Licence (EUPL) v. 1.1, v. 1.2 — Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong Reciprocity (LiLiQ-R+). The European Commission may update this Appendix to later versions of the above licences without producing a new version of the EUPL, as long as they provide the rights granted in Article 2 of this Licence and protect the covered Source Code from exclusive appropriation. All other changes or additions to this Appendix require the production of a new EUPL version. voms-api-java-3.3.5/README.md000066400000000000000000000174141477577347300155120ustar00rootroot00000000000000 # VOMS Java API ![Build Status](https://github.com/italiangrid/voms-api-java/actions/workflows/maven.yaml/badge.svg) Java client APIs for the Virtual Organization Membership Service (VOMS). The VOMS API can be used for - validating attribute certifcates (ACs) inside a proxy and reading the attributes (VOSM FQANs or VOMS generic attributes) - contacting a VOMS service in order to get an AC and for creating proxy certificates that contains an AC ## Installing If using Maven, add the dependencies to your pom file ```bash org.italiangrid voms-api-java ${voms-api-java-version} ``` ### Configure logging VOMS Java API does not rely on logging anymore to provide information to the API user. The API now provides listeners that receive interesting events related to VOMS attribute certificate parsing and validation and interactions with remote VOMS servers. ## Getting started ### Validation With version 3.0 of the API, the validation interface changes significantly. In order to validate VOMS attributes one has to do the following: ```java /* certificate chain may come either from loading (and validating) using BouncyCastle or from an authenticated HTTPS session */ X509Certificate[] theChain = ...; VOMSACValidator validator = VOMSValidators.newValidator(); List vomsAttrs = validator.validate(theChain); ``` The VOMSAttribute interface provides access to all VOMS attributes (i.e., FQANs and Generic attributes): ```java if (vomsAttrs.size() > 0) { VOMSAttribute va = vomsAttrs.get(0); List fqans = va.getFQANs(); for (String f: fqans) System.out.println(f); List gas = va.getGenericAttributes(); for (VOMSGenericAttribute g: gas) System.out.println(g); } ``` #### Getting more information about the validation outcome The API just described returns a possibly empty list of validated VOMS attributes. In order to get more information on the validation outcome (e.g. error messages etc. ) you now have two possibilities: - register a `ValidationResultListener` on the validator and separate your error handling logic from the main flow of your code - use the `validateWithResult` method #### Setting a ValidationResultListener The interface of a ValidationResultListener is defined as follows: ```java void notifyValidationResult(VOMSValidationResult result) ``` The VOMSValidationResult class provides info on the outcome of VOMS validation: ```java VOMSValidationResult{ boolean isValid(); List getValidationErrors(); VOMSAttribute getAttributes(); } ``` You can register a ValidationResultListener at VOMSACValidator creation time: ```java VOMSACValidator validator = VOMSValidators.newValidator(new ValidationResultListener() { public void notifyValidationResult(VOMSValidationResult result) { // Your code here ... }}); ``` or later with the `setValidationResultListener(ValidationResultListener l)` method. ### Using the `validateWithResult` method ```java List results = validator.validateWithResult(theChain); for(VOMSValidationResult r: results){ if ( r.isValid() ){ VOMSAttribute attrs = r.getAttributes(); ... }else{ // error handling code } } ``` ### Requesting a VOMS AC from a server and creating a proxy out of it In order to request a VOMS AC from a VOMS server you start by providing your own credentials. To parse your credentials (certificate + private key) you will use the ```java UserCredentials.loadCredentials(char[] keyPassword); ``` method. This methods looks for PEM or PKCS12 credentials in standard localtions and returns a CANL X509Credential. ```java /* Load user's credentials */ X509Credential cred = UserCredentials.loadCredentials("passphrase".toCharArray()); ``` To request an AC from a VOMS service, one has to create a VOMSACRequest in order to set options for the requested AC, like its lifetime, the VO name or the requested VOMS fqans. The VOMSACService requires that you pass in a CANL `X509CerChainValidatorExt` object that will be used to setup the SSL connection and perform certificate validation. You can easily build one with the `CertificateValidatorBuilder` VOMS helper class: ```java X509CertChainValidatorExt validator = CertificateValidatorBuilder.buildCertificateValidator(); VOMSACService service = new DefaultVOMSACService.Builder(validator).build(); DefaultVOMSACRequest request = new DefaultVOMSACRequest.Builder("atlas").lifetime(10).build(); AttributeCertificate attributeCertificate = service.getVOMSAttributeCertificate(cred, request); ``` Creating a proxy containing the VOMS AC just obtained is trivial with the help of CANL proxy generation utilities: ```java ProxyCertificateOptions proxyOptions = new ProxyCertificateOptions(cred.getCertificateChain()); proxyOptions.setAttributeCertificates(new AttributeCertificate[] {attributeCertificate}); ProxyCertificate proxyCert = ProxyGenerator.generate(proxyOptions, cred.getKey()); ``` The proxy can then be saved to an output stream in PEM format using the ```java CredentialsUtils.saveCredentials(OutputStream os, X509Credential uc) ``` method, as shown in the following example: ```java OutputStream os = new FileOutputStream("/tmp/savedProxy"); CredentialsUtils.saveCredentials(os, proxyCert.getCredential()); ``` ### Migrating from VOMS API Java v. 2.x In order to use the new API update your pom.xml with the right dependencies (in case you use maven). ```bash org.italiangrid voms-api-java 3.0.0 ``` or install the VOMS API 3.0 packages (rpms or debs). With the API v. 2.0.9 the following approach would be used to validate a VOMS AC: ```java /* 2.0.x API packages */ import org.glite.voms.VOMSAttribute; import org.glite.voms.VOMSValidator; ... // Validated certificate chain */ X509Certificate[] certchain = ...; VOMSValidator validator = new VOMSValidator(certchain); validator.validate(); List attrs = validator.getVOMSAttributes(); for (VOMSAttribute a : attrs) // Do something with the attribute ... ``` With version 3.0 the name of the packages to import has changed: ```java /* 3.0.x API packages */ import org.italiangrid.voms.test.VOMSAttribute; import org.italiangrid.voms.test.VOMSValidators; import org.italiangrid.voms.test.ac.VOMSACValidator; // The VOMSACValidator interface provides access to VOMS AC validation logic. // In order to obtain a validator use the VOMSValidators factory VOMSACValidator validator = VOMSValidators.newValidator(); // An X.509 certcain obtained somehow X509Certificate[] certChain = ...; // Use the validate method to obtain a list of VOMSAttribute objects List attrs = validator.validate(certChain); for (VOMSAttribute a : attrs){ // Do something with the attribute ... } // Shutdown the validator. This should be called only when you're sure that // you will not need the validator anymore. validator.shutdown(); ``` ## Documentation More details on the new APIs can be found in the [Javadoc](http://italiangrid.github.com/voms-api-java/javadocs/3.x/index.html). ## License Licensed under the Apache License, Version 2.0 (the "License"); you may not use this project except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. voms-api-java-3.3.5/REUSE.toml000066400000000000000000000004311477577347300160020ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare # # SPDX-License-Identifier: Apache-2.0 version = 1 [[annotations]] path = ["src/test/resources/**"] SPDX-FileCopyrightText = "2006 Istituto Nazionale di Fisica Nucleare" SPDX-License-Identifier = "Apache-2.0" voms-api-java-3.3.5/pom.xml000066400000000000000000000266101477577347300155460ustar00rootroot00000000000000 4.0.0 org.italiangrid voms-api-java 3.3.5 jar voms-api-java Java APIs to validate and request VOMS attribute certificates https://github.com/italiangrid/voms-api-java The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt https://github.com/italiangrid/voms-api-java scm:git:git://github.com/italiangrid/voms-api-java.git scm:git:ssh://git@github.com:italiangrid/voms-api-java.git 3.5.0 2.16.1 3.13.0 3.1.1 2.2.1 3.7.1 3.4.2 2.9.1 2.7 3.2.5 0.7.0 3.2.7 3.11.2 4.13.2 1.3 2.8.3 5.16.0 1.0 1.80 17 UTF-8 UTF-8 /usr/share/java /usr/share/doc/${project.name} /usr/share/javadoc/${project.name} vianello Enrico Vianello enrico.vianello@cnaf.infn.it INFN CNAF Developer giaco Francesco Giacomini francesco.giacomini@cnaf.infn.it INFN CNAF Developer szotti Stefano Zotti stefano.zotti@cnaf.infn.it INFN CNAF Developer org.apache.maven.plugins maven-enforcer-plugin ${plugin.enforcer.version} enforce-maven enforce 3.6.3 org.codehaus.mojo versions-maven-plugin ${plugin.versions.version} org.apache.maven.plugins maven-compiler-plugin ${plugin.compiler.version} 17 true true org.codehaus.mojo cobertura-maven-plugin ${plugin.cobertura.version} html xml org/italiangrid/voms/test/**/*.class org/italiangrid/voms/examples/**/*.class org.apache.maven.plugins maven-assembly-plugin ${plugin.assembly.version} ${project.name} false ${basedir}/src/main/assembly/voms-api-java.xml org.apache.maven.plugins maven-release-plugin ${plugin.release.version} forked-path org.apache.maven.plugins maven-jar-plugin ${plugin.jar.version} true org.apache.maven.plugins maven-javadoc-plugin ${plugin.javadoc.version} 17 ${project.build.directory}/javadoc attach-javadocs jar org.apache.maven.plugins maven-source-plugin ${plugin.source.version} attach-sources jar-no-fork junit junit ${junit.version} test org.hamcrest hamcrest-core ${hamcrest.version} test eu.eu-emi.security canl ${canl.version} org.bouncycastle bcpkix-jdk18on org.bouncycastle bcprov-jdk18on org.bouncycastle bcpkix-jdk18on ${bc.version} org.bouncycastle bcprov-jdk18on ${bc.version} net.jcip jcip-annotations ${jcip.version} provided org.mockito mockito-core ${mockito.version} test release-sign-artifacts performRelease true org.apache.maven.plugins maven-gpg-plugin ${plugin.gpg.version} ${env.GPG_PASSPHRASE} sign-artifacts verify sign local-staging true cnaf-releases CNAF releases https://repo.cloud.cnaf.infn.it/repository/cnaf-releases/ cnaf-snapshots CNAF snapshots https://repo.cloud.cnaf.infn.it/repository/cnaf-snapshots/ central-staging org.sonatype.central central-publishing-maven-plugin ${plugin.central-publishing.version} true central org.apache.maven.plugins maven-gpg-plugin ${plugin.maven-gpg.version} sign-artifacts verify sign --pinentry-mode loopback voms-api-java-3.3.5/src/000077500000000000000000000000001477577347300150135ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/000077500000000000000000000000001477577347300157375ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/assembly/000077500000000000000000000000001477577347300175565ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/assembly/voms-api-java.xml000066400000000000000000000020251477577347300227510ustar00rootroot00000000000000 main tar.gz false target/site/javadoc/apidocs ${assembly.javadoc.dir} 0644 target/${project.build.finalName}.jar ${project.build.finalName}.jar ${assembly.java.dir} 0644 voms-api-java-3.3.5/src/main/java/000077500000000000000000000000001477577347300166605ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/java/org/000077500000000000000000000000001477577347300174475ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/java/org/italiangrid/000077500000000000000000000000001477577347300217365ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/000077500000000000000000000000001477577347300227225ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/VOMSAttribute.java000066400000000000000000000105321477577347300262360ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms; import java.math.BigInteger; import java.security.cert.X509Certificate; import java.util.Date; import java.util.List; import javax.security.auth.x500.X500Principal; import org.bouncycastle.cert.X509AttributeCertificateHolder; /** * The VOMS attributes information. This interface provides access to all the * information available in a VOMS attribute certificate. * * @author Andrea Ceccanti * */ public interface VOMSAttribute { /** * This method returns the name of the VO this VOMS attributes are about * * @return The name of the VO this VOMS attributes are about */ public String getVO(); /** * This method returns the host where the VOMS Attribute Authority (AA) that * signed these attribute lives * * @return The name of the host where the VOMS AA that signed these attributes * lives */ public String getHost(); /** * This method returns the port on which the VOMS Attribute Authority (AA) * that signed these attributes listens for requests. * * @return The port on which the VOMS AA that signed these attributes listens * for requests */ public int getPort(); /** * This method returns the subject (as an {@link X500Principal}) of the holder * of these VOMS attributes * * @return The subject of the holder of these VOMS attributes */ public X500Principal getHolder(); /** * This method returns the holder certificate serial number * * @return The serial number of the holder certificate */ public BigInteger getHolderSerialNumber(); /** * This method returns the subject of the VOMS Attribute Authority that signed * these attributes. * * @return The subject of the VOMS AA that signed these attributes */ public X500Principal getIssuer(); /** * This method returns the attributes' validity start time * * @return The attributes' validity start time */ public Date getNotBefore(); /** * This method returns the attributes' validity end time * * @return The attributes' validity end time */ public Date getNotAfter(); /** * This method returns the list of signed Fully Qualified Attribute Names * (FQANs) in this {@link VOMSAttribute}. * * @return The {@link List} of VOMS fully qualified attribute names */ public List getFQANs(); /** * This method returns the primary FQAN (the first in the list returned by * {@link #getFQANs()}) in this {@link VOMSAttribute}. * * @return The primary VOMS fully qualified attribute name */ public String getPrimaryFQAN(); /** * This method returns the signature on the VOMS attribute certificate as a * byte array. * * @return The signature of this VOMS attributes */ public byte[] getSignature(); /** * This method returns the list of VOMS Generic attributes in this * {@link VOMSAttribute}. * * @return The VOMS generic attributes */ public List getGenericAttributes(); /** * This method returns the list of targets defined for this * {@link VOMSAttribute}. * * @return The targets for this VOMS attributes */ public List getTargets(); /** * This method returns the certificate chain of the VOMS Attribute Authority * (AA) that signed this {@link VOMSAttribute}. * * @return The VOMS AA certificate chain */ public X509Certificate[] getAACertificates(); /** * This method checks whether the attributes are valid in the current instant * of time. No validation is performed on the attributes. * * @return true if valid, false otherwise */ public boolean isValid(); /** * This method checks whether the attributes are valid in a given time passed * as argument. No validation is performed on the attributes. * * @param time * the time used for the validity check * @return true if valid, false otherwise */ public boolean validAt(Date time); /** * This method returns the underlying VOMS Attribute certificate object. * * @return the underlying bouncycastle object for the VOMS attribute * certificate. */ public X509AttributeCertificateHolder getVOMSAC(); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/VOMSError.java000066400000000000000000000007521477577347300253670ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms; /** * The base VOMS exception class. * * @author Andrea Ceccanti * */ public class VOMSError extends RuntimeException { /** * */ private static final long serialVersionUID = 1L; public VOMSError(String message) { super(message); } public VOMSError(String message, Throwable cause) { super(message, cause); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/VOMSGenericAttribute.java000066400000000000000000000014341477577347300275340ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms; /** * A VOMS generic attribute is a name=value pair attribute augmented with a * context. * * * @author Andrea Ceccanti * */ public interface VOMSGenericAttribute { /** * This method returns the name of this generic attribute * * @return the name of this generic attribute */ public String getName(); /** * This method returns the value of this generic attribute * * @return the value of this generic attribute */ public String getValue(); /** * This method returns the context for this generic attribute * * @return the context of this generic attribute */ public String getContext(); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/VOMSValidators.java000066400000000000000000000037461477577347300264140ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms; import org.italiangrid.voms.ac.VOMSACLookupStrategy; import org.italiangrid.voms.ac.VOMSACParser; import org.italiangrid.voms.ac.VOMSACValidator; import org.italiangrid.voms.ac.ValidationResultListener; import org.italiangrid.voms.ac.impl.DefaultVOMSACParser; import org.italiangrid.voms.ac.impl.DefaultVOMSValidator; import org.italiangrid.voms.store.VOMSTrustStore; import eu.emi.security.authn.x509.X509CertChainValidatorExt; /** * A factory for VOMS attributes validators and parsers. * * @author Andrea Ceccanti * */ public class VOMSValidators { private VOMSValidators() { } public static VOMSACValidator newValidator(ValidationResultListener listener) { return new DefaultVOMSValidator.Builder().validationListener(listener) .build(); } public static VOMSACValidator newValidator(VOMSTrustStore trustStore, X509CertChainValidatorExt validator, ValidationResultListener vrListener) { return new DefaultVOMSValidator.Builder().trustStore(trustStore) .certChainValidator(validator).validationListener(vrListener).build(); } public static VOMSACValidator newValidator(VOMSTrustStore store, X509CertChainValidatorExt validator, ValidationResultListener vrListener, VOMSACLookupStrategy strategy) { return new DefaultVOMSValidator.Builder().trustStore(store) .certChainValidator(validator).validationListener(vrListener) .acLookupStrategy(strategy).build(); } public static VOMSACValidator newValidator(VOMSTrustStore trustStore, X509CertChainValidatorExt validator) { return new DefaultVOMSValidator.Builder().trustStore(trustStore) .certChainValidator(validator).build(); } public static VOMSACValidator newValidator() { return new DefaultVOMSValidator.Builder().build(); } public static VOMSACParser newParser() { return new DefaultVOMSACParser(); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/ac/000077500000000000000000000000001477577347300233055ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/ac/ACLookupListener.java000066400000000000000000000021411477577347300273310ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.ac; import java.security.cert.X509Certificate; /** * This interface is used to notify of events related to the lookup and * succesfull parsing of VOMS attribute certificates from a certificate chain. * * @author andreaceccanti * */ public interface ACLookupListener { /** * Informs that an AC is being looked for in the cert chain passed as * argument. * * @param chain * the chain where the AC is looked for * @param chainLevel * the level in the chain where the AC is being looked for */ public void notifyACLookupEvent(X509Certificate[] chain, int chainLevel); /** * Informs that an AC has been succesfully parsed from the cert chain passed * as argument * * @param chain * the chain from which the AC has been parsed * @param chainLevel * the level in the chain where the AC has been parsed */ public void notifyACParseEvent(X509Certificate[] chain, int chainLevel); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/ac/ACParsingContext.java000066400000000000000000000040721477577347300273270ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.ac; import java.security.cert.X509Certificate; import java.util.List; import org.bouncycastle.asn1.x509.AttributeCertificate; /** * This class describes the context in which a VOMS {@link AttributeCertificate} * has been parsed in a certificate chain. * * @author Andrea Ceccanti * */ public class ACParsingContext { /** The parsed VOMS attribute certificates **/ private List ACs; /** The position in the cert chain where the VOMS attributes have been parsed **/ private int certChainPostion; /** The certificate chain form which the VOMS attributes have been parsed. **/ private X509Certificate[] certChain; /** * @return the aCs */ public List getACs() { return ACs; } /** * @param aCs * the aCs to set */ public void setACs(List aCs) { ACs = aCs; } /** * @return the certChainPostion */ public int getCertChainPostion() { return certChainPostion; } /** * @param certChainPostion * the certChainPostion to set */ public void setCertChainPostion(int certChainPostion) { this.certChainPostion = certChainPostion; } /** * @return the certChain */ public X509Certificate[] getCertChain() { return certChain; } /** * @param certChain * the certChain to set */ public void setCertChain(X509Certificate[] certChain) { this.certChain = certChain; } /** * @param aCs * a set of parsed VOMS Attribute Certificates * @param certChainPostion * the position in the chain where the ACs have been parsed * @param certChain * the chain from where the ACs have been parsed */ public ACParsingContext(List aCs, int certChainPostion, X509Certificate[] certChain) { ACs = aCs; this.certChainPostion = certChainPostion; this.certChain = certChain; } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/ac/VOMSACLookupStrategy.java000066400000000000000000000015311477577347300300550ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.ac; import java.security.cert.X509Certificate; import java.util.List; /** * * A strategy for looking up a set of VOMS Attribute Certificates from a * certificate chain. * * @author Andrea Ceccanti * */ public interface VOMSACLookupStrategy { /** * This method defines how a set of VOMS Attribute Certificates is looked for * in a certificate chain. * * @param certChain * the certificate chain that will be searched for VOMS attribute * certificates * * @return a {@link List} of {@link ACParsingContext} that describes the * lookup outcome */ public List lookupVOMSAttributeCertificates( X509Certificate[] certChain); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/ac/VOMSACParser.java000066400000000000000000000015171477577347300263210ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.ac; import java.security.cert.X509Certificate; import java.util.List; import org.italiangrid.voms.VOMSAttribute; /** * This interface defines the behavior of a VOMS Attribute Certificate parser. * * * @author Andrea Ceccanti * */ public interface VOMSACParser { /** * Looks for and parses VOMS attributes in the certificate chain passed as * argument (which is assumed to be already validated). * * @param validatedChain * a validated X.509 certificate chain * @return a possibly empty list of {@link VOMSAttribute} objects providing * access to the parsed VOMS attributes */ public List parse(X509Certificate[] validatedChain); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/ac/VOMSACValidationStrategy.java000066400000000000000000000022651477577347300307030ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.ac; import java.security.cert.X509Certificate; import org.italiangrid.voms.VOMSAttribute; /** * The strategy implemented to perform the validation of a VOMS attribute * certificate. * * @author Andrea Ceccanti * */ public interface VOMSACValidationStrategy { /** * Validates a VOMS Attribute Certificate * * @param attributes * the parsed VOMS attributes * @param theChain * the certificate chain from which the attributes were parsed * @return a {@link VOMSValidationResult} object describing the outcome of the * validation */ public VOMSValidationResult validateAC(VOMSAttribute attributes, X509Certificate[] theChain); /** * Validates VOMS attributes not extracted from a certificate chain (e.g., as * returned from the VOMS server) * * @param attributes * the VOMS attributes * @return a {@link VOMSValidationResult} object describing the outcome of the * validation */ public VOMSValidationResult validateAC(VOMSAttribute attributes); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/ac/VOMSACValidator.java000066400000000000000000000061001477577347300270030ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.ac; import java.security.cert.X509Certificate; import java.util.List; import org.bouncycastle.asn1.x509.AttributeCertificate; import org.italiangrid.voms.VOMSAttribute; /** * This interface extends the {@link VOMSACParser} interface and provides * methods to perform validation on the VOMS Attribute Certificates parsed from * a given certificate chain. * * @author Andrea Ceccanti * */ public interface VOMSACValidator extends VOMSACParser { /** * Parses and validates the VOMS attributes found in the certificate chain * passed as argument (which is assumed to be validated already). * * This method returns the possibly empty list of the validated attributes. * * This method should be used in conjunction with the registration of a * {@link ValidationResultListener} to get details about validation error and * warning messages. * * Use the {@link #validateWithResult(X509Certificate[])} method in case you * don't want to rely on a {@link ValidationResultListener}. * * @param validatedChain * a validated X.509 certificate chain * @return a possibly empty list of {@link VOMSAttribute} object providing * access to the validated VOMS attributes */ public List validate(X509Certificate[] validatedChain); /** * Parses and validates the VOMS attributes found in the certificate chain * passed as argument (which is assumed to be validated already). * * This method returns a possibly empty list of {@link VOMSValidationResult} * objects which describe the outcome of the validation for each VOMS AC found * in the certificate chain. * * This method is useful when you want to use a single call to get all details * about validation without relying on the registration of a * {@link ValidationResultListener}. * * @param validatedChain * a chain of X.509 certificates * @return a possibly empty list of {@link VOMSValidationResult} object * providing access to validation results and related attributes */ public List validateWithResult( X509Certificate[] validatedChain); /** * Validates the VOMS attributes found in the attribute certificate list * passed as argument. * * @param acs * a list of {@link AttributeCertificate} * @return the validated and possibly empty list of * {@link AttributeCertificate} object */ public List validateACs(List acs); /** * Sets a listener that will received validation-related events for this * {@link VOMSACValidator}. * * @param listener * the listener that will receive validation-related events. */ public void setValidationResultListener(ValidationResultListener listener); /** * Shutdown the VOMS validator. This method should be called to perform final * cleanup operations. */ public void shutdown(); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/ac/VOMSAttributesNormalizationStrategy.java000066400000000000000000000017071477577347300333020ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.ac; import java.util.List; import org.italiangrid.voms.VOMSAttribute; /** * A strategy to select the set of relevant and appliable VOMS attributes from a * set of parsed VOMS attribute certificates. * * This strategy is responsible of creating the {@link VOMSAttribute} objects * which represents the authorizative VOMS authorization information. * * @author Andrea Ceccanti * */ public interface VOMSAttributesNormalizationStrategy { /** * Returns the normalized view of VOMS Authorization information starting from * a list of VOMS Attribute certificates. * * @param acs * a list of {@link ACParsingContext} objects * * @return a possibly empty list {@link VOMSAttribute} object */ public List normalizeAttributes(List acs); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/ac/VOMSValidationResult.java000066400000000000000000000052631477577347300301540ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.ac; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.italiangrid.voms.VOMSAttribute; import org.italiangrid.voms.error.VOMSValidationErrorMessage; /** * This class represents the outcome of a VOMS validation. * * @author Andrea Ceccanti * */ public class VOMSValidationResult { /** The flag that tells whether the validation was successfull or not **/ private final boolean valid; /** A list of {@link VOMSValidationErrorMessage} **/ private final List validationErrors; /** The attributes this validation result refer to **/ private final VOMSAttribute attributes; /** * Default constructor. * * @param attributes * the attributes this validation result refer to * @param valid * true in case of validation success, * false otherwise */ public VOMSValidationResult(VOMSAttribute attributes, boolean valid) { this(attributes, valid, new ArrayList()); } /** * This constructor is used to pass in a list of validation errors as well. * * @param attributes * the {@link VOMSAttribute} that will be validated * @param valid * true in case of validation success, * false otherwise * @param validationErrors * a list of validation errors */ public VOMSValidationResult(VOMSAttribute attributes, boolean valid, List validationErrors) { this.attributes = attributes; this.valid = valid; this.validationErrors = validationErrors; } /** * Tells if validation was successful or not. * * @return valid true in case of validation success, * false otherwise */ public boolean isValid() { return valid; } /** * The attributes are to be considered valid only if the {@link #isValid()} * method for this {@link VOMSValidationResult} is true. * * @return the attributes this validation result refer to */ public VOMSAttribute getAttributes() { return attributes; } /** * @return the possibly empty list of validation errors */ public List getValidationErrors() { return Collections.unmodifiableList(validationErrors); } @Override public String toString() { return "VOMSValidationResult [valid=" + valid + ", validationErrors=" + validationErrors + ", attributes=" + attributes + "]"; } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/ac/ValidationResultListener.java000066400000000000000000000011461477577347300311510ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.ac; import org.italiangrid.voms.VOMSAttribute; /** * This interface is used to notify interested listeners of VOMS attribute * certificate validation outcome. * * @author andreaceccanti * */ public interface ValidationResultListener { /** * Informs of the result of the validation of a set of {@link VOMSAttribute} * * @param result * the validation result * */ public void notifyValidationResult(VOMSValidationResult result); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/ac/impl/000077500000000000000000000000001477577347300242465ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/ac/impl/DefaultLocalHostnameResolver.java000066400000000000000000000012221477577347300326660ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.ac.impl; import java.net.InetAddress; import java.net.UnknownHostException; /** * The default implementation for localhost name resolver. The localhost name is * resolved using the following code: * *
 * {@code
 * 		InetAddress.getLocalHost().getCanonicalHostName();
 * }
 * 
*/ public class DefaultLocalHostnameResolver implements LocalHostnameResolver { public String resolveLocalHostname() throws UnknownHostException { return InetAddress.getLocalHost().getCanonicalHostName(); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/ac/impl/DefaultVOMSACParser.java000066400000000000000000000052701477577347300305670ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.ac.impl; import java.security.cert.X509Certificate; import java.util.List; import org.italiangrid.voms.VOMSAttribute; import org.italiangrid.voms.ac.ACParsingContext; import org.italiangrid.voms.ac.VOMSACLookupStrategy; import org.italiangrid.voms.ac.VOMSACParser; import org.italiangrid.voms.ac.VOMSAttributesNormalizationStrategy; import org.italiangrid.voms.util.NullListener; /** * Default implementation of the VOMS attribute certificate parsing logic. * This class is responsible for extracting and normalizing VOMS attributes * from a given X.509 certificate chain. * *

It utilizes a {@link VOMSACLookupStrategy} to locate attribute certificates * within the provided chain and applies a {@link VOMSAttributesNormalizationStrategy} * to normalize the extracted attributes.

* *

By default, it uses {@link LeafACLookupStrategy} for lookup and * {@link LeafVOMSExtensionNormalizationStrategy} for normalization.

* */ public class DefaultVOMSACParser implements VOMSACParser { private final VOMSACLookupStrategy acLookupStrategy; private final VOMSAttributesNormalizationStrategy acNormalizationStrategy = new LeafVOMSExtensionNormalizationStrategy(); /** * Creates a new {@code DefaultVOMSACParser} with the default lookup strategy. * Uses {@link LeafACLookupStrategy} with a {@link NullListener} instance. */ public DefaultVOMSACParser() { this(new LeafACLookupStrategy(NullListener.INSTANCE)); } /** * Creates a new {@code DefaultVOMSACParser} with a specified lookup strategy. * Uses {@link LeafVOMSExtensionNormalizationStrategy} for attribute normalization. * * @param strategy the lookup strategy to use for locating attribute certificates * @throws NullPointerException if the provided strategy is {@code null} */ public DefaultVOMSACParser(VOMSACLookupStrategy strategy) { this.acLookupStrategy = strategy; } /** * Parses and extracts VOMS attributes from a validated X.509 certificate chain. * * @param validatedChain the certificate chain to analyze * @return a list of extracted and normalized {@link VOMSAttribute} objects * @throws NullPointerException if the provided certificate chain is {@code null} */ @Override public List parse(X509Certificate[] validatedChain) { if (validatedChain == null) throw new NullPointerException("Cannot parse a null certchain!"); List parsedACs = acLookupStrategy .lookupVOMSAttributeCertificates(validatedChain); return acNormalizationStrategy.normalizeAttributes(parsedACs); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/ac/impl/DefaultVOMSValidationStrategy.java000066400000000000000000000332711477577347300327460ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.ac.impl; import static org.italiangrid.voms.error.VOMSValidationErrorCode.aaCertFailsSignatureVerification; import static org.italiangrid.voms.error.VOMSValidationErrorCode.aaCertNotFound; import static org.italiangrid.voms.error.VOMSValidationErrorCode.acCertFailsSignatureVerification; import static org.italiangrid.voms.error.VOMSValidationErrorCode.acHolderDoesntMatchCertChain; import static org.italiangrid.voms.error.VOMSValidationErrorCode.acNotValidAtCurrentTime; import static org.italiangrid.voms.error.VOMSValidationErrorCode.canlError; import static org.italiangrid.voms.error.VOMSValidationErrorCode.emptyAcCertsExtension; import static org.italiangrid.voms.error.VOMSValidationErrorCode.invalidAaCert; import static org.italiangrid.voms.error.VOMSValidationErrorCode.invalidAcCert; import static org.italiangrid.voms.error.VOMSValidationErrorCode.localhostDoesntMatchAcTarget; import static org.italiangrid.voms.error.VOMSValidationErrorCode.lscDescriptionDoesntMatchAcCert; import static org.italiangrid.voms.error.VOMSValidationErrorCode.lscFileNotFound; import static org.italiangrid.voms.error.VOMSValidationErrorCode.other; import static org.italiangrid.voms.error.VOMSValidationErrorMessage.newErrorMessage; import java.net.UnknownHostException; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; import javax.security.auth.x500.X500Principal; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier; import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.asn1.x509.SubjectKeyIdentifier; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder; import org.bouncycastle.operator.ContentVerifierProvider; import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder; import org.bouncycastle.operator.bc.BcRSAContentVerifierProviderBuilder; import org.italiangrid.voms.VOMSAttribute; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.ac.VOMSACValidationStrategy; import org.italiangrid.voms.ac.VOMSValidationResult; import org.italiangrid.voms.asn1.VOMSConstants; import org.italiangrid.voms.error.VOMSValidationErrorMessage; import org.italiangrid.voms.store.LSCInfo; import org.italiangrid.voms.store.VOMSTrustStore; import eu.emi.security.authn.x509.ValidationError; import eu.emi.security.authn.x509.ValidationResult; import eu.emi.security.authn.x509.X509CertChainValidatorExt; import eu.emi.security.authn.x509.impl.X500NameUtils; import eu.emi.security.authn.x509.proxy.ProxyUtils; /** * The Default VOMS validation strategy. * * @author andreaceccanti * */ public class DefaultVOMSValidationStrategy implements VOMSACValidationStrategy { private final VOMSTrustStore store; private final X509CertChainValidatorExt certChainValidator; private final LocalHostnameResolver hostnameResolver; public DefaultVOMSValidationStrategy(VOMSTrustStore store, X509CertChainValidatorExt validator, LocalHostnameResolver resolver) { this.store = store; this.certChainValidator = validator; this.hostnameResolver = resolver; } public DefaultVOMSValidationStrategy(VOMSTrustStore store, X509CertChainValidatorExt validator) { this(store, validator, new DefaultLocalHostnameResolver()); } private boolean checkACHolder(VOMSAttribute attributes, X509Certificate[] chain, List validationErrors) { X500Principal chainHolder = ProxyUtils.getOriginalUserDN(chain); boolean holderDoesMatch = chainHolder.equals(attributes.getHolder()); if (!holderDoesMatch) { String acHolderSubject = X500NameUtils.getReadableForm(attributes.getHolder()); String certChainSubject = X500NameUtils.getReadableForm(chainHolder); validationErrors.add(VOMSValidationErrorMessage.newErrorMessage(acHolderDoesntMatchCertChain, acHolderSubject, certChainSubject)); } return holderDoesMatch; } private boolean checkACValidity(VOMSAttribute attributes, List validationErrors) { Date now = new Date(); boolean valid = attributes.validAt(now); if (!valid) { VOMSValidationErrorMessage m = VOMSValidationErrorMessage.newErrorMessage( acNotValidAtCurrentTime, attributes.getNotBefore(), attributes.getNotAfter(), now); validationErrors.add(m); } return valid; } private boolean checkLocalAACertSignature(VOMSAttribute attributes, List validationErrors) { X509Certificate localAACert = store.getAACertificateBySubject(attributes.getIssuer()); if (localAACert == null) { validationErrors.add(VOMSValidationErrorMessage.newErrorMessage(aaCertNotFound)); return false; } if (!validateCertificate(localAACert, validationErrors)) { validationErrors.add(VOMSValidationErrorMessage.newErrorMessage(invalidAaCert)); return false; } if (!checkAuthorityKeyIdentifier(localAACert, attributes, validationErrors)) { return false; } boolean signatureValid = verifyACSignature(attributes, localAACert); if (!signatureValid) { String readableSubject = X500NameUtils.getReadableForm(localAACert.getSubjectX500Principal()); validationErrors.add(VOMSValidationErrorMessage .newErrorMessage(aaCertFailsSignatureVerification, readableSubject)); } return signatureValid; } private boolean checkLSCSignature(VOMSAttribute attributes, List validationErrors) { LSCInfo lsc = store.getLSC(attributes.getVO(), attributes.getHost()); X509Certificate[] aaCerts = attributes.getAACertificates(); if (lsc == null) { validationErrors.add(VOMSValidationErrorMessage.newErrorMessage(lscFileNotFound)); return false; } if (aaCerts == null || aaCerts.length == 0) { validationErrors.add(VOMSValidationErrorMessage.newErrorMessage(emptyAcCertsExtension)); return false; } if (!lsc.matches(aaCerts)) { validationErrors .add(VOMSValidationErrorMessage.newErrorMessage(lscDescriptionDoesntMatchAcCert)); return false; } // LSC matches aa certs, verify certificates extracted from the AC if (!validateCertificateChain(aaCerts, validationErrors)) { validationErrors.add(VOMSValidationErrorMessage.newErrorMessage(invalidAcCert)); return false; } if (!checkAuthorityKeyIdentifier(aaCerts[0], attributes, validationErrors)) { return false; } boolean signatureValid = verifyACSignature(attributes, aaCerts[0]); if (!signatureValid) { String readableSubject = X500NameUtils.getReadableForm(aaCerts[0].getSubjectX500Principal()); validationErrors.add(VOMSValidationErrorMessage .newErrorMessage(acCertFailsSignatureVerification, readableSubject)); } return signatureValid; } private boolean checkSignature(VOMSAttribute attributes, List validationErrors) { boolean valid = checkLSCSignature(attributes, validationErrors); if (!valid) valid = checkLocalAACertSignature(attributes, validationErrors); return valid; } private boolean checkTargets(VOMSAttribute attributes, List validationErrors) { if (attributes.getTargets() == null || attributes.getTargets().size() == 0) return true; String localhostName; try { localhostName = hostnameResolver.resolveLocalHostname(); } catch (UnknownHostException e) { validationErrors .add(newErrorMessage(other, "Error resolving localhost name: " + e.getMessage())); return false; } if (!attributes.getTargets().contains(localhostName)) { validationErrors.add(newErrorMessage(localhostDoesntMatchAcTarget, localhostName, attributes.getTargets().toString())); return false; } return true; } private boolean checkNoRevAvailExtension(VOMSAttribute attributes, List validationErrors) { Extension noRevAvail = attributes.getVOMSAC().getExtension(Extension.noRevAvail); if (noRevAvail != null && noRevAvail.isCritical()) { validationErrors.add(newErrorMessage(other, "NoRevAvail AC extension cannot be critical!")); return false; } return true; } private boolean checkAuthorityKeyIdentifier(X509Certificate aaCert, VOMSAttribute attributes, List validationErrors) { AuthorityKeyIdentifier akid = AuthorityKeyIdentifier.fromExtensions(attributes.getVOMSAC().getExtensions()); try { X509CertificateHolder aaCertHolder = new JcaX509CertificateHolder(aaCert); SubjectKeyIdentifier skid = SubjectKeyIdentifier.fromExtensions(aaCertHolder.getExtensions()); boolean authKeyIdMatches = Arrays.equals(skid.getKeyIdentifier(), akid.getKeyIdentifier()); if (!authKeyIdMatches) { validationErrors.add(newErrorMessage(other, "AuthorityKeyIdentifier in the AC does not match AA certificate subject key identifier!")); return false; } return true; } catch (CertificateEncodingException e) { validationErrors.add(newErrorMessage(other, String.format("VOMS AA certificate parse error: %s", e.getMessage()))); return false; } } private boolean checkAuthorityKeyIdentifierExtension(VOMSAttribute attributes, List validationErrors) { Extension authKeyId = attributes.getVOMSAC().getExtension(Extension.authorityKeyIdentifier); if (authKeyId != null && authKeyId.isCritical()) { validationErrors .add(newErrorMessage(other, "AuthorityKeyIdentifier AC extension cannot be critical!")); return false; } // authKeyIdentifier value is checked in AC signature verification return true; } private boolean checkUnhandledCriticalExtensions(VOMSAttribute attributes, List validationErrors) { @SuppressWarnings("unchecked") List acExtensions = attributes.getVOMSAC().getExtensionOIDs(); for (ASN1ObjectIdentifier extId : acExtensions) { if (!VOMSConstants.VOMS_HANDLED_EXTENSIONS.contains(extId) && attributes.getVOMSAC().getExtension(extId).isCritical()) { validationErrors.add(newErrorMessage(other, "unknown critical extension found in VOMS AC: " + extId.getId())); return false; } } return true; } public VOMSValidationResult validateAC(VOMSAttribute attributes) { boolean valid = true; List validationErrors = new ArrayList(); // Check temporal validity valid = checkACValidity(attributes, validationErrors); if (valid) // Verify signature on AC checking LSC file or local AA certificate valid = checkSignature(attributes, validationErrors); if (valid) // Check targets valid = checkTargets(attributes, validationErrors); // AC extension checking to be compliant with rfc 3281 if (valid) valid = checkAuthorityKeyIdentifierExtension(attributes, validationErrors); if (valid) valid = checkNoRevAvailExtension(attributes, validationErrors); if (valid) valid = checkUnhandledCriticalExtensions(attributes, validationErrors); return new VOMSValidationResult(attributes, valid, validationErrors); } public VOMSValidationResult validateAC(VOMSAttribute attributes, X509Certificate[] chain) { boolean valid = true; List validationErrors = new ArrayList(); // Check temporal validity valid = checkACValidity(attributes, validationErrors); if (valid) // Verify signature on AC checking LSC file or local AA certificate valid = checkSignature(attributes, validationErrors); if (valid) // Check AC holder valid = checkACHolder(attributes, chain, validationErrors); if (valid) // Check targets valid = checkTargets(attributes, validationErrors); // AC extension checking to be compliant with rfc 3281 if (valid) valid = checkAuthorityKeyIdentifierExtension(attributes, validationErrors); if (valid) valid = checkNoRevAvailExtension(attributes, validationErrors); if (valid) valid = checkUnhandledCriticalExtensions(attributes, validationErrors); return new VOMSValidationResult(attributes, valid, validationErrors); } private boolean validateCertificate(X509Certificate c, List validationErrors) { return validateCertificateChain(new X509Certificate[] {c}, validationErrors); } private boolean validateCertificateChain(X509Certificate[] chain, List validationErrors) { ValidationResult result = certChainValidator.validate(chain); for (ValidationError e : result.getErrors()) validationErrors.add(VOMSValidationErrorMessage.newErrorMessage(canlError, e.getMessage())); return result.isValid(); } private boolean verifyACSignature(VOMSAttribute attributes, X509Certificate cert) { try { X509CertificateHolder certHolder = new JcaX509CertificateHolder(cert); ContentVerifierProvider cvp = new BcRSAContentVerifierProviderBuilder(new DefaultDigestAlgorithmIdentifierFinder()) .build(certHolder); return attributes.getVOMSAC().isSignatureValid(cvp); } catch (Exception e) { throw new VOMSError("Error verifying AC signature: " + e.getMessage(), e); } } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/ac/impl/DefaultVOMSValidator.java000066400000000000000000000125741477577347300310610ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.ac.impl; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import org.bouncycastle.asn1.x509.AttributeCertificate; import org.italiangrid.voms.VOMSAttribute; import org.italiangrid.voms.ac.VOMSACLookupStrategy; import org.italiangrid.voms.ac.VOMSACValidationStrategy; import org.italiangrid.voms.ac.VOMSACValidator; import org.italiangrid.voms.ac.VOMSValidationResult; import org.italiangrid.voms.ac.ValidationResultListener; import org.italiangrid.voms.asn1.VOMSACUtils; import org.italiangrid.voms.store.UpdatingVOMSTrustStore; import org.italiangrid.voms.store.VOMSTrustStore; import org.italiangrid.voms.store.VOMSTrustStores; import org.italiangrid.voms.util.CertificateValidatorBuilder; import org.italiangrid.voms.util.NullListener; import eu.emi.security.authn.x509.X509CertChainValidatorExt; /** * The default implementation of the VOMS validator. * * @author andreaceccanti * */ public class DefaultVOMSValidator extends DefaultVOMSACParser implements VOMSACValidator { public static final String DEFAULT_TRUST_ANCHORS_DIR = "/etc/grid-security/certificates"; private final VOMSACValidationStrategy validationStrategy; private final VOMSTrustStore trustStore; private ValidationResultListener validationResultListener; private final Object listenerLock = new Object(); public static class Builder { private VOMSACValidationStrategy validationStrategy; private VOMSTrustStore trustStore; private ValidationResultListener validationResultListener; private X509CertChainValidatorExt certChainValidator; private VOMSACLookupStrategy acLookupStrategy; public Builder() { } public Builder validationStrategy(VOMSACValidationStrategy s) { this.validationStrategy = s; return this; } public Builder trustStore(VOMSTrustStore ts) { this.trustStore = ts; return this; } public Builder validationListener(ValidationResultListener l) { this.validationResultListener = l; return this; } public Builder certChainValidator(X509CertChainValidatorExt v) { this.certChainValidator = v; return this; } public Builder acLookupStrategy(VOMSACLookupStrategy ls) { this.acLookupStrategy = ls; return this; } private void sanityChecks() { if (validationStrategy == null) { if (trustStore == null) trustStore = VOMSTrustStores.newTrustStore(); if (certChainValidator == null) certChainValidator = new CertificateValidatorBuilder() .trustAnchorsDir(DEFAULT_TRUST_ANCHORS_DIR).build(); validationStrategy = new DefaultVOMSValidationStrategy(trustStore, certChainValidator); } if (validationResultListener == null) { validationResultListener = NullListener.INSTANCE; } if (acLookupStrategy == null){ acLookupStrategy = new LeafACLookupStrategy(); } } public DefaultVOMSValidator build() { sanityChecks(); return new DefaultVOMSValidator(this); } } private DefaultVOMSValidator(Builder b) { super(b.acLookupStrategy); this.validationStrategy = b.validationStrategy; this.trustStore = b.trustStore; this.validationResultListener = b.validationResultListener; } public List validateWithResult( X509Certificate[] validatedChain) { return internalValidate(validatedChain); } protected List internalValidate( X509Certificate[] validatedChain) { List parsedAttrs = parse(validatedChain); List results = new ArrayList(); for (VOMSAttribute a : parsedAttrs) { VOMSValidationResult result = validationStrategy.validateAC(a, validatedChain); synchronized (listenerLock) { validationResultListener.notifyValidationResult(result); } results.add(result); } return results; } public List validate(X509Certificate[] validatedChain) { List validAttributes = new ArrayList(); for (VOMSValidationResult result : internalValidate(validatedChain)) { if (result.isValid()) { validAttributes.add(result.getAttributes()); } } return validAttributes; } public void shutdown() { if (trustStore instanceof UpdatingVOMSTrustStore) { ((UpdatingVOMSTrustStore) trustStore).cancel(); } } public List validateACs(List acs) { List validatedAcs = new ArrayList(); for (AttributeCertificate ac : acs) { VOMSAttribute vomsAttrs = VOMSACUtils.deserializeVOMSAttributes(ac); VOMSValidationResult result = validationStrategy.validateAC(vomsAttrs); synchronized (listenerLock) { validationResultListener.notifyValidationResult(result); } if (result.isValid()) { validatedAcs.add(ac); } } return validatedAcs; } public void setValidationResultListener(ValidationResultListener listener) { synchronized (listenerLock) { if (listener != null) { this.validationResultListener = listener; } } } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/ac/impl/LeafACLookupStrategy.java000066400000000000000000000044361477577347300311100ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.ac.impl; import java.io.IOException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import org.bouncycastle.asn1.x509.AttributeCertificate; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.ac.ACLookupListener; import org.italiangrid.voms.ac.ACParsingContext; import org.italiangrid.voms.ac.VOMSACLookupStrategy; import org.italiangrid.voms.asn1.VOMSACUtils; import org.italiangrid.voms.asn1.VOMSConstants; import org.italiangrid.voms.util.NullListener; import eu.emi.security.authn.x509.proxy.ProxyUtils; /** * This strategy returns the leaf VOMS Attribute Certificate in a certificate * chain, i.e. the Attribute Certificate found in the latest delegation in the * chain. * * @author Andrea Ceccanti * */ public class LeafACLookupStrategy implements VOMSACLookupStrategy, VOMSConstants { private ACLookupListener listener; public LeafACLookupStrategy(ACLookupListener l) { this.listener = l; } public LeafACLookupStrategy() { this(NullListener.INSTANCE); } public List lookupVOMSAttributeCertificates( X509Certificate[] certChain) { List parsedACs = new ArrayList(); if (certChain == null || certChain.length == 0) throw new VOMSError( "Cannot extract VOMS Attribute Certificates from a null or empty certificate chain!"); for (int index = 0; index < certChain.length; index++) { X509Certificate cert = certChain[index]; listener.notifyACLookupEvent(certChain, index); try { if (ProxyUtils.isProxy(cert)) { List vomsACs = VOMSACUtils .getACsFromCertificate(cert); // Break at the first AC found from the top of the chain if (!vomsACs.isEmpty()) { listener.notifyACParseEvent(certChain, index); ACParsingContext ctx = new ACParsingContext(vomsACs, index, certChain); parsedACs.add(ctx); break; } } } catch (IOException e) { throw new VOMSError(e.getMessage(), e); } } return parsedACs; } } LeafVOMSExtensionNormalizationStrategy.java000066400000000000000000000021031477577347300345710ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/ac/impl// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.ac.impl; import java.util.Collections; import java.util.List; import org.bouncycastle.asn1.x509.AttributeCertificate; import org.italiangrid.voms.VOMSAttribute; import org.italiangrid.voms.ac.ACParsingContext; import org.italiangrid.voms.ac.VOMSAttributesNormalizationStrategy; import org.italiangrid.voms.asn1.VOMSACUtils; import org.italiangrid.voms.asn1.VOMSConstants; /** * * This strategy extracts the VOMS attributes from the top VOMS extension found * in the parsing context passed as argument. * * @author Andrea Ceccanti * */ public class LeafVOMSExtensionNormalizationStrategy implements VOMSAttributesNormalizationStrategy, VOMSConstants { public List normalizeAttributes(List acs) { if (acs == null || acs.isEmpty()) return Collections.emptyList(); List attrs = acs.get(0).getACs(); return VOMSACUtils.deserializeVOMSAttributes(attrs); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/ac/impl/LocalHostnameResolver.java000066400000000000000000000011221477577347300313600ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.ac.impl; import java.net.UnknownHostException; /** * A {@link LocalHostnameResolver} resolves the localhost host name. * */ public interface LocalHostnameResolver { /** * Resolves the hostname for localhost * * @return a String containing the localhost hostname * @throws UnknownHostException * when there is an error resolving the hostname */ public String resolveLocalHostname() throws UnknownHostException; } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/ac/impl/VOMSAttributesImpl.java000066400000000000000000000077421477577347300306000ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.ac.impl; import java.math.BigInteger; import java.security.cert.X509Certificate; import java.util.Date; import java.util.List; import javax.security.auth.x500.X500Principal; import org.bouncycastle.cert.X509AttributeCertificateHolder; import org.italiangrid.voms.VOMSAttribute; import org.italiangrid.voms.VOMSGenericAttribute; import org.italiangrid.voms.util.TimeUtils; import eu.emi.security.authn.x509.impl.X500NameUtils; /** * The default implementation for voms attributes * * @author andreaceccanti * */ public class VOMSAttributesImpl implements VOMSAttribute { public static final int DEFAULT_CLOCK_SKEW_IN_MINUTES = 5; private String VO; private String host; private int port; private List FQANs; private X500Principal issuer; private X500Principal holder; private BigInteger holderSerialNumber; private Date notAfter; private Date notBefore; private byte[] signature; private List genericAttributes; private List acTargets; private X509Certificate[] aaCerts; private X509AttributeCertificateHolder VOMSAC; public VOMSAttributesImpl() { } public X500Principal getIssuer() { return issuer; } public String getPrimaryFQAN() { return FQANs.get(0); } public String getVO() { return VO; } public void setIssuer(X500Principal issuer) { this.issuer = issuer; } public void setVO(String vO) { VO = vO; } public List getFQANs() { return FQANs; } public void setFQANs(List fQANs) { FQANs = fQANs; } public String getHost() { return host; } public int getPort() { return port; } public X500Principal getHolder() { return holder; } public Date getNotBefore() { return notBefore; } public Date getNotAfter() { return notAfter; } public byte[] getSignature() { return signature; } public void setHost(String host) { this.host = host; } public void setPort(int port) { this.port = port; } public void setHolder(X500Principal holder) { this.holder = holder; } public void setNotAfter(Date notAfter) { this.notAfter = notAfter; } public void setNotBefore(Date notBefore) { this.notBefore = notBefore; } public void setSignature(byte[] signature) { this.signature = signature; } @Override public String toString() { return "VOMSAttributesImpl [VO=" + VO + ", host=" + host + ", port=" + port + ", FQANs=" + FQANs + ", gas=" + genericAttributes + ", issuer='" + X500NameUtils.getReadableForm(issuer) + "', holder='" + X500NameUtils.getReadableForm(holder) + "', notAfter=" + notAfter + ", notBefore=" + notBefore + ", targets=" + acTargets + " ]"; } public List getGenericAttributes() { return genericAttributes; } public void setGenericAttributes(List genericAttributes) { this.genericAttributes = genericAttributes; } public List getTargets() { return acTargets; } public void setTargets(List targets) { acTargets = targets; } public X509Certificate[] getAACertificates() { return aaCerts; } public void setAACertificates(X509Certificate[] aaCerts) { this.aaCerts = aaCerts; } public boolean isValid() { return validAt(new Date()); } public boolean validAt(Date date) { return TimeUtils.checkTimeInRangeWithSkew(date, getNotBefore(), getNotAfter(), DEFAULT_CLOCK_SKEW_IN_MINUTES); } public X509AttributeCertificateHolder getVOMSAC() { return VOMSAC; } public void setVOMSAC(X509AttributeCertificateHolder ac) { VOMSAC = ac; } public BigInteger getHolderSerialNumber() { return holderSerialNumber; } public void setHolderSerialNumber(BigInteger holderSerialNumber) { this.holderSerialNumber = holderSerialNumber; } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/ac/impl/VOMSGenericAttributeImpl.java000066400000000000000000000040111477577347300316740ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.ac.impl; import org.italiangrid.voms.VOMSGenericAttribute; /** * The default implementation for VOMS Generic Attributes. * * @author Andrea Ceccanti * */ public class VOMSGenericAttributeImpl implements VOMSGenericAttribute { private String name; private String value; private String context; public VOMSGenericAttributeImpl() { } public String getName() { return name; } public String getValue() { return value; } public String getContext() { return context; } public void setName(String name) { this.name = name; } public void setValue(String value) { this.value = value; } public void setContext(String context) { this.context = context; } @Override public String toString() { return "VOMSGenericAttribute [name=" + name + ", value=" + value + ", context=" + context + "]"; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((context == null) ? 0 : context.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((value == null) ? 0 : value.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; VOMSGenericAttributeImpl other = (VOMSGenericAttributeImpl) obj; if (context == null) { if (other.context != null) return false; } else if (!context.equals(other.context)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (value == null) { if (other.value != null) return false; } else if (!value.equals(other.value)) return false; return true; } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/ac/impl/package-info.java000066400000000000000000000003461477577347300274400ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 /** * Implementation classes for VOMS attributes validation and parsing. */ package org.italiangrid.voms.ac.impl; voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/ac/package-info.java000066400000000000000000000003661477577347300265010ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 /** * This package provides the APIs to perform validation and parsing * of VOMS attributes. */ package org.italiangrid.voms.ac; voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/asn1/000077500000000000000000000000001477577347300235645ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/asn1/VOMSACGenerator.java000066400000000000000000000415721477577347300272770ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.asn1; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.math.BigInteger; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.util.Date; import java.util.EnumSet; import java.util.List; import java.util.Random; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1Object; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERTaggedObject; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier; import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.asn1.x509.GeneralNames; import org.bouncycastle.cert.AttributeCertificateHolder; import org.bouncycastle.cert.AttributeCertificateIssuer; import org.bouncycastle.cert.CertIOException; import org.bouncycastle.cert.X509AttributeCertificateHolder; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.X509v2AttributeCertificateBuilder; import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder; import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.operator.ContentSigner; import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder; import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.VOMSGenericAttribute; import eu.emi.security.authn.x509.X509Credential; import eu.emi.security.authn.x509.proxy.CertificateExtension; /** * A generator for VOMS Attribute Certificates (ACs). *

* This class provides methods for creating VOMS ACs with customizable properties, including * optional extensions and fake signature bits for testing purposes. *

* *

* It uses BouncyCastle for cryptographic operations and supports various extensions required for * VOMS attribute certificates. *

* */ public class VOMSACGenerator implements VOMSConstants { /** * Enumeration defining various properties that can influence the generation of VOMS Attribute * Certificates. */ public enum ACGenerationProperties { // @formatting off /** * Skips the inclusion of the AC Certs extension in the generated Attribute Certificate. *

* This extension normally contains the issuer's certificate chain, which may be omitted * if the relying party already possesses it. *

*/ SKIP_AC_CERTS_EXTENSION, /** * Generates fake signature bits instead of signing the certificate with a real key. *

* This is primarily used for testing purposes, as the resulting AC will not be verifiable. *

*/ FAKE_SIGNATURE_BITS, /** * Includes a fake critical extension in the generated Attribute Certificate. *

* This extension is added for testing scenarios where certificate parsers need to handle * unknown critical extensions. *

*/ INCLUDE_FAKE_CRITICAL_EXTENSION, /** * Includes the "No Revocation Available" extension as a critical extension. *

* This extension indicates that no revocation information is available for the AC. *

*/ INCLUDE_CRITICAL_NO_REV_AVAIL_EXTENSION, /** * Includes the Authority Key Identifier (AKID) extension as a critical extension. *

* The AKID extension helps in linking the AC to its issuer, making it easier for * verification systems to locate the issuing certificate. *

*/ INCLUDE_CRITICAL_AKID_EXTENSION, /** * Includes an empty AC Certs extension in the generated Attribute Certificate. *

* This is useful for testing scenarios where the extension is expected but contains no * actual certificate information. *

*/ INCLUDE_EMPTY_AC_CERTS_EXTENSION; // @formatting on } /** Default generation properties (none enabled). */ public static final EnumSet defaultGenerationProperties = EnumSet.noneOf(ACGenerationProperties.class); /** * A ContentSigner implementation that generates random signature bits. *

* This is used for testing purposes to create attribute certificates with fake signatures. *

*/ static class RandomContentSigner implements ContentSigner { /** The length of the randomly generated signature. */ public static final int SIG_LENGHT = 1024; ByteArrayOutputStream bos = new ByteArrayOutputStream(); AlgorithmIdentifier sigAlgId; /** * Constructs a RandomContentSigner with the given signature algorithm name. * * @param sigAlgName the name of the signature algorithm */ public RandomContentSigner(String sigAlgName) { this.sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find(sigAlgName); } @Override public AlgorithmIdentifier getAlgorithmIdentifier() { return sigAlgId; } @Override public OutputStream getOutputStream() { return bos; } @Override public byte[] getSignature() { try { bos.close(); } catch (IOException e) { // Ignore } Random r = new Random(); byte[] sigBytes = new byte[SIG_LENGHT]; r.nextBytes(sigBytes); return sigBytes; } } /** Fake extension OID used in testing. */ public static final ASN1ObjectIdentifier FAKE_EXT_OID = new ASN1ObjectIdentifier("1.3.6.1.4.1.8005.100.120.82"); private X509Credential aaCredential; private ContentSigner signer; /** * Retrieves the appropriate ContentSigner based on the provided properties. * * @param properties the properties influencing AC generation * @return a ContentSigner instance * @throws VOMSError if an error occurs during signer creation */ private ContentSigner getSigner(EnumSet properties) { if (signer == null) { JcaContentSignerBuilder builder = new JcaContentSignerBuilder(aaCredential.getCertificate().getSigAlgName()); builder.setProvider(BouncyCastleProvider.PROVIDER_NAME); try { if (properties.contains(ACGenerationProperties.FAKE_SIGNATURE_BITS)) { signer = new RandomContentSigner(aaCredential.getCertificate().getSigAlgName()); } else { signer = builder.build(aaCredential.getKey()); } } catch (OperatorCreationException e) { throw new VOMSError(e.getMessage(), e); } } return signer; } /** * Constructs a VOMSACGenerator with the given credential. * * @param aaCredential the attribute authority credential */ public VOMSACGenerator(X509Credential aaCredential) { this.aaCredential = aaCredential; } /** * Builds a VOMS URI. * * @param voName the VO name * @param host the host name * @param port the port number * @return a formatted VOMS URI */ private String buildVOURI(String voName, String host, int port) { return String.format("%s://%s:%d", voName, host, port); } private ASN1Encodable buildACCertsExtensionContent(EnumSet properties) { ASN1EncodableVector issuerCertsContainer = new ASN1EncodableVector(); if (properties.contains(ACGenerationProperties.INCLUDE_EMPTY_AC_CERTS_EXTENSION)) issuerCertsContainer.add(new DERSequence()); else issuerCertsContainer .add(new DERSequence(getCertAsDEREncodable(aaCredential.getCertificate()))); return new DERSequence(issuerCertsContainer); } private AuthorityKeyIdentifier buildAuthorityKeyIdentifier() throws CertificateEncodingException, NoSuchAlgorithmException { X509CertificateHolder holder = new JcaX509CertificateHolder(aaCredential.getCertificate()); JcaX509ExtensionUtils utils = new JcaX509ExtensionUtils(); return utils.createAuthorityKeyIdentifier(holder.getSubjectPublicKeyInfo()); } private ASN1Encodable buildFQANsAttributeContent(List fqans, GeneralName policyAuthorityInfo) { ASN1EncodableVector container = new ASN1EncodableVector(); ASN1EncodableVector encodedFQANs = new ASN1EncodableVector(); container.add(new GeneralNames(policyAuthorityInfo)); for (String s : fqans) encodedFQANs.add(new DEROctetString(s.getBytes())); container.add(new DERSequence(encodedFQANs)); return new DERSequence(container); } private ASN1Encodable buildGAExtensionContent(EnumSet properties, List gas, GeneralName policyAuthorityInfo) { ASN1EncodableVector tagContainer = new ASN1EncodableVector(); ASN1EncodableVector tagSequences = new ASN1EncodableVector(); for (VOMSGenericAttribute a : gas) { tagSequences.add(buildTagSequence(a)); } tagContainer.add(new GeneralNames(policyAuthorityInfo)); tagContainer.add(new DERSequence(tagSequences)); DERSequence finalSequence; // We wrap this three times as VOMS core does, even if I think this // is a bug finalSequence = new DERSequence(new DERSequence(new DERSequence(tagContainer))); return finalSequence; } private AttributeCertificateHolder buildHolder(X509Certificate holderCert) throws CertificateEncodingException { JcaX509CertificateHolder holderWrappedCert = new JcaX509CertificateHolder(holderCert); return new AttributeCertificateHolder(holderWrappedCert.getSubject(), holderCert.getSerialNumber()); } private AttributeCertificateIssuer buildIssuer() throws CertificateEncodingException { JcaX509CertificateHolder issuer = new JcaX509CertificateHolder(aaCredential.getCertificate()); return new AttributeCertificateIssuer(issuer.getSubject()); } private GeneralName buildPolicyAuthorityInfo(String voName, String host, int port) { return new GeneralName(GeneralName.uniformResourceIdentifier, buildVOURI(voName, host, port)); } private DERSequence buildTagSequence(VOMSGenericAttribute ga) { ASN1EncodableVector tagSequence = new ASN1EncodableVector(); tagSequence.add(getDEROctetString(ga.getName())); tagSequence.add(getDEROctetString(ga.getValue())); tagSequence.add(getDEROctetString(ga.getContext())); return new DERSequence(tagSequence); } private ASN1Encodable buildTargetsExtensionContent(EnumSet properties, List targets) { ASN1EncodableVector targetSeq = new ASN1EncodableVector(); for (String s : targets) { DERTaggedObject encodedTarget = new DERTaggedObject(0, new GeneralName(GeneralName.uniformResourceIdentifier, s)); // We wrap the target in another sequence as the old VOMS does targetSeq.add(new DERSequence(encodedTarget)); } DERSequence targetExtensionContent = new DERSequence(new DERSequence(targetSeq)); return targetExtensionContent; } /** * Generates a VOMS attribute certificate with the given properties. * * @param fqans the list of Fully Qualified Attribute Names (FQANs) * @param gas the list of generic attributes * @param targets the list of target restrictions * @param holderCert the X.509 certificate of the holder * @param serialNumber the serial number of the AC * @param notBefore the start of the AC validity period * @param notAfter the end of the AC validity period * @param voName the VO name * @param host the VOMS server hostname * @param port the VOMS server port * @return the generated X.509 attribute certificate * @throws VOMSError if certificate generation fails */ public X509AttributeCertificateHolder generateVOMSAttributeCertificate(List fqans, List gas, List targets, X509Certificate holderCert, BigInteger serialNumber, Date notBefore, Date notAfter, String voName, String host, int port) throws VOMSError { return generateVOMSAttributeCertificate(defaultGenerationProperties, fqans, gas, targets, holderCert, serialNumber, notBefore, notAfter, voName, host, port); } /** * Generates a VOMS attribute certificate with the specified properties. * * @param generationProperties the properties influencing AC generation * @param fqans the list of Fully Qualified Attribute Names (FQANs) * @param gas the list of generic attributes * @param targets the list of target restrictions * @param holderCert the X.509 certificate of the holder * @param serialNumber the serial number of the AC * @param notBefore the start of the AC validity period * @param notAfter the end of the AC validity period * @param voName the VO name * @param host the VOMS server hostname * @param port the VOMS server port * @return the generated X.509 attribute certificate * @throws VOMSError if certificate generation fails */ public X509AttributeCertificateHolder generateVOMSAttributeCertificate( EnumSet generationProperties, List fqans, List gas, List targets, X509Certificate holderCert, BigInteger serialNumber, Date notBefore, Date notAfter, String voName, String host, int port) throws VOMSError { AttributeCertificateHolder holder = null; AttributeCertificateIssuer issuer = null; try { holder = buildHolder(holderCert); issuer = buildIssuer(); X509v2AttributeCertificateBuilder builder = new X509v2AttributeCertificateBuilder(holder, issuer, serialNumber, notBefore, notAfter); GeneralName policyAuthorityInfo = buildPolicyAuthorityInfo(voName, host, port); builder.addAttribute(VOMS_FQANS_OID, buildFQANsAttributeContent(fqans, policyAuthorityInfo)); if (gas != null && !gas.isEmpty()) { builder.addExtension(VOMS_GENERIC_ATTRS_OID, false, buildGAExtensionContent(generationProperties, gas, policyAuthorityInfo)); } if (targets != null && !targets.isEmpty()) { builder.addExtension(Extension.targetInformation, true, buildTargetsExtensionContent(generationProperties, targets)); } if (!generationProperties.contains(ACGenerationProperties.SKIP_AC_CERTS_EXTENSION)) { builder.addExtension(VOMS_CERTS_OID, false, buildACCertsExtensionContent(generationProperties)); } if (generationProperties.contains(ACGenerationProperties.INCLUDE_FAKE_CRITICAL_EXTENSION)) { builder.addExtension(FAKE_EXT_OID, true, new DERSequence()); } boolean noRevAvailIsCritical = false; boolean akidIsCritical = false; if (generationProperties .contains(ACGenerationProperties.INCLUDE_CRITICAL_NO_REV_AVAIL_EXTENSION)) { noRevAvailIsCritical = true; } if (generationProperties.contains(ACGenerationProperties.INCLUDE_CRITICAL_AKID_EXTENSION)) { akidIsCritical = true; } builder.addExtension(Extension.noRevAvail, noRevAvailIsCritical, DERNull.INSTANCE); AuthorityKeyIdentifier akid = buildAuthorityKeyIdentifier(); builder.addExtension(Extension.authorityKeyIdentifier, akidIsCritical, akid != null ? akid : DERNull.INSTANCE); return builder.build(getSigner(generationProperties)); } catch (CertificateEncodingException | CertIOException | NoSuchAlgorithmException e) { throw new VOMSError(e.getMessage(), e); } } /** * Generates a VOMS certificate extension. * * @param acs the list of X.509 attribute certificates * @return the generated certificate extension */ public CertificateExtension generateVOMSExtension(List acs) { ASN1EncodableVector vomsACs = new ASN1EncodableVector(); for (X509AttributeCertificateHolder ac : acs) { vomsACs.add(ac.toASN1Structure()); } DERSequence acSeq = new DERSequence(vomsACs); return new CertificateExtension(VOMS_EXTENSION_OID.getId(), acSeq.toASN1Primitive(), false); } private ASN1Encodable getCertAsDEREncodable(X509Certificate cert) { try { byte[] certBytes = cert.getEncoded(); ByteArrayInputStream bais = new ByteArrayInputStream(certBytes); ASN1InputStream is = new ASN1InputStream(bais); ASN1Object derCert = is.readObject(); is.close(); return derCert; } catch (CertificateEncodingException | IOException e) { throw new VOMSError("Error encoding X509 certificate: " + e.getMessage(), e); } } private DEROctetString getDEROctetString(String s) { return new DEROctetString(s.getBytes()); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/asn1/VOMSACUtils.java000066400000000000000000000356301477577347300264470ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.asn1; import java.io.ByteArrayInputStream; import java.io.IOException; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.List; import javax.security.auth.x500.X500Principal; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERIA5String; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DLSequence; import org.bouncycastle.asn1.x509.Attribute; import org.bouncycastle.asn1.x509.AttributeCertificate; import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.asn1.x509.IetfAttrSyntax; import org.bouncycastle.asn1.x509.Target; import org.bouncycastle.asn1.x509.TargetInformation; import org.bouncycastle.asn1.x509.Targets; import org.bouncycastle.cert.X509AttributeCertificateHolder; import org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory; import org.italiangrid.voms.VOMSAttribute; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.VOMSGenericAttribute; import org.italiangrid.voms.ac.impl.VOMSAttributesImpl; import org.italiangrid.voms.ac.impl.VOMSGenericAttributeImpl; /** * A set of VOMS AC handling utilities. * * @author Andrea Ceccanti * */ public class VOMSACUtils implements VOMSConstants { public static final String POLICY_AUTHORITY_SEP = "://"; /** * Returns the VOMS extension, if present, in a given certificate * * @param cert * the {@link X509Certificate} where the extension will be searched * @return the DER-encoded octet string of the extension value or null if it * is not present. */ public static byte[] getVOMSExtensionFromCertificate(X509Certificate cert) { return cert.getExtensionValue(VOMSConstants.VOMS_EXTENSION_OID.getId()); } /** * Deserializes the VOMS Attribute certificates in a given certificate * extension * * @param vomsExtension * the VOMS extension * @return the possibly empty {@link List} of {@link AttributeCertificate} * extracted from a given extension * @throws IOException * in case of deserialization errors */ public static List getACsFromVOMSExtension( byte[] vomsExtension) throws IOException { List acs = null; if (vomsExtension == null) return Collections.emptyList(); acs = new ArrayList(); // Convert extension to a DEROctetString ASN1InputStream asn1Stream = new ASN1InputStream(new ByteArrayInputStream( vomsExtension)); byte[] payload = ((DEROctetString) asn1Stream.readObject()).getOctets(); asn1Stream.close(); asn1Stream = new ASN1InputStream(new ByteArrayInputStream(payload)); // VOMS extension is SEQUENCE of SET of AttributeCertificate // now, SET is an ordered sequence, and an AC is a sequence as // well -- thus the three nested ASN.1 sequences below... ASN1Sequence baseSequence = (ASN1Sequence) asn1Stream.readObject(); asn1Stream.close(); @SuppressWarnings("unchecked") Enumeration setSequence = baseSequence.getObjects(); while (setSequence.hasMoreElements()) { ASN1Sequence acSequence = setSequence.nextElement(); @SuppressWarnings("unchecked") Enumeration theACs = acSequence.getObjects(); while (theACs.hasMoreElements()) { AttributeCertificate parsedAC = AttributeCertificate.getInstance(theACs.nextElement()); acs.add(parsedAC); } } return acs; } /** * Deserializes the VOMS Attribute certificates, if present, in a given * certificate passed as argument * * @param cert * the {@link X509Certificate} where the ACs will be searched * @return the possibly empty {@link List} of {@link AttributeCertificate} * objects extracted from the VOMS extension * @throws IOException * in case of deserialization errors */ public static List getACsFromCertificate( X509Certificate cert) throws IOException { return getACsFromVOMSExtension(getVOMSExtensionFromCertificate(cert)); } /** * Deserializes the FQANs contained in a {@link IetfAttrSyntax} object * * @param attr * the {@link IetfAttrSyntax} attribute syntax object containing the * VOMS extension * @return a {@link List} of FQANs */ private static List deserializeFQANs(IetfAttrSyntax attr) { if (attr.getValueType() != IetfAttrSyntax.VALUE_OCTETS) raiseACNonConformantError("unsupported attribute values encoding."); List fqans = new ArrayList(); ASN1OctetString[] values = (ASN1OctetString[]) attr.getValues(); for (ASN1OctetString s : values) fqans.add(new String(s.getOctets())); return fqans; } @SuppressWarnings("rawtypes") private static List deserializeACTargets( X509AttributeCertificateHolder ac) { List targets = new ArrayList(); Extension targetExtension = ac.getExtension(Extension.targetInformation); if (targetExtension == null) return targets; TargetInformation ti = TargetInformation .getInstance((ASN1Sequence) targetExtension.getParsedValue()); // Only one Targets according to RFC 3281 Targets asn1TargetContainer = ti.getTargetsObjects()[0]; // The deserialization has to be done by hand since it seems VOMS // does not correctly encode the ACTargets extension... ASN1Sequence targetSequence = (ASN1Sequence) asn1TargetContainer .toASN1Primitive(); Target[] asn1Targets = new Target[targetSequence.size()]; int count = 0; for (Enumeration e = targetSequence.getObjects(); e.hasMoreElements();) { // There's one sequence more than expected here that makes // the bc constructor fail... ASN1Sequence seq = (ASN1Sequence) e.nextElement(); ASN1TaggedObject val = (ASN1TaggedObject) seq.getObjectAt(0); asn1Targets[count++] = Target.getInstance(val); } // Extract the actual string for (Target t : asn1Targets) { GeneralName targetURI = t.getTargetName(); if (targetURI.getTagNo() != GeneralName.uniformResourceIdentifier) raiseACNonConformantError("wrong AC target extension encoding. Only URI targets are supported."); String targetString = ((DERIA5String) targetURI.getName()).getString(); targets.add(targetString); } return targets; } private static void raiseACNonConformantError(String errorString) { throw new VOMSError("Non conformant VOMS Attribute certificate: " + errorString); } /** * Peforms some sanity checks on the format of the policy authority field * found in a VOMS extension. The enforced format is: vo://host:port * * @param attr * the {@link IetfAttrSyntax} attribute syntax object containing the * VOMS extension * @return the validated policy authority as a {@link String} */ private static String policyAuthoritySanityChecks(IetfAttrSyntax attr) { // The policy authority value is encoded as a DERIA5String String policyAuthority = ((DERIA5String) attr.getPolicyAuthority() .getNames()[0].getName()).getString(); // PolicyAuthority scheme: ://: int index = policyAuthority.indexOf(POLICY_AUTHORITY_SEP); if ((index < 0) || (index == policyAuthority.length() - 1)) raiseACNonConformantError("unsupported policy authority encoding '" + policyAuthority + "'"); return policyAuthority; } /** * Deserializes the information in a list of VOMS attribute certificates. * * @param acs * a {@link List} of VOMS acs * @return a possibly empty list of {@link VOMSAttribute} */ public static List deserializeVOMSAttributes( List acs) { if (acs == null || acs.size() == 0) return Collections.emptyList(); List attributes = new ArrayList(); for (AttributeCertificate a : acs) { attributes.add(deserializeVOMSAttributes(a)); } return attributes; } /** * Deserializes the information in a VOMS attribute certificate. * * @param ac * a VOMS {@link AttributeCertificate} * @return a {@link VOMSAttribute} object which provides more convenient * access to the VOMS authorization information */ public static VOMSAttribute deserializeVOMSAttributes(AttributeCertificate ac) { VOMSAttributesImpl attrs = new VOMSAttributesImpl(); X509AttributeCertificateHolder acHolder = new X509AttributeCertificateHolder( ac); Attribute[] asn1Attrs = acHolder.getAttributes(VOMS_FQANS_OID); for (Attribute a : asn1Attrs) { ASN1Primitive theVOMSDerObject = a.getAttributeValues()[0] .toASN1Primitive(); IetfAttrSyntax attrSyntax = IetfAttrSyntax.getInstance(ASN1Sequence .getInstance(theVOMSDerObject)); String policyAuthority = policyAuthoritySanityChecks(attrSyntax); // The policy authority string has the following format: // ://: attrs.setVO(policyAuthority.substring(0, policyAuthority.indexOf(POLICY_AUTHORITY_SEP))); attrs.setHost(policyAuthority.substring( policyAuthority.indexOf(POLICY_AUTHORITY_SEP) + 3, policyAuthority.lastIndexOf(":"))); attrs.setPort(Integer.parseInt(policyAuthority.substring(policyAuthority .lastIndexOf(":") + 1))); attrs.setFQANs(deserializeFQANs(attrSyntax)); attrs.setNotBefore(acHolder.getNotBefore()); attrs.setNotAfter(acHolder.getNotAfter()); attrs.setSignature(acHolder.getSignature()); attrs.setGenericAttributes(deserializeGAs(acHolder)); attrs.setAACertificates(deserializeACCerts(acHolder)); attrs.setTargets(deserializeACTargets(acHolder)); attrs.setVOMSAC(acHolder); try { attrs.setIssuer(new X500Principal(acHolder.getIssuer().getNames()[0] .getEncoded())); attrs.setHolder(new X500Principal(acHolder.getHolder().getIssuer()[0] .getEncoded())); attrs.setHolderSerialNumber(acHolder.getHolder().getSerialNumber()); } catch (IOException e) { throw new VOMSError( "Error parsing attribute certificate issuer or holder name: " + e.getMessage(), e); } } return attrs; } /** * Deserializes the VOMS generic attributes * * @param ac * the VOMS {@link X509AttributeCertificateHolder} * @return the {@link List} of {@link VOMSGenericAttribute} contained in the * ac */ private static List deserializeGAs( X509AttributeCertificateHolder ac) { List gas = new ArrayList(); Extension gasExtension = ac.getExtension(VOMS_GENERIC_ATTRS_OID); if (gasExtension == null) return gas; // SEQUENCE of TagList - contains just one taglist element ASN1Sequence tagContainerSeq = (ASN1Sequence) gasExtension.getParsedValue(); if (tagContainerSeq.size() != 1) raiseACNonConformantError("unsupported generic attributes container format."); // TagList - this also should be a sigle element sequence ASN1Sequence tagListSeq = (ASN1Sequence) tagContainerSeq.getObjectAt(0); if (tagListSeq.size() > 1) raiseACNonConformantError("unsupported taglist format."); // This TagList sequence is empty, gLite 3.2 VOMS versions had a bug // that added the extension even there were no attributes encoded... if (tagListSeq.size() == 0) return gas; // Down one level tagListSeq = (ASN1Sequence) tagListSeq.getObjectAt(0); // TODO: check policyAuthority!! // GeneralNames policyAuthority = // GeneralNames.getInstance(tagListSeq.getObjectAt(0)); // tags SEQUENCE OF Tag ASN1Sequence tags = (ASN1Sequence) tagListSeq.getObjectAt(1); @SuppressWarnings("unchecked") Enumeration e = tags.getObjects(); while (e.hasMoreElements()) { ASN1Sequence theActualTag = e.nextElement(); if (theActualTag.size() != 3) raiseACNonConformantError("unsupported tag format."); VOMSGenericAttributeImpl attribute = new VOMSGenericAttributeImpl(); attribute.setName(new String(DEROctetString.getInstance( theActualTag.getObjectAt(0)).getOctets())); attribute.setValue(new String(DEROctetString.getInstance( theActualTag.getObjectAt(1)).getOctets())); attribute.setContext(new String(DEROctetString.getInstance( theActualTag.getObjectAt(2)).getOctets())); gas.add(attribute); } return gas; } /** * Deserializes the VOMS ACCerts extension * * @param ac * the VOMS {@link X509AttributeCertificateHolder} * @return the parsed array of {@link X509Certificate} */ private static X509Certificate[] deserializeACCerts( X509AttributeCertificateHolder ac) { List certs = new ArrayList(); Extension e = ac.getExtension(VOMS_CERTS_OID); if (e == null) { return null; } ASN1Sequence certSeq = (ASN1Sequence) e.getParsedValue(); if (certSeq.size() != 1) { raiseACNonConformantError("unsupported accerts format."); } // Down one level certSeq = (ASN1Sequence) certSeq.getObjectAt(0); @SuppressWarnings("unchecked") Enumeration encodedCerts = certSeq.getObjects(); CertificateFactory cf = new CertificateFactory(); while (encodedCerts.hasMoreElements()) { DLSequence s = encodedCerts.nextElement(); X509Certificate theCert; try { ASN1InputStream stream = new ASN1InputStream(s.getEncoded()); theCert = (X509Certificate) cf.engineGenerateCertificate(stream); } catch (CertificateParsingException ex) { throw new VOMSError("Certificate parsing error: " + ex.getMessage(), ex); } catch (CertificateEncodingException ex) { throw new VOMSError("Certificate encoding error: " + ex.getMessage(), ex); } catch (CertificateException ex) { throw new VOMSError("Error generating certificate from parsed data: " + ex.getMessage(), ex); } catch (IOException ex) { throw new VOMSError("Certficate parsing error : "+ex.getMessage(), ex); } certs.add(theCert); } return certs.toArray(new X509Certificate[certs.size()]); } private VOMSACUtils() { } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/asn1/VOMSConstants.java000066400000000000000000000026231477577347300271130ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.asn1; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.x509.Extension; /** * A set of useful constants for ASN.1 parsing of VOMS attributes. * * @author Andrea Ceccanti * */ public interface VOMSConstants { /** * The VOMS attribute certificate extension OID. */ public final ASN1ObjectIdentifier VOMS_EXTENSION_OID = new ASN1ObjectIdentifier( "1.3.6.1.4.1.8005.100.100.5"); /** * The VOMS attributes OID. */ public final ASN1ObjectIdentifier VOMS_FQANS_OID = new ASN1ObjectIdentifier( "1.3.6.1.4.1.8005.100.100.4"); /** * The VOMS Certs extension OID. */ public final ASN1ObjectIdentifier VOMS_CERTS_OID = new ASN1ObjectIdentifier( "1.3.6.1.4.1.8005.100.100.10"); /** * The VOMS Generic attributes extension OID. */ public final ASN1ObjectIdentifier VOMS_GENERIC_ATTRS_OID = new ASN1ObjectIdentifier( "1.3.6.1.4.1.8005.100.100.11"); public final Set VOMS_HANDLED_EXTENSIONS = new HashSet( Arrays.asList(VOMS_FQANS_OID, VOMS_CERTS_OID, VOMS_GENERIC_ATTRS_OID, Extension.targetInformation, Extension.noRevAvail, Extension.authorityKeyIdentifier)); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/asn1/package-info.java000066400000000000000000000004471477577347300267600ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 /** * This package provides classes and utilities that deal with serialization and * deserialization of VOMS attributes from ASN.1 streams. */ package org.italiangrid.voms.asn1; voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/credential/000077500000000000000000000000001477577347300250345ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/credential/FilePermissionError.java000066400000000000000000000011431477577347300316400ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.credential; import org.italiangrid.voms.VOMSError; /** * This error is raised when there is an attempt to load a credential which has * the wrong file permissions * */ public class FilePermissionError extends VOMSError { public FilePermissionError(String message) { super(message); } public FilePermissionError(String message, Throwable cause) { super(message, cause); } /** * */ private static final long serialVersionUID = 1L; } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/credential/LoadCredentialsEventListener.java000066400000000000000000000025041477577347300334450ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.credential; /** * A {@link LoadCredentialsEventListener} is notified of the outcome of load * credentials operations. * * @author andreaceccanti * */ public interface LoadCredentialsEventListener { /** * Informs that credentials are been looked for in the locations passed as * argument. * * @param locations * the locations (as strings) where the credentials * are being searched */ public void notifyCredentialLookup(String... locations); /** * Informs that credentials have been succesfully loaded from the credentials * passed as argument. * * @param locations * the locations (as strings) where the credentials * are being searched */ public void notifyLoadCredentialSuccess(String... locations); /** * Informs that credentials could not be loaded form the locations passed as * argument. * * @param error * the {@link Throwable} that caused the credential load operation to * fail * @param locations * the locations where the credentials where loaded from */ public void notifyLoadCredentialFailure(Throwable error, String... locations); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/credential/LoadCredentialsStrategy.java000066400000000000000000000013721477577347300324620ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.credential; import eu.emi.security.authn.x509.helpers.PasswordSupplier; import eu.emi.security.authn.x509.X509Credential; /** * A strategy to load user credentials * * @author andreaceccanti * */ public interface LoadCredentialsStrategy { /** * Loads a user credential * * @param passwordFinder * the password finder used to potentially decrypt the credential * encrypted private key. * * @return an {@link X509Credential}, or null if no credential * was found */ public X509Credential loadCredentials(PasswordSupplier passwordFinder); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/credential/ProxyNamingPolicy.java000066400000000000000000000012461477577347300313350ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.credential; /** * A {@link ProxyNamingPolicy} defines the naming policy for a VOMS proxy. * * @author andreaceccanti * */ public interface ProxyNamingPolicy { /** * Builds the file name of a VOMS proxy * * @param tmpPath * the path of the temporary directory of the system * @param userId * the effective user id the user for which the proxy is created * @return a {@link String} representing the proxy file name */ public String buildProxyFileName(String tmpPath, int userId); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/credential/UserCredentials.java000066400000000000000000000024041477577347300307730ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.credential; import eu.emi.security.authn.x509.helpers.PasswordSupplier; import org.italiangrid.voms.credential.impl.DefaultLoadCredentialsStrategy; import eu.emi.security.authn.x509.X509Credential; /** * This class implements convenience methods to load X509 user credentials in * PEM or PKCS12 format. * * @author Andrea Ceccanti * */ public class UserCredentials { private static LoadCredentialsStrategy loadCredentialsStrategy = new DefaultLoadCredentialsStrategy(); public static void setLoadCredentialsStrategy(LoadCredentialsStrategy strategy) { loadCredentialsStrategy = strategy; } public static X509Credential loadCredentials() { return loadCredentials((char[]) null); } public static X509Credential loadCredentials(final char[] keyPassword) { PasswordSupplier pf = new PasswordSupplier() { public char[] getPassword() { return keyPassword; } }; return loadCredentialsStrategy.loadCredentials(pf); } public static X509Credential loadCredentials(PasswordSupplier passwordFinder) { return loadCredentialsStrategy.loadCredentials(passwordFinder); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/credential/VOMSEnvironmentVariables.java000066400000000000000000000012021477577347300325340ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.credential; public interface VOMSEnvironmentVariables { public static final String X509_CERT_DIR = "X509_CERT_DIR"; public static final String X509_VOMS_DIR = "X509_VOMS_DIR"; public static final String X509_USER_PROXY = "X509_USER_PROXY"; public static final String X509_USER_CERT = "X509_USER_CERT"; public static final String X509_USER_KEY = "X509_USER_KEY"; public static final String PKCS12_USER_CERT = "PKCS12_USER_CERT"; public static final String VOMS_USER_ID = "VOMS_UID"; }voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/credential/impl/000077500000000000000000000000001477577347300257755ustar00rootroot00000000000000AbstractLoadCredentialsStrategy.java000066400000000000000000000123111477577347300350230ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/credential/impl// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.credential.impl; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import eu.emi.security.authn.x509.helpers.PasswordSupplier; import org.italiangrid.voms.credential.LoadCredentialsEventListener; import org.italiangrid.voms.credential.LoadCredentialsStrategy; import org.italiangrid.voms.credential.VOMSEnvironmentVariables; import org.italiangrid.voms.util.FilePermissionHelper; import eu.emi.security.authn.x509.X509Credential; import eu.emi.security.authn.x509.impl.KeystoreCredential; import eu.emi.security.authn.x509.impl.PEMCredential; /** * Base class for load credentials strategy providing utility classes for * loading credentials from the filesystem and notifying the results of load * operations to interested listeners (via {@link LoadCredentialsEventListener} * ). * * @author andreaceccanti * */ public abstract class AbstractLoadCredentialsStrategy implements LoadCredentialsStrategy, VOMSEnvironmentVariables { /** * The {@link LoadCredentialsEventListener} that is notified of load * credentials outcome. */ LoadCredentialsEventListener listener; /** * Constructor that let client pass in a {@link LoadCredentialsEventListener}. * * @param listener * the listener that is notified of load credential events from this * {@link AbstractLoadCredentialsStrategy}. */ protected AbstractLoadCredentialsStrategy( LoadCredentialsEventListener listener) { this.listener = listener; } /** * Convenience method to check if a file exists and is readable * * @param filename * the file to be checked * @return true if the file exists and is readable, * false otherwise */ protected boolean fileExistsAndIsReadable(String filename) { File f = new File(filename); return f.exists() && f.isFile() && f.canRead(); } /** * Loads a PEM X.509 credential and notifies the registered * {@link LoadCredentialsEventListener} of the load operation outcome. * * @param privateKeyPath * the path to the private key * @param certificatePath * the path to the certificate * @param pf * a {@link PasswordSupplier} used to resolve the private key password * when needed * @return the loaded {@link X509Credential}, or null if the * credential couldn't be loaded */ protected X509Credential loadPEMCredential(String privateKeyPath, String certificatePath, PasswordSupplier pf) { PEMCredential cred = null; listener.notifyCredentialLookup(privateKeyPath, certificatePath); try { FilePermissionHelper.checkPrivateKeyPermissions(privateKeyPath); cred = new PEMCredential(new FileInputStream(privateKeyPath), new FileInputStream(certificatePath), pf); listener.notifyLoadCredentialSuccess(privateKeyPath, certificatePath); } catch (Throwable t) { listener.notifyLoadCredentialFailure(t, privateKeyPath, certificatePath); } return cred; } /** * Loads a PCKS12 X.509 credential and notifies the registered * {@link LoadCredentialsEventListener} of the load operation outcome. * * @param pkcs12FilePath * the path to the pkcs12 credential * @param pf * a {@link PasswordSupplier} used to resolve the private key password * @return the loaded {@link X509Credential}, or null if the * credential couldn't be loaded */ protected X509Credential loadPKCS12Credential(String pkcs12FilePath, PasswordSupplier pf) { KeystoreCredential cred = null; listener.notifyCredentialLookup(pkcs12FilePath); if (fileExistsAndIsReadable(pkcs12FilePath)) { char[] keyPassword = pf.getPassword(); try { FilePermissionHelper.checkPKCS12Permissions(pkcs12FilePath); cred = new KeystoreCredential(pkcs12FilePath, keyPassword, keyPassword, null, "PKCS12"); listener.notifyLoadCredentialSuccess(pkcs12FilePath); } catch (Throwable t) { listener.notifyLoadCredentialFailure(t, pkcs12FilePath); } } else listener.notifyLoadCredentialFailure(new FileNotFoundException( pkcs12FilePath + " (cannot read file)"), pkcs12FilePath); return cred; } /** * Loads an X.509 proxy credential and notifies the registered * {@link LoadCredentialsEventListener} of the load operation outcome. * * @param proxyPath * the path to the proxy credential * @return the loaded {@link X509Credential}, or null if the * credential couldn't be loaded */ protected X509Credential loadProxyCredential(String proxyPath) { PEMCredential cred = null; listener.notifyCredentialLookup(proxyPath); try { FilePermissionHelper.checkProxyPermissions(proxyPath); cred = new PEMCredential(new FileInputStream(proxyPath), (char[]) null); listener.notifyLoadCredentialSuccess(proxyPath); } catch (Throwable t) { listener.notifyLoadCredentialFailure(t, proxyPath); } return cred; } } DefaultLoadCredentialsStrategy.java000066400000000000000000000163661477577347300346620ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/credential/impl// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.credential.impl; import eu.emi.security.authn.x509.helpers.PasswordSupplier; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.credential.LoadCredentialsEventListener; import org.italiangrid.voms.credential.ProxyNamingPolicy; import org.italiangrid.voms.util.NullListener; import eu.emi.security.authn.x509.X509Credential; /** * The default strategy used to load user credentials when no file is explicitly pointed out by the * user of this API. * * Credentials are searched in the following places (in sequence): * *
    * *
  • If the X509_USER_CERT and X509_USER_KEY environment * variables are set, their values are used to load the user credentials
  • * *
  • If the X509_USER_CERT and X509_USER_KEY system properties * are set, their values are used to load the user credentials
  • * *
  • If the PKCS12_USER_CERT environment variable is set, its value is used to * load the user credentials.
  • * *
  • If the PKCS12_USER_CERT system property is set, its value is used to load * the user credentials.
  • * *
  • The content of the .globus directory in the user's home is searched for a PEM * certificate (in the usercert.pem and userkey.pem files).
  • * *
  • The content of the .globus directory in the user's home is searched for a PKC12 certificate * (in the usercert.p12 file).
  • *
* */ public class DefaultLoadCredentialsStrategy extends AbstractLoadCredentialsStrategy { private static final String GLOBUS_PKCS12_CRED_PATH_SUFFIX = ".globus/usercred.p12"; private static final String GLOBUS_PEM_CERT_PATH_SUFFIX = ".globus/usercert.pem"; private static final String GLOBUS_PEM_KEY_PATH_SUFFIX = ".globus/userkey.pem"; public static final String HOME_PROPERTY = "user.home"; public static final String TMPDIR_PROPERTY = "java.io.tmpdir"; public static final String TMPDIR_PATH = "/tmp"; private static final ProxyNamingPolicy proxyPathBuilder = new DefaultProxyPathBuilder(); private String home; private String tmpDir; /** * Constructs a strategy with specified home and temp directories and a listener. * * @param homeFolder the home directory path * @param tempDir the temporary directory path * @param listener event listener for credential loading */ public DefaultLoadCredentialsStrategy(String homeFolder, String tempDir, LoadCredentialsEventListener listener) { super(listener); this.home = homeFolder; this.tmpDir = tempDir; if (home == null) throw new VOMSError(HOME_PROPERTY + " not found in system properties!"); } /** * Constructs a strategy with a specified home directory. * * @param homeFolder the home directory path */ public DefaultLoadCredentialsStrategy(String homeFolder) { this(homeFolder, System.getProperty(TMPDIR_PROPERTY), NullListener.INSTANCE); } /** * Constructs a strategy using default system properties. */ public DefaultLoadCredentialsStrategy() { this(System.getProperty(HOME_PROPERTY), System.getProperty(TMPDIR_PROPERTY), NullListener.INSTANCE); } /** * Constructs a strategy with a specified event listener. * * @param listener the credential loading event listener */ public DefaultLoadCredentialsStrategy(LoadCredentialsEventListener listener) { this(System.getProperty(HOME_PROPERTY), System.getProperty(TMPDIR_PROPERTY), listener); } /** * Looks for the value of a given property in the environment or system properties. * * @param propName the property to look for * @return the property value, or null if not found */ public String getFromEnvOrSystemProperty(String propName) { String val = System.getenv(propName); if (val == null) val = System.getProperty(propName); return val; } /** * Loads user credentials using the available strategies. * * @param pf the password supplier * @return the loaded credentials */ public X509Credential loadCredentials(PasswordSupplier pf) { if (pf == null) throw new IllegalArgumentException("Please provide a non-null password finder!"); try { X509Credential cred = loadPEMCredentialFromEnv(pf); if (cred == null) cred = loadPKCS12CredentialFromEnv(pf); if (cred == null) cred = loadPEMCredentialsFromGlobusDir(pf); if (cred == null) cred = loadPKCS12CredentialsFromGlobusDir(pf); return cred; } catch (Exception e) { throw new VOMSError("Error loading credential: " + e.getMessage(), e); } } /** * Loads a proxy credential based on the user ID. * * @return the loaded proxy credential or null if not found */ protected X509Credential loadProxyFromUID() { String uid = getFromEnvOrSystemProperty(VOMS_USER_ID); if (uid != null) { String proxyFile = proxyPathBuilder.buildProxyFileName(tmpDir, Integer.parseInt(uid)); return loadProxyCredential(proxyFile); } return null; } /** * Loads a proxy credential from environment variables. * * @return the loaded proxy credential or null if not found */ protected X509Credential loadProxyFromEnv() { String proxyPath = getFromEnvOrSystemProperty(X509_USER_PROXY); if (proxyPath != null) return loadProxyCredential(proxyPath); return null; } /** * Loads a PEM credential from environment variables. * * @param pf the password supplier * @return the loaded credential or null if not found */ protected X509Credential loadPEMCredentialFromEnv(PasswordSupplier pf) { String certPath = getFromEnvOrSystemProperty(X509_USER_CERT); String keyPath = getFromEnvOrSystemProperty(X509_USER_KEY); if (certPath != null && keyPath != null) { return loadPEMCredential(keyPath, certPath, pf); } return null; } /** * Loads a PKCS12 credential from environment variables. * * @param pf the password supplier * @return the loaded credential or null if not found */ protected X509Credential loadPKCS12CredentialFromEnv(PasswordSupplier pf) { String pkcs12Path = getFromEnvOrSystemProperty(PKCS12_USER_CERT); if (pkcs12Path != null) { return loadPKCS12Credential(pkcs12Path, pf); } return null; } /** * Loads a PKCS12 credential from the Globus directory. * * @param pf the password supplier * @return the loaded credential or null if not found */ protected X509Credential loadPKCS12CredentialsFromGlobusDir(PasswordSupplier pf) { String credPath = String.format("%s/%s", home, GLOBUS_PKCS12_CRED_PATH_SUFFIX); return loadPKCS12Credential(credPath, pf); } /** * Loads a PEM credential from the Globus directory. * * @param pf the password supplier * @return the loaded credential or null if not found */ protected X509Credential loadPEMCredentialsFromGlobusDir(PasswordSupplier pf) { String certPath = String.format("%s/%s", home, GLOBUS_PEM_CERT_PATH_SUFFIX); String keyPath = String.format("%s/%s", home, GLOBUS_PEM_KEY_PATH_SUFFIX); return loadPEMCredential(keyPath, certPath, pf); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/credential/impl/DefaultProxyPathBuilder.java000066400000000000000000000006451477577347300334170ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.credential.impl; import org.italiangrid.voms.credential.ProxyNamingPolicy; public class DefaultProxyPathBuilder implements ProxyNamingPolicy { public String buildProxyFileName(String tmpPath, int userId) { return String.format("%s/x509up_u%d", tmpPath, userId); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/credential/impl/package-info.java000066400000000000000000000004311477577347300311620ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 /** * This package provides the implementation of the user credentials loading APIs. * * @author andreaceccanti * */ package org.italiangrid.voms.credential.impl;voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/credential/package-info.java000066400000000000000000000003421477577347300302220ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 /** * This package provides the API for loading user credentials. */ package org.italiangrid.voms.credential; voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/error/000077500000000000000000000000001477577347300240535ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/error/VOMSValidationErrorCode.java000066400000000000000000000013271477577347300313250ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.error; /** * VOMS validation error codes. * * @author Andrea Ceccanti * */ public enum VOMSValidationErrorCode { // Temporal validity acNotValidAtCurrentTime, // LSC signature checks lscFileNotFound, emptyAcCertsExtension, lscDescriptionDoesntMatchAcCert, invalidAcCert, acCertFailsSignatureVerification, // Local AA cert signature checks aaCertNotFound, invalidAaCert, aaCertFailsSignatureVerification, // Holder checks acHolderDoesntMatchCertChain, // Targets checks localhostDoesntMatchAcTarget, // CAnL errors canlError, // Other other; } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/error/VOMSValidationErrorMessage.java000066400000000000000000000051731477577347300320420ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.error; import java.text.MessageFormat; import java.util.MissingResourceException; import java.util.ResourceBundle; /** * A VOMS validation error message class (freely inspired by the CANL validation * error message class). * * @author Andrea Ceccanti * */ public class VOMSValidationErrorMessage { static final String ERROR_BUNDLE = VOMSValidationErrorMessage.class .getPackage().getName() + "." + "validationErrors"; private VOMSValidationErrorCode errorCode; private String message; private Object[] parameters; public static VOMSValidationErrorMessage newErrorMessage( VOMSValidationErrorCode errorCode) { return new VOMSValidationErrorMessage(errorCode); } public static VOMSValidationErrorMessage newErrorMessage( VOMSValidationErrorCode errorCode, Object... params) { return new VOMSValidationErrorMessage(errorCode, params); } private VOMSValidationErrorMessage(VOMSValidationErrorCode errorCode) { this(errorCode, (Object[]) null); } private VOMSValidationErrorMessage(VOMSValidationErrorCode errorCode, Object... params) { this.errorCode = errorCode; this.parameters = params; ResourceBundle bundle = ResourceBundle.getBundle(ERROR_BUNDLE); String template = null; try { template = bundle.getString(errorCode.name()); } catch (MissingResourceException e) { template = "Other error"; } message = MessageFormat.format(template, parameters); } public VOMSValidationErrorCode getErrorCode() { return errorCode; } public String getMessage() { return message; } public Object[] getParameters() { return parameters; } @Override public String toString() { return String.format("[%s]:%s", errorCode.name(), message); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((errorCode == null) ? 0 : errorCode.hashCode()); result = prime * result + ((message == null) ? 0 : message.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; VOMSValidationErrorMessage other = (VOMSValidationErrorMessage) obj; if (errorCode != other.errorCode) return false; if (message == null) { if (other.message != null) return false; } else if (!message.equals(other.message)) return false; return true; } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/error/package-info.java000066400000000000000000000003541477577347300272440ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 /** * This package provides error code and message definitions for the VOMS API. */ package org.italiangrid.voms.error; voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/examples/000077500000000000000000000000001477577347300245405ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/examples/ValidationExample.java000066400000000000000000000023451477577347300310150ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.examples; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.security.KeyStoreException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.List; import org.italiangrid.voms.VOMSAttribute; import org.italiangrid.voms.VOMSValidators; import org.italiangrid.voms.ac.VOMSACValidator; import eu.emi.security.authn.x509.impl.PEMCredential; /** * A simple example showing how VOMS attributes validation is done with the new * API * * @author Andrea Ceccanti * */ public class ValidationExample { public ValidationExample() throws KeyStoreException, CertificateException, FileNotFoundException, IOException { VOMSACValidator validator = VOMSValidators.newValidator(); PEMCredential c = new PEMCredential(new FileInputStream("somefile"), (char[]) null); X509Certificate[] chain = c.getCertificateChain(); List attrs = validator.validate(chain); for (VOMSAttribute a : attrs) System.out.println(a); validator.shutdown(); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/examples/package-info.java000066400000000000000000000003411477577347300277250ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 /** * This package provides examples of the use of VOMS Java APIs. */ package org.italiangrid.voms.examples; voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/package-info.java000066400000000000000000000006211477577347300261100ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 /** * * This package provides main VOMS Java APIs class and interfaces. * For an introductory guide to the use of the API, check the API user manual * here. * * @author Andrea Ceccanti * */ package org.italiangrid.voms;voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/000077500000000000000000000000001477577347300244125ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/ACDecodingStrategy.java000066400000000000000000000010141477577347300307140ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request; /** * Decodes an encoded VOMS attribute certificate * * @author andreaceccanti * */ public interface ACDecodingStrategy { /** * Decodes an encoded VOMS attribute certificate * * @param ac * the encoded VOMS attribute certificate * @return a byte array containing the VOMS attribute certificate */ public byte[] decode(String ac); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/SSLSocketFactoryProvider.java000066400000000000000000000076251477577347300321440ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import javax.net.ssl.KeyManager; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.util.CertificateValidatorBuilder; import eu.emi.security.authn.x509.X509CertChainValidatorExt; import eu.emi.security.authn.x509.X509Credential; import eu.emi.security.authn.x509.helpers.ssl.DisabledNameMismatchCallback; import eu.emi.security.authn.x509.helpers.ssl.EnforcingNameMismatchCallback; import eu.emi.security.authn.x509.impl.SocketFactoryCreator2; /** * Provides an SSL socket factory configured using CAnL. * * This class is responsible for creating an {@link SSLSocketFactory} that is configured with a * given X.509 credential and certificate validator. It supports optional hostname verification. * */ public class SSLSocketFactoryProvider { /** The X.509 credential used for SSL connections. */ private X509Credential credential; /** The certificate chain validator. */ private X509CertChainValidatorExt validator; /** Flag indicating whether hostname checks should be skipped. */ private boolean skipHostnameChecks; /** * Constructs an {@link SSLSocketFactoryProvider} with the given credential, validator, and * hostname check setting. * * @param credential the X.509 credential * @param validator the certificate chain validator * @param skipHostnameChecks true to disable hostname verification, false otherwise */ public SSLSocketFactoryProvider(X509Credential credential, X509CertChainValidatorExt validator, boolean skipHostnameChecks) { this.credential = credential; this.validator = validator; this.skipHostnameChecks = skipHostnameChecks; } /** * Constructs an {@link SSLSocketFactoryProvider} with the given credential and validator, with * hostname verification enabled. * * @param credential the X.509 credential * @param validator the certificate chain validator */ public SSLSocketFactoryProvider(X509Credential credential, X509CertChainValidatorExt validator) { this(credential, validator, false); } /** * Constructs an {@link SSLSocketFactoryProvider} with the given credential and a default * validator. * * @param credential the X.509 credential */ public SSLSocketFactoryProvider(X509Credential credential) { this(credential, new CertificateValidatorBuilder().trustAnchorsUpdateInterval(60000L).build()); } /** * Returns an SSL socket factory configured with the provided credential and validator. * * @return the {@link SSLSocketFactory} object */ public SSLSocketFactory getSSLSockectFactory() { SSLContext context = null; try { context = SSLContext.getInstance("TLS"); } catch (NoSuchAlgorithmException e) { throw new VOMSError(e.getMessage(), e); } KeyManager[] keyManagers = new KeyManager[] {credential.getKeyManager()}; SocketFactoryCreator2 factory = new SocketFactoryCreator2(credential, validator, skipHostnameChecks ? new DisabledNameMismatchCallback() : new EnforcingNameMismatchCallback()); X509TrustManager trustManager = factory.getSSLTrustManager(); TrustManager[] trustManagers = new TrustManager[] {trustManager}; // Using new SecureRandom instead of SecureRandom.getInstance("SHA1PRNG") to avoid unnecessary // blocking SecureRandom secureRandom = new SecureRandom(); try { context.init(keyManagers, trustManagers, secureRandom); } catch (KeyManagementException e) { throw new VOMSError(e.getMessage(), e); } return context.getSocketFactory(); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/VOMSACRequest.java000066400000000000000000000015401477577347300276160ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request; import java.util.List; /** * A request for a VOMS Attribute certificate. * * @author Andrea Ceccanti * */ public interface VOMSACRequest { /** * @return the lifetime for this {@link VOMSACRequest}. */ public int getLifetime(); /** * @return the list of the requested FQANs specified in this * {@link VOMSACRequest} object. */ public List getRequestedFQANs(); /** * @return the list of targets (i.e., host where the requested ACs will be * valid) for this {@link VOMSACRequest} object. */ public List getTargets(); /** * @return the name of the VO this {@link VOMSACRequest} object is about. */ public String getVoName(); }voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/VOMSACService.java000066400000000000000000000015731477577347300275740ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request; import org.bouncycastle.asn1.x509.AttributeCertificate; import eu.emi.security.authn.x509.X509Credential; /** * The {@link VOMSACService} interface. * * @author Andrea Ceccanti * */ public interface VOMSACService { /** * Returns an {@link AttributeCertificate} given a {@link VOMSACRequest} for * VOMS attributes. * * @param credential * the credential to be used when contacting the service * @param request * the request for VOMS attributes * @return a possibly null {@link AttributeCertificate} containing (a subset * of) the requested attributes. */ public AttributeCertificate getVOMSAttributeCertificate( X509Credential credential, VOMSACRequest request); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/VOMSESLookupStrategy.java000066400000000000000000000014311477577347300312050ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request; import java.io.File; import java.util.List; /** * An strategy for building a list of {@link File} objects which will provide * access to the local trusted VOMS server contact information. * * @author Andrea Ceccanti * */ public interface VOMSESLookupStrategy { /** * @return a {@link List} of {@link File} objects that can be used to parse * VOMSES information. */ public List lookupVomsesInfo(); /** * @return a {@link List} of the paths that have been looked up to find * {@link File} objects that can be used to parse VOMSES information. */ public List searchedPaths(); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/VOMSESParser.java000066400000000000000000000023611477577347300274500ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request; import java.io.File; import java.io.Reader; import java.util.List; import org.italiangrid.voms.VOMSError; /** * A VOMSES file parser. * * @author Andrea Ceccanti * */ public interface VOMSESParser { /** * Parses the VOMS contact information from the {@link Reader} passed as * argument. * * @param vomsesReader * the {@link Reader} object where voms contact information can be * read from. * @return a {@link VOMSServerInfo} object containing the VOMS server contact * information. * @throws VOMSError * in case of parsing errors */ public List parse(Reader vomsesReader); /** * Parses the VOMS contact information from the {@link File} passed as * argument. * * @param f * the {@link File} object where voms contact information can be read * from. * @return a {@link VOMSServerInfo} object containing the VOMS server contact * information. * @throws VOMSError * in case of parsing errors */ public List parse(File f); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/VOMSESParserFactory.java000066400000000000000000000007571477577347300310070ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request; import org.italiangrid.voms.request.impl.LegacyVOMSESParserImpl; /** * A factory class for {@link VOMSESParser}. * * @author Andrea Ceccanti * */ public class VOMSESParserFactory { /** * @return Returns a {@link VOMSESParser}. */ public static VOMSESParser newVOMSESParser() { return new LegacyVOMSESParserImpl(); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/VOMSErrorMessage.java000066400000000000000000000010341477577347300303560ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request; /** * * This class is used to decode VOMS error messages contained in a VOMS * response. * * @author Andrea Ceccanti * @author Vincenzo Ciaschini * */ public class VOMSErrorMessage extends VOMSMessage { public VOMSErrorMessage(int code, String message) { super(code, message); } public String toString() { return "voms error " + code + ": " + message; } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/VOMSMessage.java000066400000000000000000000014141477577347300273460ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request; /** * * This class is used to decode VOMS error messages contained in a VOMS * response. * * @author Andrea CEccanti * */ public class VOMSMessage { int code; String message; public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public VOMSMessage(int code, String message) { this.code = code; this.message = message; } public String toString() { return "voms message " + code + ": " + message; } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/VOMSProtocol.java000066400000000000000000000014371477577347300275700ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request; import eu.emi.security.authn.x509.X509Credential; /** * The request/response protocol for VOMS, with a methods accepting a rerquest * and returning a response. * * @author valerioventuri * */ public interface VOMSProtocol { /** * Makes a request, get the response. * * @param endpoint * the voms server endpoint information * @param credential * the credentials. * @param request * the request. * * @return a {@link VOMSResponse} containing the response. */ public VOMSResponse doRequest(VOMSServerInfo endpoint, X509Credential credential, VOMSACRequest request); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/VOMSProtocolError.java000066400000000000000000000027121477577347300305770ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request; import org.italiangrid.voms.VOMSError; import eu.emi.security.authn.x509.X509Credential; /** * Exception used when errors are raised during the interaction with a * (possibly) remote VOMS server. * * @author andreaceccanti * */ public class VOMSProtocolError extends VOMSError { /** * */ private static final long serialVersionUID = 1L; /** * The request that is related with this error */ private final VOMSACRequest request; /** * The credential related with this error */ private final X509Credential credential; /** * The VOMS server endpoint information related with this error */ private final VOMSServerInfo serverInfo; public VOMSProtocolError(String message, VOMSServerInfo serv, VOMSACRequest req, X509Credential cred, Throwable c) { super(message, c); this.request = req; this.credential = cred; this.serverInfo = serv; } /** * @return the request that is related with this error */ public VOMSACRequest getRequest() { return request; } /** * @return the client credential related with this error */ public X509Credential getCredential() { return credential; } /** * @return the VOMS serverInfo related with this error */ public VOMSServerInfo getServerInfo() { return serverInfo; } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/VOMSProtocolListener.java000066400000000000000000000016441477577347300312760ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request; /** * A listener that is notified of low-level VOMS protocol messages * * @author cecco * */ public interface VOMSProtocolListener { /** * Informs that a VOMS HTTP GET request is being issued for the URL passed as * argument * * @param url * the request url */ public void notifyHTTPRequest(String url); /** * Informs that a VOMS legacy request is being issued * * @param xmlLegacyRequest * a string representation of the XML legacy request */ public void notifyLegacyRequest(String xmlLegacyRequest); /** * Informs that a VOMSResponse was received from a remote VOMS server * * @param r * the received {@link VOMSResponse} */ public void notifyReceivedResponse(VOMSResponse r); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/VOMSRequestListener.java000066400000000000000000000041351477577347300311230ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request; /** * A listener that informs about events related with a request to a VOMS server. * * @author andreaceccanti * */ public interface VOMSRequestListener { /** * Informs of the start of a request to a VOMS server * * @param request * the request * @param si * the VOMS server endpoint information */ public void notifyVOMSRequestStart(VOMSACRequest request, VOMSServerInfo si); /** * Informs of the succesfull conclusion of a request to a VOMS server * * @param request * the request * @param endpoint * the VOMS server endpoint information */ public void notifyVOMSRequestSuccess(VOMSACRequest request, VOMSServerInfo endpoint); /** * Informs of a VOMS request failure * * @param request * the request * @param endpoint * the VOMS server endpoint information * @param error * the error related with the failure */ public void notifyVOMSRequestFailure(VOMSACRequest request, VOMSServerInfo endpoint, Throwable error); /** * Informs that errors were included in the VOMS response produced by a VOMS * server * * @param request * the request related to the received response * @param si * the VOMS server endpoint information * @param errors * the error messages included in the response */ public void notifyErrorsInVOMSReponse(VOMSACRequest request, VOMSServerInfo si, VOMSErrorMessage[] errors); /** * Informs that warnings were included in the VOMS response produced by a VOMS * server * * @param request * the request related to the received response * @param si * the VOMS server endpoint information * @param warnings * the warning messages included in the response */ public void notifyWarningsInVOMSResponse(VOMSACRequest request, VOMSServerInfo si, VOMSWarningMessage[] warnings); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/VOMSResponse.java000066400000000000000000000024721477577347300275650ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request; /** * * @author Andrea Ceccanti * */ public interface VOMSResponse { /** * @return true if this {@link VOMSResponse} has errors, * false otherwise */ public boolean hasErrors(); /** * @return true if this {@link VOMSResponse} has warnings, * false otherwise */ public boolean hasWarnings(); /** * * Extracts the AC from the VOMS response. * * @return an array of bytes containing the AC. */ public byte[] getAC(); /** * Extracts the version from the VOMS response. * * @return an integer containing the AC. */ public abstract int getVersion(); /** * * Extracts the error messages from the VOMS response. * * @return an array of {@link VOMSErrorMessage} objects. */ public VOMSErrorMessage[] errorMessages(); /** * Extracts the warning messags from the VOMS response. * * @return an array of {@link VOMSWarningMessage} objects. */ public VOMSWarningMessage[] warningMessages(); /** * * @return Returns the XML representation of the response as a string. */ public String getXMLAsString(); }voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/VOMSResponseParsingStrategy.java000066400000000000000000000012241477577347300326260ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request; import java.io.InputStream; /** * The strategy for parsing a response coming from a VOMS service. * * @author valerioventuri * */ public interface VOMSResponseParsingStrategy { /** * Parse the response coming from a VOMS service and build a * {@link VOMSResponse} object. * * @param inputStream * the response from the VOMS service. * @return the response object representing the response from the service. */ public VOMSResponse parse(InputStream inputStream); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/VOMSServerInfo.java000066400000000000000000000021051477577347300300420ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request; import java.net.URI; /** * This interface represents a VOMS server contact information, typically * provided in vomses files. * * @see VOMSESLookupStrategy * @see VOMSESParser * * @author Andrea Ceccanti * */ public interface VOMSServerInfo { /** * Returns the alias for this {@link VOMSServerInfo}. * * @return the alias */ public String getAlias(); /** * Returns the VO name for this {@link VOMSServerInfo}. * * @return the vo name */ public String getVoName(); /** * Returns the URL for this {@link VOMSServerInfo}. * * @return the contact {@link URI} */ public URI getURL(); /** * Returns the certificate subject as listed in the VOMSES configuration for * this {@link VOMSServerInfo} * * @return a string containing the certificate subject, enconded following the * DN openssl slash-separated syntax */ public String getVOMSServerDN(); }voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/VOMSServerInfoStore.java000066400000000000000000000022651477577347300310660ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request; import java.util.Set; /** * A store containing the contact information for locally trusted VOMS servers. * * @author Andrea Ceccanti * */ public interface VOMSServerInfoStore { /** * Returns a set of {@link VOMSServerInfo} object matching a vo name or alias * passed as argument. * * @param voName * a VO name * @return a possibly empty set of {@link VOMSServerInfo} object matching the * vo name or alias passed as argument */ public Set getVOMSServerInfo(String voName); /** * Returns a set of all {@link VOMSServerInfo} objects in this * {@link VOMSServerInfoStore}. * * @return a possibly empty set of all {@link VOMSServerInfo} objects in this * {@link VOMSServerInfoStore}. */ public Set getVOMSServerInfo(); /** * Adds a {@link VOMSServerInfo} to this {@link VOMSServerInfoStore}. * * @param info * the {@link VOMSServerInfo} object to add. */ public void addVOMSServerInfo(VOMSServerInfo info); }voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/VOMSServerInfoStoreListener.java000066400000000000000000000022651477577347300325740ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request; import java.util.List; /** * This interface is used to notify about events related to the load operations * of VOMSES server endpoint information. * * @author andreaceccanti * */ public interface VOMSServerInfoStoreListener { /** * Informs that no valid VOMS information was found on the system. * * @param searchedPaths * the list of searched paths */ public void notifyNoValidVOMSESError(List searchedPaths); /** * Informs that VOMSES is being search at the path passed as argument * * @param vomsesPath * the path where VOMSES information are being looked for */ public void notifyVOMSESlookup(String vomsesPath); /** * Informs that VOMSES information was succesfully loaded from a given path * * @param vomsesPath * the path where VOMSES information was loaded from * @param info * the {@link VOMSServerInfo} voms endpoint information */ public void notifyVOMSESInformationLoaded(String vomsesPath, VOMSServerInfo info); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/VOMSWarningMessage.java000066400000000000000000000010041477577347300306670ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request; /** * * This class is used to decode VOMS error messages contained in a VOMS * response. * * @author Andrea CEccanti * */ public class VOMSWarningMessage extends VOMSMessage { public VOMSWarningMessage(int code, String message) { super(code, message); } public String toString() { return "voms warning " + code + ": " + message; } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/impl/000077500000000000000000000000001477577347300253535ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/impl/ACGenerationParams.java000066400000000000000000000167441477577347300316750ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request.impl; import static java.lang.Integer.parseInt; import static java.lang.Long.parseLong; import static java.util.Objects.isNull; import static org.italiangrid.voms.request.impl.FakeVOMSACServiceProperties.FQANS; import static org.italiangrid.voms.request.impl.FakeVOMSACServiceProperties.GAS; import static org.italiangrid.voms.request.impl.FakeVOMSACServiceProperties.HOST; import static org.italiangrid.voms.request.impl.FakeVOMSACServiceProperties.NOT_AFTER; import static org.italiangrid.voms.request.impl.FakeVOMSACServiceProperties.NOT_BEFORE; import static org.italiangrid.voms.request.impl.FakeVOMSACServiceProperties.PORT; import static org.italiangrid.voms.request.impl.FakeVOMSACServiceProperties.SERIAL; import static org.italiangrid.voms.request.impl.FakeVOMSACServiceProperties.VO; import static org.italiangrid.voms.util.GaParser.parseGaString; import static org.italiangrid.voms.util.TimeUtils.parseDate; import java.math.BigInteger; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.italiangrid.voms.VOMSGenericAttribute; import org.italiangrid.voms.ac.impl.VOMSGenericAttributeImpl; /** * This class represents the parameters required for generating an Attribute Certificate (AC). * It encapsulates various attributes such as Virtual Organization (VO), Fully Qualified Attribute Names (FQANs), * Generic Attributes (GAs), host details, validity periods, and a serial number. */ public class ACGenerationParams { /** The Virtual Organization name. */ final String vo; /** The list of Fully Qualified Attribute Names. */ final List fqans; /** The list of Generic Attributes. */ final List gas; /** The host associated with the AC request. */ final String host; /** The port associated with the AC request. */ final int port; /** The start time of the validity period. */ final Date notBefore; /** The end time of the validity period. */ final Date notAfter; /** The serial number of the attribute certificate. */ final BigInteger serialNo; /** * Private constructor to initialize an instance using the Builder pattern. * * @param builder the builder instance used to construct this object */ private ACGenerationParams(Builder builder) { this.vo = builder.vo; this.fqans = builder.fqans; this.gas = builder.gas; this.host = builder.host; this.port = builder.port; this.notBefore = builder.notBefore; this.notAfter = builder.notAfter; this.serialNo = builder.serialNo; } /** @return the Virtual Organization name */ public String getVo() { return vo; } /** @return the list of Fully Qualified Attribute Names */ public List getFqans() { return fqans; } /** @return the list of Generic Attributes */ public List getGas() { return gas; } /** @return the host associated with the AC request */ public String getHost() { return host; } /** @return the port associated with the AC request */ public int getPort() { return port; } /** @return the start time of the validity period */ public Date getNotBefore() { return notBefore; } /** @return the end time of the validity period */ public Date getNotAfter() { return notAfter; } /** @return the serial number of the attribute certificate */ public BigInteger getSerialNo() { return serialNo; } /** * Builder class for constructing {@link ACGenerationParams} instances. */ public static class Builder { String vo = "test"; List fqans; List gas; String host = "voms.example"; int port = 15000; Date notBefore; Date notAfter; BigInteger serialNo = BigInteger.valueOf(0L); /** Default constructor initializing lists. */ public Builder() { fqans = new ArrayList<>(); gas = new ArrayList<>(); } /** * Sets the VO. * @param vo the Virtual Organization name * @return the Builder instance */ public Builder vo(String vo) { this.vo = vo; return this; } /** * Adds a Fully Qualified Attribute Name. * @param fqan the FQAN to add * @return the Builder instance */ public Builder fqan(String fqan) { fqans.add(fqan); return this; } /** * Adds a Generic Attribute. * @param name the attribute name * @param value the attribute value * @param context the attribute context * @return the Builder instance */ public Builder ga(String name, String value, String context) { VOMSGenericAttributeImpl ga = new VOMSGenericAttributeImpl(); ga.setName(name); ga.setValue(value); ga.setContext(context); gas.add(ga); return this; } /** * Sets the host. * @param host the host * @return the Builder instance */ public Builder host(String host) { this.host = host; return this; } /** * Sets the port. * @param port the port number * @return the Builder instance */ public Builder port(int port) { this.port = port; return this; } /** * Sets the not-before validity time. * @param notBefore the start of the validity period * @return the Builder instance */ public Builder notBefore(Date notBefore) { this.notBefore = notBefore; return this; } /** * Sets the not-after validity time. * @param notAfter the end of the validity period * @return the Builder instance */ public Builder notAfter(Date notAfter) { this.notAfter = notAfter; return this; } /** * Sets the serial number. * @param serialNo the serial number * @return the Builder instance */ public Builder serialNo(long serialNo) { this.serialNo = BigInteger.valueOf(serialNo); return this; } /** * Builds the {@link ACGenerationParams} instance. * @return a new ACGenerationParams object */ public ACGenerationParams build() { return new ACGenerationParams(this); } } /** @return a new Builder instance */ public static Builder builder() { return new Builder(); } /** * Constructs an {@link ACGenerationParams} instance from system properties. * * @return a configured ACGenerationParams instance. */ public static ACGenerationParams fromSystemProperties() { ACGenerationParams.Builder builder = ACGenerationParams.builder(); builder.vo(VO.getSystemPropertyValue()); String fqansString = FQANS.getSystemPropertyValue(); for (String f : fqansString.split(",")) { String trimmedFqan = f.trim(); if (!trimmedFqan.isEmpty()) { builder.fqan(trimmedFqan); } } builder.host(HOST.getSystemPropertyValue()); builder.port(parseInt(PORT.getSystemPropertyValue())); builder.serialNo(parseLong(SERIAL.getSystemPropertyValue())); String notBefore = NOT_BEFORE.getSystemPropertyValue(); if (!isNull(notBefore)) { builder.notBefore(parseDate(notBefore)); } String notAfter = NOT_AFTER.getSystemPropertyValue(); if (!isNull(notAfter)) { builder.notAfter(parseDate(notAfter)); } String gaString = GAS.getSystemPropertyValue(); if (!isNull(gaString)) { parseGaString(gaString).forEach(a -> builder.ga(a.getName(), a.getValue(), builder.vo)); } return builder.build(); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/impl/AbstractVOMSProtocol.java000066400000000000000000000113021477577347300322050ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request.impl; import javax.net.ssl.SSLSocketFactory; import org.italiangrid.voms.request.SSLSocketFactoryProvider; import org.italiangrid.voms.request.VOMSProtocol; import org.italiangrid.voms.request.VOMSProtocolListener; import org.italiangrid.voms.util.NullListener; import eu.emi.security.authn.x509.X509CertChainValidatorExt; import eu.emi.security.authn.x509.X509Credential; /** * Abstract base class providing a skeletal implementation of the VOMS client-server protocol. This * class handles SSL authentication, connection timeouts, and hostname verification. */ public abstract class AbstractVOMSProtocol implements VOMSProtocol { /** * Enabled TLS protocols for VOMS legacy connections. */ public static final String[] VOMS_LEGACY_ENABLED_PROTOCOLS = {"TLSv1", "TLSv1.1", "TLSv1.2"}; /** * The default value for the socket connection timeout (in milliseconds). */ public static final int DEFAULT_CONNECT_TIMEOUT = 5000; /** * The default value for the socket read timeout (in milliseconds). */ public static final int DEFAULT_READ_TIMEOUT = 5000; /** * The default policy for skipping hostname verification. */ public static final boolean DEFAULT_SKIP_HOSTNAME_CHECKS = false; /** * Listener for protocol events. */ protected VOMSProtocolListener listener = NullListener.INSTANCE; /** * Validator used for SSL authentication. */ protected X509CertChainValidatorExt validator; /** * TCP connection timeout in milliseconds. */ protected int connectTimeout = DEFAULT_CONNECT_TIMEOUT; /** * Socket read timeout in milliseconds. */ protected int readTimeout = DEFAULT_READ_TIMEOUT; /** * Flag indicating whether hostname verification is disabled. */ protected boolean skipHostnameChecks = DEFAULT_SKIP_HOSTNAME_CHECKS; /** * Constructor initializing the protocol with a certificate validator. * * @param validator the certificate validator for SSL authentication */ public AbstractVOMSProtocol(X509CertChainValidatorExt validator) { this.validator = validator; } /** * Constructor initializing the protocol with a validator, listener, and timeout settings. * * @param validator the certificate validator for SSL authentication * @param listener the listener for protocol events * @param connectTimeout the socket connection timeout in milliseconds * @param readTimeout the socket read timeout in milliseconds */ public AbstractVOMSProtocol(X509CertChainValidatorExt validator, VOMSProtocolListener listener, int connectTimeout, int readTimeout) { this.validator = validator; this.connectTimeout = connectTimeout; this.readTimeout = readTimeout; this.listener = listener; } /** * Creates an SSL socket factory using the provided credential and validator. * * @param credential the client credential for SSL authentication * @return an SSL socket factory configured with the given credential and validator */ protected SSLSocketFactory getSSLSocketFactory(X509Credential credential) { SSLSocketFactoryProvider sslSocketFactoryProvider = new SSLSocketFactoryProvider(credential, validator, skipHostnameChecks); return sslSocketFactoryProvider.getSSLSockectFactory(); } /** * Retrieves the connection timeout value. * * @return the connection timeout in milliseconds */ public int getConnectTimeout() { return connectTimeout; } /** * Sets the connection timeout for the underlying socket. * * @param connectTimeout the connection timeout in milliseconds */ public void setConnectTimeout(int connectTimeout) { this.connectTimeout = connectTimeout; } /** * Retrieves the read timeout value. * * @return the read timeout in milliseconds */ public int getReadTimeout() { return readTimeout; } /** * Sets the read timeout for the underlying socket. * * @param readTimeout the read timeout in milliseconds */ public void setReadTimeout(int readTimeout) { this.readTimeout = readTimeout; } /** * Checks whether hostname verification is disabled. * * @return {@code true} if hostname checks are skipped, {@code false} otherwise */ public boolean isSkipHostnameChecks() { return skipHostnameChecks; } /** * Configures whether SSL hostname verification should be skipped. * * @param skipHostnameChecks {@code true} to disable hostname verification, {@code false} to * enable it */ public void setSkipHostnameChecks(boolean skipHostnameChecks) { this.skipHostnameChecks = skipHostnameChecks; } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/impl/BaseVOMSESLookupStrategy.java000066400000000000000000000023441477577347300327450ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request.impl; import java.io.File; import java.util.ArrayList; import java.util.List; import org.italiangrid.voms.request.VOMSESLookupStrategy; /** * A base VOMSES lookup strategy which just run a existence check on a given * list of paths. * * @author Andrea Ceccanti * */ public class BaseVOMSESLookupStrategy implements VOMSESLookupStrategy { private final List checkedPaths; public BaseVOMSESLookupStrategy() { checkedPaths = new ArrayList(); } public BaseVOMSESLookupStrategy(List checkedPaths) { if (checkedPaths == null) throw new NullPointerException("Please provide a non-null list of paths."); this.checkedPaths = checkedPaths; } public List lookupVomsesInfo() { List vomsesPaths = new ArrayList(); for (String p : checkedPaths) { File f = new File(p); if (f.exists()) vomsesPaths.add(f); } return vomsesPaths; } public List searchedPaths() { return checkedPaths; } public void addPath(String vomsesPath) { checkedPaths.add(vomsesPath); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/impl/DefaultVOMSACRequest.java000066400000000000000000000035261477577347300320720ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request.impl; import java.util.Collections; import java.util.List; import java.util.concurrent.TimeUnit; import org.italiangrid.voms.request.VOMSACRequest; /** * The default implementation for a {@link VOMSACRequest}. * * @author Valerio Venturi * */ public class DefaultVOMSACRequest implements VOMSACRequest { public static final int DEFAULT_LIFETIME = (int) TimeUnit.HOURS.toSeconds(12); private int lifetime; private List requestedFQANs; private List targets; private String voName; public int getLifetime() { return lifetime; } public List getRequestedFQANs() { return requestedFQANs; } public List getTargets() { return targets; } public String getVoName() { return voName; } private DefaultVOMSACRequest(Builder b) { this.lifetime = b.lifetime; this.voName = b.voName; this.targets = b.targets; this.requestedFQANs = b.requestedFQANs; } public static class Builder { private int lifetime = DEFAULT_LIFETIME; private List requestedFQANs = Collections.emptyList(); private List targets = Collections.emptyList(); private String voName; public Builder(String voName) { this.voName = voName; } public Builder lifetime(int l) { this.lifetime = l; return this; } public Builder fqans(List fqans) { if (fqans != null) this.requestedFQANs = fqans; return this; } public Builder targets(List targets) { if (targets != null) this.targets = targets; return this; } public DefaultVOMSACRequest build() { return new DefaultVOMSACRequest(this); } } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/impl/DefaultVOMSACService.java000066400000000000000000000373441477577347300320470ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request.impl; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.x509.AttributeCertificate; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.request.VOMSACRequest; import org.italiangrid.voms.request.VOMSACService; import org.italiangrid.voms.request.VOMSESLookupStrategy; import org.italiangrid.voms.request.VOMSProtocol; import org.italiangrid.voms.request.VOMSProtocolError; import org.italiangrid.voms.request.VOMSProtocolListener; import org.italiangrid.voms.request.VOMSRequestListener; import org.italiangrid.voms.request.VOMSResponse; import org.italiangrid.voms.request.VOMSServerInfo; import org.italiangrid.voms.request.VOMSServerInfoStore; import org.italiangrid.voms.request.VOMSServerInfoStoreListener; import org.italiangrid.voms.util.NullListener; import eu.emi.security.authn.x509.X509CertChainValidatorExt; import eu.emi.security.authn.x509.X509Credential; /** * The default implementation of the {@link VOMSACService}. * * * @author Valerio Venturi * @author Andrea Ceccanti * */ public class DefaultVOMSACService implements VOMSACService { /** * The listener that will be informed about request events */ protected final VOMSRequestListener requestListener; /** * The listener that will be informed about low-level protocol details */ protected final VOMSProtocolListener protocolListener; /** * The validator used for the SSL handshake */ protected final X509CertChainValidatorExt validator; /** * The store used to keep VOMS server contact information. */ protected final VOMSServerInfoStore serverInfoStore; /** * The http protocol implementation */ protected final VOMSProtocol httpProtocol; /** * The voms legacy protocol implementation */ protected final VOMSProtocol legacyProtocol; /** * Whether VOMS legacy protocol should be used as a fallback when REST protocol fails */ protected final boolean legacyProtocolEnabled; /** * Constructor which builds a {@link DefaultVOMSACService} from a {@link Builder} * * @param builder the builder object that provides the settings for this {@link VOMSACService} */ protected DefaultVOMSACService(Builder builder) { this.validator = builder.validator; this.requestListener = builder.requestListener; this.protocolListener = builder.protocolListener; this.serverInfoStore = builder.serverInfoStore; this.httpProtocol = builder.httpProtocol; this.legacyProtocol = builder.legacyProtocol; this.legacyProtocolEnabled = builder.legacyProtocolEnabled; } /** * Extracts an AC from a VOMS response * * @param request the request * @param response the received response * @return a possibly null {@link AttributeCertificate} object */ protected AttributeCertificate getACFromResponse(VOMSACRequest request, VOMSResponse response) { byte[] acBytes = response.getAC(); if (acBytes == null) return null; ASN1InputStream asn1InputStream = new ASN1InputStream(acBytes); AttributeCertificate attributeCertificate = null; try { attributeCertificate = AttributeCertificate.getInstance(asn1InputStream.readObject()); asn1InputStream.close(); return attributeCertificate; } catch (Throwable e) { requestListener.notifyVOMSRequestFailure(request, null, new VOMSError("Error unmarshalling VOMS AC. Cause: " + e.getMessage(), e)); return null; } } private VOMSResponse doRequest(VOMSProtocol protocol, VOMSServerInfo endpoint, X509Credential cred, VOMSACRequest req) { VOMSResponse response = null; try { response = protocol.doRequest(endpoint, cred, req); } catch (VOMSProtocolError e) { requestListener.notifyVOMSRequestFailure(req, endpoint, e); } return response; } /** * Handles errors included in the VOMS response * * @param request the request * @param si the VOMS server endpoint information * @param response the received {@link VOMSResponse} */ protected void handleErrorsInResponse(VOMSACRequest request, VOMSServerInfo si, VOMSResponse response) { if (response.hasErrors()) requestListener.notifyErrorsInVOMSReponse(request, si, response.errorMessages()); } /** * Handles warnings included in the VOMS response * * @param request the request * @param si the VOMS server endpoint information * @param response the received {@link VOMSResponse} */ protected void handleWarningsInResponse(VOMSACRequest request, VOMSServerInfo si, VOMSResponse response) { if (response.hasWarnings()) requestListener.notifyWarningsInVOMSResponse(request, si, response.warningMessages()); } public AttributeCertificate getVOMSAttributeCertificate(X509Credential credential, VOMSACRequest request) { List vomsServerInfos = getVOMSServerInfos(request); if (vomsServerInfos.isEmpty()) throw new VOMSError("VOMS server for VO " + request.getVoName() + " " + "is not known! Check your vomses configuration."); VOMSResponse response = null; AttributeCertificate vomsAC = null; for (VOMSServerInfo vomsServerInfo : vomsServerInfos) { requestListener.notifyVOMSRequestStart(request, vomsServerInfo); // Try HTTP request first response = doRequest(httpProtocol, vomsServerInfo, credential, request); // If failed, try legacy request if (response == null && legacyProtocolEnabled) { response = doRequest(legacyProtocol, vomsServerInfo, credential, request); } if (response == null) { if (legacyProtocolEnabled) { requestListener.notifyVOMSRequestFailure(request, vomsServerInfo, new VOMSError("REST and legacy VOMS endpoints failed.")); } continue; } // Notify that the server was contacted successfully requestListener.notifyVOMSRequestSuccess(request, vomsServerInfo); // Notify errors handleErrorsInResponse(request, vomsServerInfo, response); // Notify warnings handleWarningsInResponse(request, vomsServerInfo, response); vomsAC = getACFromResponse(request, response); // Exit the loop only when succesfully get an AC // out of the VOMS server if (!response.hasErrors() && vomsAC != null) { return vomsAC; } } // if we reach this point we had failures in contacting // all known voms server for the VO requestListener.notifyVOMSRequestFailure(request, null, null); return null; } /** * Get VOMS server endpoint information that matches with the {@link VOMSACRequest} passed as * argument. * * This method returns a random shuffle of the {@link VOMSServerInfo} objects that match the input * request. * * @param request the request * @return a possibly empty {@link List} of {@link VOMSServerInfo} objects */ protected List getVOMSServerInfos(VOMSACRequest request) { List vomsServerInfos = new ArrayList(serverInfoStore.getVOMSServerInfo(request.getVoName())); if (!vomsServerInfos.isEmpty()) { Collections.shuffle(vomsServerInfos); } return vomsServerInfos; } /** * Creates a {@link DefaultVOMSACService} object. The {@link DefaultVOMSACService} parameters can * be set with the appropriate methods. Example: * *
   * 
   * 
   * 
   * {
   *   @code
   *   VOMSACService acService =
   *       new DefaultVOMSACService.Builder(certChainValidator).requestListener(requestListener)
   *         .serverInfoStoreListener(serverInfoStoreListener)
   *         .protocolListener(protocolListener)
   *         .build();
   * }
   * 
* * */ public static class Builder { /** * The listener that will be informed about request events */ private VOMSRequestListener requestListener = NullListener.INSTANCE; /** * The listener that will be informed about low-level protocol details */ private VOMSProtocolListener protocolListener = NullListener.INSTANCE; /** * The listener that will be informed about server info store events */ private VOMSServerInfoStoreListener storeListener = NullListener.INSTANCE; /** * The validator used for the SSL handshake */ private X509CertChainValidatorExt validator; /** * The store used to keep VOMS server contact information. */ private VOMSServerInfoStore serverInfoStore; /** * The provided strategy to lookup vomses information. */ private VOMSESLookupStrategy vomsesLookupStrategy; /** * A list of paths where vomses information will be looked for, used to create the server info * store. */ private List vomsesLocations; /** * The connect timeout value */ private int connectTimeout = AbstractVOMSProtocol.DEFAULT_CONNECT_TIMEOUT; /** * The read timeout used */ private int readTimeout = AbstractVOMSProtocol.DEFAULT_READ_TIMEOUT; /** * Whether the client should skip hostname checking */ private boolean skipHostnameChecks = true; /** * The http protocol implementation */ protected VOMSProtocol httpProtocol; /** * The voms legacy protocol implementation */ protected VOMSProtocol legacyProtocol; /** * Whether the client should attempt legacy protocol requests */ private boolean legacyProtocolEnabled = false; /** * Creates a Builder for a {@link DefaultVOMSACService}. * * @param certChainValidator the validator to use to setup the SSL connection and validate the * certificates */ public Builder(X509CertChainValidatorExt certChainValidator) { if (certChainValidator == null) throw new NullPointerException("Please provide a non-null certificate chain validator"); this.validator = certChainValidator; } /** * Sets the request listener for the {@link DefaultVOMSACService} that this builder is creating * * @param l the request listener that will receive notifications about request events * @return this {@link Builder} instance */ public Builder requestListener(VOMSRequestListener l) { this.requestListener = l; return this; } /** * Sets the {@link VOMSServerInfoStoreListener} for the {@link DefaultVOMSACService} that this * builder is creating * * @param sl the store listener that will receive notifications about store events * @return this {@link Builder} instance */ public Builder serverInfoStoreListener(VOMSServerInfoStoreListener sl) { this.storeListener = sl; return this; } /** * Sets the {@link VOMSServerInfoStore} for the {@link DefaultVOMSACService} that this builder * is creating * * @param sis a {@link VOMSServerInfoStore} object * @return this {@link Builder} instance */ public Builder serverInfoStore(VOMSServerInfoStore sis) { this.serverInfoStore = sis; return this; } /** * Sets the {@link VOMSProtocolListener} for the {@link DefaultVOMSACService} that this builder * is creating * * @param pl the {@link VOMSProtocolListener} that will receive notifications about protocol * events * @return this {@link Builder} instance */ public Builder protocolListener(VOMSProtocolListener pl) { this.protocolListener = pl; return this; } /** * Sets the connect timeout (in millisecods) for the {@link DefaultVOMSACService} that this * builder is creating * * @param timeout the timeout value in milliseconds * @return this {@link Builder} instance */ public Builder connectTimeout(int timeout) { this.connectTimeout = timeout; return this; } /** * Sets the read timeout (in milliseconds) for the {@link DefaultVOMSACService} that this * builder is creating * * @param timeout the timeout value in milliseconds * @return this {@link Builder} instance */ public Builder readTimeout(int timeout) { this.readTimeout = timeout; return this; } /** * Sets a flag to skip VOMS hostname checking. Allows for creative VOMS server side certificate * configuration. * * @param s true to skip the checks, false otherwise * * @return this {@link Builder} instance */ public Builder skipHostnameChecks(boolean s) { this.skipHostnameChecks = s; return this; } /** * Sets the vomses lookup strategy for the {@link DefaultVOMSACService} that this builder is * creating * * @param strategy the {@link VOMSESLookupStrategy} object * @return this {@link Builder} instance */ public Builder vomsesLookupStrategy(VOMSESLookupStrategy strategy) { this.vomsesLookupStrategy = strategy; return this; } /** * Sets a list of locations that will be used to build a {@link VOMSESLookupStrategy} for the * {@link DefaultVOMSACService} that this builder is creating * * @param vomsesLocations a list of paths where vomses information will be looked for * @return this {@link Builder} instance */ public Builder vomsesLocations(List vomsesLocations) { this.vomsesLocations = vomsesLocations; return this; } /** * Sets the http protocol implementation * * @param httpProtocol the http protocol implementatino * @return this {@link Builder} instance */ public Builder httpProtocol(VOMSProtocol httpProtocol) { this.httpProtocol = httpProtocol; return this; } /** * Sets the legacy protocol implementation * * @param legacyProtocol the legacy protocol implementation * * @return the {@link Builder} */ public Builder legacyProtocol(VOMSProtocol legacyProtocol) { this.legacyProtocol = legacyProtocol; return this; } /** * Enables/disables the fallback the VOMS legacy protocol. * * @param lpe true to enable the legacy protocol, false otherwise * * @return this {@link Builder} instance */ public Builder legacyProtocolEnabled(boolean lpe) { this.legacyProtocolEnabled = lpe; return this; } /** * Builds the server info store */ protected void buildServerInfoStore() { if (serverInfoStore != null) return; serverInfoStore = new DefaultVOMSServerInfoStore.Builder().lookupStrategy(vomsesLookupStrategy) .storeListener(storeListener) .vomsesPaths(vomsesLocations) .build(); } /** * Builds default protocols if needed */ protected void buildProtocols() { if (httpProtocol == null) { RESTProtocol p = new RESTProtocol(validator, protocolListener, connectTimeout, readTimeout); p.setSkipHostnameChecks(skipHostnameChecks); httpProtocol = p; } if (legacyProtocol == null) { LegacyProtocol p = new LegacyProtocol(validator, protocolListener, connectTimeout, readTimeout); p.setSkipHostnameChecks(skipHostnameChecks); legacyProtocol = p; } } /** * Builds the {@link DefaultVOMSACService} * * @return a {@link DefaultVOMSACService} configured as required by this builder */ public DefaultVOMSACService build() { buildServerInfoStore(); buildProtocols(); return new DefaultVOMSACService(this); } } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/impl/DefaultVOMSESLookupStrategy.java000066400000000000000000000014421477577347300334550ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request.impl; import java.util.Arrays; /** * Default VOMSES information lookup strategy. * * This implementation looks for vomses information in the following paths: *
    *
  • /etc/vomses *
  • ${user.home}/.glite/vomses *
  • ${user.home}/.voms/vomses *
* * @author Andrea Ceccanti * */ public class DefaultVOMSESLookupStrategy extends BaseVOMSESLookupStrategy { public static final String DEFAULT_VOMSES_DIR = "/etc/vomses"; public DefaultVOMSESLookupStrategy() { super(Arrays.asList(DEFAULT_VOMSES_DIR, System.getProperty("user.home") + "/.glite/vomses", System.getProperty("user.home") + "/.voms/vomses")); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/impl/DefaultVOMSServerInfo.java000066400000000000000000000051101477577347300323070ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request.impl; import java.net.URI; import org.italiangrid.voms.request.VOMSServerInfo; /** * The default implementation of the {@link VOMSServerInfo} endpoint * information. * * @author andreaceccanti * */ public class DefaultVOMSServerInfo implements VOMSServerInfo { /** The VOMS server alias **/ String alias; /** The VO name **/ String voName; /** The VOMS server URI **/ URI URL; /** The VOMS server certificate subject **/ String vomsServerDN; public DefaultVOMSServerInfo() { } public String getAlias() { return alias; } public void setAlias(String alias) { this.alias = alias; } public String getVoName() { return voName; } public void setVoName(String voName) { this.voName = voName; } public String getVOMSServerDN() { return vomsServerDN; } public void setVOMSServerDN(String vomsServerDN) { this.vomsServerDN = vomsServerDN; } public URI getURL() { return URL; } public void setURL(URI uRL) { URL = uRL; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((URL == null) ? 0 : URL.hashCode()); result = prime * result + ((alias == null) ? 0 : alias.hashCode()); result = prime * result + ((voName == null) ? 0 : voName.hashCode()); result = prime * result + ((vomsServerDN == null) ? 0 : vomsServerDN.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; DefaultVOMSServerInfo other = (DefaultVOMSServerInfo) obj; if (URL == null) { if (other.URL != null) return false; } else if (!URL.equals(other.URL)) return false; if (alias == null) { if (other.alias != null) return false; } else if (!alias.equals(other.alias)) return false; if (voName == null) { if (other.voName != null) return false; } else if (!voName.equals(other.voName)) return false; if (vomsServerDN == null) { if (other.vomsServerDN != null) return false; } else if (!vomsServerDN.equals(other.vomsServerDN)) return false; return true; } @Override public String toString() { return "VOMSServerInfo [alias=" + alias + ", voName=" + voName + ", URL=" + URL + ", vomsServerDN=" + vomsServerDN + "]"; } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/impl/DefaultVOMSServerInfoStore.java000066400000000000000000000141431477577347300333320ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request.impl; import java.io.File; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import org.italiangrid.voms.request.VOMSESLookupStrategy; import org.italiangrid.voms.request.VOMSESParser; import org.italiangrid.voms.request.VOMSESParserFactory; import org.italiangrid.voms.request.VOMSServerInfo; import org.italiangrid.voms.request.VOMSServerInfoStore; import org.italiangrid.voms.request.VOMSServerInfoStoreListener; import org.italiangrid.voms.util.NullListener; /** * * A {@link DefaultVOMSServerInfoStore} organizes voms servers found in vomses * configuration files in map keyed by vo alias. This way is easy to know which * servers acts as replicas for the same vos. * * @author Andrea Ceccanti * * */ public class DefaultVOMSServerInfoStore implements VOMSServerInfoStore { private VOMSESLookupStrategy lookupStrategy; private VOMSServerInfoStoreListener listener; protected Map> serverInfoStore = new TreeMap>(); private VOMSESParser vomsesParser; private DefaultVOMSServerInfoStore(Builder b) { this.lookupStrategy = b.lookupStrategy; this.listener = b.listener; this.vomsesParser = b.vomsesParser; initializeStore(); } public void addVOMSServerInfo(VOMSServerInfo info) { addVOMSServerInfo(info, null); } private void addVOMSServerInfo(VOMSServerInfo info, String path) { if (serverInfoStore.containsKey(info.getAlias())) { serverInfoStore.get(info.getAlias()).add(info); } else { Set siCont = new HashSet(); siCont.add(info); serverInfoStore.put(info.getAlias(), siCont); } listener.notifyVOMSESInformationLoaded(path, info); } public Set getVOMSServerInfo() { Set allEntries = new HashSet(); for (Map.Entry> entry : serverInfoStore .entrySet()) allEntries.addAll(entry.getValue()); return allEntries; } public Set getVOMSServerInfo(String voName) { Set result = serverInfoStore.get(voName); if (result == null) { result = Collections.emptySet(); } return result; } private void initializeStore() { List vomsesPaths = lookupStrategy.lookupVomsesInfo(); if (vomsesPaths.isEmpty()) listener.notifyNoValidVOMSESError(lookupStrategy.searchedPaths()); for (File f : vomsesPaths) { listener.notifyVOMSESlookup(f.getAbsolutePath()); List vomsServerInfo = vomsesParser.parse(f); for (VOMSServerInfo si : vomsServerInfo) { addVOMSServerInfo(si, f.getAbsolutePath()); } } } /** * Creates a {@link DefaultVOMSServerInfoStore}. The * {@link DefaultVOMSServerInfoStore} parameters can be set with the * appropriate methods. Example: * *
   * 
   * {
   *   @code
   *   VOMSServerInfoStore serverInfoStore = new DefaultVOMSServerInfoStore.Builder()
   *     .storeListener(storeListener).vomsesPaths(vomsesLocations).build();
   * };
   * 
* */ public static class Builder { /** * A list of paths where vomses information will be looked for */ private List vomsesPaths; /** * The {@link VOMSESLookupStrategy} that will be used to lookup vomses * information */ private VOMSESLookupStrategy lookupStrategy; /** * The listener that will be notified of interesting store events */ private VOMSServerInfoStoreListener listener = NullListener.INSTANCE; /** * The parser implementation used to parse VOMSES files */ private VOMSESParser vomsesParser = VOMSESParserFactory.newVOMSESParser(); public Builder() { } /** * Sets the {@link VOMSESLookupStrategy} that will be used to lookup vomses * information for the {@link DefaultVOMSServerInfoStore} that this builder * is creating * * @param strategy * The strategy that will be used to lookup vomses information * @return this {@link Builder} instance */ public Builder lookupStrategy(VOMSESLookupStrategy strategy) { this.lookupStrategy = strategy; return this; } /** * Sets the {@link VOMSServerInfoStoreListener} that will receive * store-related notifications for the {@link DefaultVOMSServerInfoStore} * that this builder is creating * * @param l * the listener * @return this {@link Builder} instance */ public Builder storeListener(VOMSServerInfoStoreListener l) { this.listener = l; return this; } /** * Sets the {@link VOMSESParser} implementation that will be used to parse * vomses files * * @param p * the parser * @return this {@link Builder} instance */ public Builder vomsesParser(VOMSESParser p) { this.vomsesParser = p; return this; } /** * Sets a list of paths where vomses files will be looked up by the * {@link DefaultVOMSServerInfoStore} that this builder is creating * * @param paths * a list of paths * @return this {@link Builder} instance */ public Builder vomsesPaths(List paths) { this.vomsesPaths = paths; return this; } private void buildLookupStrategy() { if (lookupStrategy != null) return; if (vomsesPaths != null) lookupStrategy = new BaseVOMSESLookupStrategy(vomsesPaths); else lookupStrategy = new DefaultVOMSESLookupStrategy(); } /** * Builds the {@link DefaultVOMSServerInfoStore} * * @return a {@link DefaultVOMSServerInfoStore} configured as required by * this builder */ public DefaultVOMSServerInfoStore build() { buildLookupStrategy(); return new DefaultVOMSServerInfoStore(this); } } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/impl/FakeVOMSACService.java000066400000000000000000000117641477577347300313270ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request.impl; import static org.italiangrid.voms.request.impl.FakeVOMSACServiceProperties.AA_CERT; import static org.italiangrid.voms.request.impl.FakeVOMSACServiceProperties.AA_KEY; import java.math.BigInteger; import java.net.URI; import java.net.URISyntaxException; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Objects; import org.bouncycastle.asn1.x509.AttributeCertificate; import org.bouncycastle.cert.X509AttributeCertificateHolder; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.asn1.VOMSACGenerator; import org.italiangrid.voms.request.VOMSACRequest; import org.italiangrid.voms.request.VOMSACService; import org.italiangrid.voms.request.VOMSRequestListener; import org.italiangrid.voms.request.VOMSServerInfo; import eu.emi.security.authn.x509.X509Credential; import eu.emi.security.authn.x509.impl.PEMCredential; public class FakeVOMSACService implements VOMSACService { final VOMSACGenerator acGenerator; final VOMSRequestListener listener; ACGenerationParams acParams; long acSerialNumber = 0; private FakeVOMSACService(X509Credential aaCredential, ACGenerationParams acParams, VOMSRequestListener listener) { this.acGenerator = new VOMSACGenerator(aaCredential); this.listener = listener; this.acParams = acParams; } private VOMSServerInfo buildFakeServerInfo(String vo, String host, int port) throws URISyntaxException { DefaultVOMSServerInfo info = new DefaultVOMSServerInfo(); info.setAlias("Fake local VOMS server"); info.setVoName(vo); String vomsUri = String.format("voms://%s:%d", host, port); info.setURL(new URI(vomsUri)); return info; } protected X509AttributeCertificateHolder buildAC(X509Credential credential, VOMSACRequest request) { Calendar cal = Calendar.getInstance(); Date now = cal.getTime(); List fqans = request.getRequestedFQANs(); if (Objects.isNull(fqans) || fqans.isEmpty()) { fqans = acParams.getFqans(); } String vo = request.getVoName(); if (Objects.isNull(vo)) { vo = acParams.getVo(); } BigInteger serialNo = acParams.getSerialNo(); if (Objects.isNull(serialNo)) { serialNo = BigInteger.valueOf(acSerialNumber++); } Date notBefore = acParams.getNotBefore(); if (Objects.isNull(notBefore)) { notBefore = now; } Date notAfter = acParams.getNotAfter(); if (Objects.isNull(notAfter)) { cal.add(Calendar.SECOND, request.getLifetime()); notAfter = cal.getTime(); } try { VOMSServerInfo fakeEndpoint = buildFakeServerInfo(vo, acParams.getHost(), acParams.getPort()); listener.notifyVOMSRequestStart(request, fakeEndpoint); X509AttributeCertificateHolder ac = acGenerator.generateVOMSAttributeCertificate(fqans, acParams.getGas(), request.getTargets(), credential.getCertificate(), serialNo, notBefore, notAfter, vo, acParams.getHost(), acParams.getPort()); listener.notifyVOMSRequestSuccess(request, fakeEndpoint); return ac; } catch (URISyntaxException e) { throw new VOMSError(e.getMessage(), e); } } @Override public AttributeCertificate getVOMSAttributeCertificate(X509Credential credential, VOMSACRequest request) { X509AttributeCertificateHolder acHolder = buildAC(credential, request); return acHolder.toASN1Structure(); } public ACGenerationParams getAcParams() { return acParams; } public void setAcParams(ACGenerationParams acParams) { this.acParams = acParams; } public long getAcSerialNumber() { return acSerialNumber; } public void setAcSerialNumber(long acSerialNumber) { this.acSerialNumber = acSerialNumber; } public static FakeVOMSACService newInstance(X509Credential aaCredential, ACGenerationParams params, VOMSRequestListener listener) { return new FakeVOMSACService(aaCredential, params, listener); } public static FakeVOMSACService newInstanceFromProperties(VOMSRequestListener listener) { String aaCert = AA_CERT.getSystemPropertyValue(); String aaKey = AA_KEY.getSystemPropertyValue(); if (Objects.isNull(aaCert)) { throw new VOMSError( String.format("%s is not set", FakeVOMSACServiceProperties.AA_CERT.name())); } if (Objects.isNull(aaKey)) { throw new VOMSError( String.format("%s is not set", FakeVOMSACServiceProperties.AA_KEY.name())); } try { PEMCredential aaCredential = new PEMCredential(aaKey, aaCert, null); ACGenerationParams acParams = ACGenerationParams.fromSystemProperties(); return new FakeVOMSACService(aaCredential, acParams, listener); } catch (Exception e) { String errorMsg = String.format("Error loading VOMS fake AC AA credential from '%s' and '%s': %s", aaKey, aaCert, e.getMessage()); throw new VOMSError(errorMsg, e); } } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/impl/FakeVOMSACServiceProperties.java000066400000000000000000000021441477577347300333740ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request.impl; public enum FakeVOMSACServiceProperties { FAKE("voms.fake"), AA_CERT("voms.fake.aaCert", "/etc/grid-security/hostcert.pem"), AA_KEY("voms.fake.aaKey", "/etc/grid-security/hostkey.pem"), VO("voms.fake.vo", "test"), FQANS("voms.fake.fqans", "/test"), GAS("voms.fake.gas"), HOST("voms.fake.host", "voms.example"), PORT("voms.fake.port", "15000"), NOT_BEFORE("voms.fake.notBefore"), NOT_AFTER("voms.fake.notAfter"), SERIAL("voms.fake.serial", "0"); private String propertyName; private String defaultValue; private FakeVOMSACServiceProperties(String propName, String defaultValue) { this.propertyName = propName; this.defaultValue = defaultValue; } private FakeVOMSACServiceProperties(String propName) { this(propName, null); } public String getPropertyName() { return propertyName; } public String getSystemPropertyValue() { return System.getProperty(getPropertyName(), defaultValue); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/impl/GoodACDecodingStrategy.java000066400000000000000000000006571477577347300325020ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request.impl; import org.bouncycastle.util.encoders.Base64; import org.italiangrid.voms.request.ACDecodingStrategy; public class GoodACDecodingStrategy implements ACDecodingStrategy { public byte[] decode(String ac) { return Base64.decode(ac.trim().replaceAll("\n", "")); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/impl/LegacyProtocol.java000066400000000000000000000061271477577347300311520ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request.impl; import java.io.IOException; import java.io.InputStream; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import org.italiangrid.voms.request.VOMSACRequest; import org.italiangrid.voms.request.VOMSProtocol; import org.italiangrid.voms.request.VOMSProtocolError; import org.italiangrid.voms.request.VOMSProtocolListener; import org.italiangrid.voms.request.VOMSResponse; import org.italiangrid.voms.request.VOMSServerInfo; import eu.emi.security.authn.x509.X509CertChainValidatorExt; import eu.emi.security.authn.x509.X509Credential; import eu.emi.security.authn.x509.impl.CertificateUtils; import eu.emi.security.authn.x509.impl.FormatMode; import eu.emi.security.authn.x509.impl.HostnameMismatchCallback2; /** * Protocol implementing the legacy interface. * * */ public class LegacyProtocol extends AbstractVOMSProtocol implements VOMSProtocol, HostnameMismatchCallback2 { public LegacyProtocol(X509CertChainValidatorExt validator, VOMSProtocolListener listener, int connectTimeout, int readTimeout) { super(validator, listener, connectTimeout, readTimeout); } public synchronized VOMSResponse doRequest(VOMSServerInfo endpoint, X509Credential credential, VOMSACRequest request) { SSLSocketFactory sslSocketFactory = getSSLSocketFactory(credential); SSLSocket sslSocket = null; try { sslSocket = (SSLSocket) sslSocketFactory.createSocket(); sslSocket.setSoTimeout(readTimeout); sslSocket.setEnabledProtocols(VOMS_LEGACY_ENABLED_PROTOCOLS); SocketAddress sa = new InetSocketAddress(endpoint.getURL().getHost(), endpoint.getURL().getPort()); sslSocket.connect(sa, connectTimeout); } catch (Throwable t) { throw new VOMSProtocolError(t.getMessage(), endpoint, request, credential, t); } LegacyRequestSender protocol = LegacyRequestSender.instance(listener); VOMSResponse response = null; try { protocol.sendRequest(request, endpoint, sslSocket.getOutputStream()); InputStream inputStream = sslSocket.getInputStream(); response = new LegacyVOMSResponseParsingStrategy().parse(inputStream); sslSocket.close(); } catch (IOException e) { throw new VOMSProtocolError(e.getMessage(), endpoint, request, credential, e); } listener.notifyReceivedResponse(response); return response; } @Override public void nameMismatch(X509Certificate peerCertificate, String hostName) throws CertificateException { String peerCertString = CertificateUtils.format(peerCertificate, FormatMode.MEDIUM_ONE_LINE); String message = String .format( "No subject alternative DNS name matching %s found. Peer certificate : %s", hostName, peerCertString); throw new CertificateException(message); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/impl/LegacyRequestSender.java000066400000000000000000000056761477577347300321520ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request.impl; import java.io.OutputStream; import java.io.StringWriter; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.request.VOMSACRequest; import org.italiangrid.voms.request.VOMSProtocolListener; import org.italiangrid.voms.request.VOMSServerInfo; import org.w3c.dom.Document; /** * This class manages the client-side communication protocol with the VOMS * server. * * @author Andrea Ceccanti * */ public class LegacyRequestSender { private VOMSRequestFactory requestFactory = VOMSRequestFactory.instance(); private TransformerFactory transformerFactory; private VOMSProtocolListener listener; private LegacyRequestSender(VOMSProtocolListener listener) { transformerFactory = TransformerFactory.newInstance(); this.listener = listener; } public static LegacyRequestSender instance(VOMSProtocolListener listener) { return new LegacyRequestSender(listener); } protected String xmlDocAsString(Document doc) { Transformer transformer; try { transformer = transformerFactory.newTransformer(); } catch (TransformerConfigurationException e) { throw new VOMSError(e.getMessage(), e); } StringWriter writer = new StringWriter(); DOMSource source = new DOMSource(doc); StreamResult res = new StreamResult(writer); try { transformer.transform(source, res); } catch (TransformerException e) { throw new VOMSError(e.getMessage(), e); } writer.flush(); return writer.toString(); } /** * * This method is used to send a request to a VOMS server. * * * @param acRequest * the AC request parameters. See {@link VOMSACRequest}. * @param endpoint * the {@link VOMSServerInfo} endpoint to use for this * request * @param stream * an output stream. */ public void sendRequest(VOMSACRequest acRequest, VOMSServerInfo endpoint, OutputStream stream) { Document request = requestFactory.buildRequest(acRequest, endpoint); Transformer transformer; try { transformer = transformerFactory.newTransformer(); } catch (TransformerConfigurationException e) { throw new VOMSError(e.getMessage(), e); } listener.notifyLegacyRequest(xmlDocAsString(request)); DOMSource source = new DOMSource(request); StreamResult res = new StreamResult(stream); try { transformer.transform(source, res); stream.flush(); } catch (Exception e) { throw new VOMSError(e.getMessage(), e); } } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/impl/LegacyVOMSESParserImpl.java000066400000000000000000000106241477577347300323610ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request.impl; import java.io.BufferedReader; import java.io.File; import java.io.FileFilter; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.Reader; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.request.VOMSESParser; import org.italiangrid.voms.request.VOMSServerInfo; /** * Implementation of the {@link org.italiangrid.voms.request.VOMSESParser} interface. * This class is responsible for parsing VOMSES configuration files and extracting * {@link org.italiangrid.voms.request.VOMSServerInfo} instances from them. * *

It supports parsing from files, directories, and readers, and ensures that * the VOMSES files exist and are readable before processing.

* *

VOMSES files typically contain server connection information in a structured format.

*/ public class LegacyVOMSESParserImpl implements VOMSESParser { /** * Line parser used to process individual VOMSES lines. */ private final VOMSESLineParser lineParser = new VOMSESLineParser(); /** * Performs basic sanity checks on the provided file. * * @param f the file to check * @throws VOMSError if the file does not exist or is not readable */ protected void fileSanityChecks(File f) { if (!f.exists()) { throw new VOMSError("VOMSES file does not exist: " + f.getAbsolutePath()); } if (!f.canRead()) { throw new VOMSError("VOMSES file is not readable: " + f.getAbsolutePath()); } } /** * Parses a single line from a VOMSES file. * * @param vomsesLine the line to parse * @return a {@link VOMSServerInfo} instance representing the parsed line * @throws URISyntaxException if the URI in the line is malformed */ protected VOMSServerInfo parseLine(String vomsesLine) throws URISyntaxException { return lineParser.parse(vomsesLine); } /** * Parses VOMSES configuration from a {@link Reader}. * * @param vomsesReader the reader containing VOMSES configuration * @return a list of {@link VOMSServerInfo} instances extracted from the input */ public List parse(Reader vomsesReader) { BufferedReader reader = new BufferedReader(vomsesReader); String line = null; List result = new ArrayList(); try { while ((line = reader.readLine()) != null) { // Ignore comments if (line.startsWith("#")) continue; // skip empty lines if (line.matches("\\s*$")) continue; VOMSServerInfo parsedInfo = parseLine(line); if (parsedInfo != null) result.add(parsedInfo); } } catch (Exception e) { throw new VOMSError("Error parsing VOMSES information...", e); } return result; } /** * Parses all VOMSES files in a given directory. * * @param directory the directory containing VOMSES files * @return a list of {@link VOMSServerInfo} instances parsed from the directory */ protected List parseDirectory(File directory) { Set joinedServerInfo = new HashSet(); File[] certFiles = directory.listFiles(new FileFilter() { public boolean accept(File pathname) { return pathname.isFile() && !pathname.getName().startsWith("."); } }); for (File f : certFiles) joinedServerInfo.addAll(parse(f)); return new ArrayList(joinedServerInfo); } /** * Parses a VOMSES file or directory. * * @param f the file or directory to parse * @return a list of {@link VOMSServerInfo} instances parsed from the file/directory * @throws VOMSError if the file is not found or an error occurs during parsing */ public List parse(File f) { fileSanityChecks(f); if (f.isDirectory()) return parseDirectory(f); try { BufferedReader r = new BufferedReader(new FileReader(f)); return parse(r); } catch (FileNotFoundException e) { throw new VOMSError("VOMSES file not found: " + f.getAbsolutePath(), e); } catch (VOMSError e) { throw new VOMSError("Error parsing VOMSES file: " + f.getAbsolutePath(), e); } } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/impl/LegacyVOMSResponse.java000066400000000000000000000100501477577347300316420ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request.impl; import java.util.ArrayList; import java.util.List; import org.italiangrid.voms.request.VOMSErrorMessage; import org.italiangrid.voms.request.VOMSResponse; import org.italiangrid.voms.request.VOMSWarningMessage; import org.italiangrid.voms.util.VOMSBase64Decoder; import org.italiangrid.voms.util.XMLUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; public class LegacyVOMSResponse implements VOMSResponse { private static int ERROR_OFFSET = 1000; protected Document xmlResponse; /** * Builds a VOMSResponse starting from a DOM an XML document (see * {@link Document}). * * @param res * the XML document for the response */ public LegacyVOMSResponse(Document res) { xmlResponse = res; } /* * (non-Javadoc) * * @see org.glite.voms.contact.VOMSResponseIF#getVersion() */ public int getVersion() { Element versionElement = (Element) xmlResponse.getElementsByTagName( "version").item(0); if (versionElement == null) { return 0; } return Integer.parseInt(versionElement.getFirstChild().getNodeValue()); } /* * (non-Javadoc) * * @see org.glite.voms.contact.VOMSResponseIF#hasErrors() */ public boolean hasErrors() { return errorMessages() != null; } /* * (non-Javadoc) * * @see org.glite.voms.contact.VOMSResponseIF#hasWarnings() */ public boolean hasWarnings() { return warningMessages() != null; } /* * (non-Javadoc) * * @see org.glite.voms.contact.VOMSResponseIF#getAC() */ public byte[] getAC() { Element acElement = (Element) xmlResponse.getElementsByTagName("ac") .item(0); byte[] ac = VOMSBase64Decoder.decode(acElement.getFirstChild() .getNodeValue()); if (ac == null) ac = new GoodACDecodingStrategy().decode(acElement.getFirstChild() .getNodeValue()); return ac; } /* * (non-Javadoc) * * @see org.glite.voms.contact.VOMSResponseIF#errorMessages() */ public VOMSErrorMessage[] errorMessages() { NodeList nodes = xmlResponse.getElementsByTagName("item"); if (nodes.getLength() == 0) return null; List errorList = new ArrayList(); for (int i = 0; i < nodes.getLength(); i++) { Element itemElement = (Element) nodes.item(i); Element numberElement = (Element) itemElement.getElementsByTagName( "number").item(0); Element messageElement = (Element) itemElement.getElementsByTagName( "message").item(0); int number = Integer.parseInt(numberElement.getFirstChild() .getNodeValue()); if (number >= ERROR_OFFSET) errorList.add(new VOMSErrorMessage(number, messageElement .getFirstChild().getNodeValue())); } if (errorList.isEmpty()) return null; return errorList.toArray(new VOMSErrorMessage[errorList.size()]); } public VOMSWarningMessage[] warningMessages() { NodeList nodes = xmlResponse.getElementsByTagName("item"); if (nodes.getLength() == 0) return null; List warningList = new ArrayList(); for (int i = 0; i < nodes.getLength(); i++) { Element itemElement = (Element) nodes.item(i); Element numberElement = (Element) itemElement.getElementsByTagName( "number").item(0); Element messageElement = (Element) itemElement.getElementsByTagName( "message").item(0); int number = Integer.parseInt(numberElement.getFirstChild() .getNodeValue()); if (number < ERROR_OFFSET) warningList.add(new VOMSWarningMessage(number, messageElement .getFirstChild().getNodeValue())); } if (warningList.isEmpty()) return null; return warningList.toArray(new VOMSWarningMessage[warningList.size()]); } public String getXMLAsString() { return XMLUtils.documentAsString(xmlResponse); } } LegacyVOMSResponseParsingStrategy.java000066400000000000000000000026041477577347300346400ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/impl// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request.impl; import java.io.InputStream; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.request.VOMSResponse; import org.italiangrid.voms.request.VOMSResponseParsingStrategy; import org.w3c.dom.Document; /** * Parsing strategy for legacy VOMS responses. * * @author valerioventuri * */ public class LegacyVOMSResponseParsingStrategy implements VOMSResponseParsingStrategy { protected DocumentBuilder documentBuilder; public LegacyVOMSResponseParsingStrategy() { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setIgnoringComments(true); factory.setNamespaceAware(false); factory.setValidating(false); try { documentBuilder = factory.newDocumentBuilder(); } catch (ParserConfigurationException e) { throw new VOMSError(e.getMessage(), e); } } public VOMSResponse parse(InputStream inputStream) { try { Document document = documentBuilder.parse(inputStream); return new LegacyVOMSResponse(document); } catch (Exception e) { throw new VOMSError(e.getMessage()); } } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/impl/RESTProtocol.java000066400000000000000000000054751477577347300305300ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request.impl; import java.io.IOException; import java.io.InputStream; import java.net.URL; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLSession; import org.italiangrid.voms.request.VOMSACRequest; import org.italiangrid.voms.request.VOMSProtocol; import org.italiangrid.voms.request.VOMSProtocolError; import org.italiangrid.voms.request.VOMSProtocolListener; import org.italiangrid.voms.request.VOMSResponse; import org.italiangrid.voms.request.VOMSServerInfo; import eu.emi.security.authn.x509.X509CertChainValidatorExt; import eu.emi.security.authn.x509.X509Credential; /** * Protocol implementing the REST-style interface. * * @author valerioventuri * */ public class RESTProtocol extends AbstractVOMSProtocol implements VOMSProtocol { public RESTProtocol(X509CertChainValidatorExt validator, VOMSProtocolListener listener, int connectTimeout, int readTimeout) { super(validator, listener, connectTimeout, readTimeout); } public VOMSResponse doRequest(VOMSServerInfo endpoint, X509Credential credential, VOMSACRequest request) { RESTServiceURLBuilder restQueryBuilder = new RESTServiceURLBuilder(); URL serviceUrl = restQueryBuilder.build(endpoint, request); RESTVOMSResponseParsingStrategy responseParsingStrategy = new RESTVOMSResponseParsingStrategy(); HttpsURLConnection connection = null; try { connection = (HttpsURLConnection) serviceUrl.openConnection(); if (isSkipHostnameChecks()){ connection.setHostnameVerifier(new HostnameVerifier() { public boolean verify(String arg0, SSLSession arg1) { return true; } }); } connection.setConnectTimeout(connectTimeout); connection.setReadTimeout(readTimeout); } catch (IOException e) { throw new VOMSProtocolError(e.getMessage(), endpoint, request, credential, e); } connection.setSSLSocketFactory(getSSLSocketFactory(credential)); listener.notifyHTTPRequest(serviceUrl.toExternalForm()); try { connection.connect(); } catch (IOException e) { throw new VOMSProtocolError(e.getMessage(), endpoint, request, credential, e); } InputStream is = null; try { if (connection.getResponseCode() != 200) { is = connection.getErrorStream(); } else is = connection.getInputStream(); } catch (IOException e) { throw new VOMSProtocolError(e.getMessage(), endpoint, request, credential, e); } VOMSResponse response = responseParsingStrategy.parse(is); listener.notifyReceivedResponse(response); connection.disconnect(); return response; } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/impl/RESTServiceURLBuilder.java000066400000000000000000000044501477577347300322110ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request.impl; import java.net.MalformedURLException; import java.net.URL; import java.util.Iterator; import java.util.List; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.request.VOMSACRequest; import org.italiangrid.voms.request.VOMSServerInfo; /** * An helper class which builds a URL suitable for an HTTPS VOMS REST request * starting from the VOMS URI as available in a {@link VOMSServerInfo} object. * * @author Valerio Venturi * */ public class RESTServiceURLBuilder { public URL build(VOMSServerInfo endpoint, VOMSACRequest request) { URL url = null; try { url = new URL("https", endpoint.getURL().getHost(), endpoint.getURL() .getPort(), buildPath(endpoint, request)); } catch (MalformedURLException e) { throw new VOMSError("Malformed URI: " + e.getMessage()); } return url; } private String buildPath(VOMSServerInfo endpoint, VOMSACRequest request) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("/generate-ac?fqans="); if (request.getRequestedFQANs().isEmpty()) { // Take voname from endpoint info stringBuilder.append("/" + endpoint.getVoName()); } else { List FQANs = request.getRequestedFQANs(); Iterator i = FQANs.iterator(); boolean first = true; while (i.hasNext()) { if (!first) stringBuilder.append(","); stringBuilder.append((String) i.next()); first = false; } } String targetString = targetListAsCommaSeparatedList(request.getTargets()); if (targetString != null && targetString.trim().length() != 0) { stringBuilder.append("&targets="); stringBuilder.append(targetString); } stringBuilder.append("&lifetime="); stringBuilder.append(request.getLifetime()); return stringBuilder.toString(); } private String targetListAsCommaSeparatedList(List targets) { StringBuilder targetStringBuilder = new StringBuilder(); for (String target : targets) { targetStringBuilder.append(target); targetStringBuilder.append(','); } return targetStringBuilder.toString(); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/impl/RESTVOMSResponse.java000066400000000000000000000113701477577347300312210ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request.impl; import org.italiangrid.voms.request.ACDecodingStrategy; import org.italiangrid.voms.request.VOMSErrorMessage; import org.italiangrid.voms.request.VOMSResponse; import org.italiangrid.voms.request.VOMSWarningMessage; import org.italiangrid.voms.util.XMLUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; /** * * This class is used to parse and represent VOMS server responses coming from a RESTful VOMS * service. * */ public class RESTVOMSResponse implements VOMSResponse { private static int ERROR_OFFSET = 1000; /** The XML response document from the VOMS server. */ protected Document xmlResponse; /** * Constructs a {@code RESTVOMSResponse} with the given XML response document. * * @param res the XML response document */ public RESTVOMSResponse(Document res) { xmlResponse = res; } /** * Retrieves the version of the VOMS response. * * @return the version number, or 0 if not found */ public int getVersion() { Element versionElement = (Element) xmlResponse.getElementsByTagName("version").item(0); if (versionElement == null) { return 0; } return Integer.parseInt(versionElement.getFirstChild().getNodeValue()); } /** * Checks if the response contains errors. * * @return {@code true} if errors are present, {@code false} otherwise */ public boolean hasErrors() { return xmlResponse.getElementsByTagName("error").getLength() != 0; } /** * Checks if the response contains warnings. * * @return {@code true} if warnings are present, {@code false} otherwise */ public boolean hasWarnings() { return xmlResponse.getElementsByTagName("warning").getLength() != 0; } /** * Retrieves the attribute certificate (AC) from the response. * * @return the decoded AC as a byte array, or {@code null} if not found */ public byte[] getAC() { Element acElement = (Element) xmlResponse.getElementsByTagName("ac").item(0); if (acElement == null || !acElement.hasChildNodes()) { return null; } String acString = acElement.getFirstChild().getNodeValue(); ACDecodingStrategy acDecodingStrategy = new GoodACDecodingStrategy(); return acDecodingStrategy.decode(acString); } /** * Retrieves error messages from the response. * * @return an array of {@link VOMSErrorMessage} objects, or {@code null} if no errors are found */ public VOMSErrorMessage[] errorMessages() { NodeList nodes = xmlResponse.getElementsByTagName("error"); if (nodes.getLength() == 0) { return null; } VOMSErrorMessage[] result = new VOMSErrorMessage[nodes.getLength()]; for (int i = 0; i < nodes.getLength(); i++) { Element itemElement = (Element) nodes.item(i); Element codeElement = (Element) itemElement.getElementsByTagName("code").item(0); Element messageElement = (Element) itemElement.getElementsByTagName("message").item(0); String strcode = codeElement.getFirstChild().getNodeValue(); int code; if (strcode.equals("NoSuchUser")) { code = 1001; } else if (strcode.equals("BadRequest")) { code = 1005; } else if (strcode.equals("SuspendedUser")) { code = 1004; } else { // InternalError code = 1006; } result[i] = new VOMSErrorMessage(code, messageElement.getFirstChild().getNodeValue()); } return result; } /** * Retrieves warning messages from the response. * * @return an array of {@link VOMSWarningMessage} objects, or {@code null} if no warnings are * found */ public VOMSWarningMessage[] warningMessages() { NodeList nodes = xmlResponse.getElementsByTagName("warning"); if (nodes.getLength() == 0) { return null; } VOMSWarningMessage[] result = new VOMSWarningMessage[nodes.getLength()]; for (int i = 0; i < nodes.getLength(); i++) { Element itemElement = (Element) nodes.item(i); String message = itemElement.getFirstChild().getNodeValue(); int number; if (message.contains("validity")) { number = 2; } else if (message.contains("selected")) { number = 1; } else if (message.contains("contains attributes")) { number = 3; } else { number = 4; } if (number < ERROR_OFFSET) { result[i] = new VOMSWarningMessage(number, message); } } return result; } /** * Converts the XML response to a string representation. * * @return the XML response as a string */ public String getXMLAsString() { return XMLUtils.documentAsString(xmlResponse); } } RESTVOMSResponseParsingStrategy.java000066400000000000000000000032731477577347300342140ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/impl// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request.impl; import java.io.InputStream; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.request.VOMSResponse; import org.italiangrid.voms.request.VOMSResponseParsingStrategy; import org.w3c.dom.Document; /** * Strategy for parsing a response coming from a RESTFul VOMS. * * @author valerioventuri * */ public class RESTVOMSResponseParsingStrategy implements VOMSResponseParsingStrategy { private DocumentBuilder docBuilder; /** * */ public RESTVOMSResponseParsingStrategy() { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setIgnoringComments(true); factory.setNamespaceAware(false); factory.setValidating(false); try { docBuilder = factory.newDocumentBuilder(); } catch (ParserConfigurationException e) { throw new VOMSError(e.getMessage(), e); } } /** * Parse a response coming from a RESTFul VOMS service and builds a * {@link VOMSResponse} object representing the response. * * @param inputStream * the response coming from the service * @return a {@link VOMSResponse} object representing the response. * */ public VOMSResponse parse(InputStream inputStream) { try { Document document = docBuilder.parse(inputStream); return new RESTVOMSResponse(document); } catch (Exception e) { throw new VOMSError(e.getMessage()); } } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/impl/VOMSESLineParser.java000066400000000000000000000106551477577347300312260ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request.impl; import java.net.URI; import java.net.URISyntaxException; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.request.VOMSServerInfo; /** * A parser for VOMSES lines. * * The VOMSES line format is as follows: * *
 * "alias" "hostname" "port" "server DN" "vo_name"
 * 
* * This parser eats up whitespace and characters outside of quotes and tolerates * an additional quoted field ("globus_version") that was for some time needed. * * * @author andreaceccanti * */ public class VOMSESLineParser { private interface ParserState { void parse(char c); }; private final ParserState outsideQuotes = new ParserState() { public void parse(char c) { if (c == '"') VOMSESLineParser.this.tokenStart(); } }; private final ParserState insideQuotes = new ParserState() { public void parse(char c) { if (c == '"') { VOMSESLineParser.this.tokenEnd(); } else { VOMSESLineParser.this.tokenChar(c); } } }; static final String VOMSES_FIELD_NAMES[] = { "vo alias", "voms host", "voms port", "voms server DN", "vo name", "globus version" }; static final int VO_ALIAS = 0, VOMS_HOST = 1, VOMS_PORT = 2, VOMS_SERVER_DN = 3, VO_NAME = 4, GLOBUS_VERSION = 5; static final int MIN_VOMSES_FIELD_COUNT = 4; private String[] tokens = new String[VOMSES_FIELD_NAMES.length]; private StringBuilder currentToken; private int tokenCount; private boolean tokenComplete; private ParserState currentState; private void lineSanityChecks(String line) { if (line == null) throw new VOMSError("Cannot parse a null VOMSES line"); } private void init() { tokenCount = -1; currentToken = null; tokenComplete = false; currentState = outsideQuotes; for (int i = 0; i < tokens.length; i++) tokens[i] = null; } public VOMSServerInfo parse(String line) { init(); lineSanityChecks(line); if (line.isEmpty()) return null; for (int i = 0; i < line.length(); i++) { char c = line.charAt(i); currentState.parse(c); } if (!tokenComplete) { String msg = String.format( "Invalid VOMSES line: incomplete '%s' field. [line: %s]", VOMSES_FIELD_NAMES[tokenCount], line); throw new VOMSError(msg); } if (tokenCount < MIN_VOMSES_FIELD_COUNT) { String msg = String.format( "Invalid VOMSES line: incomplete information. [line: %s]", line); throw new VOMSError(msg); } DefaultVOMSServerInfo si = new DefaultVOMSServerInfo(); si.setAlias(tokens[VO_ALIAS]); String url = String.format("voms://%s:%s", tokens[VOMS_HOST], tokens[VOMS_PORT]); validateTokens(line); try { si.setURL(new URI(url)); si.setVOMSServerDN(tokens[VOMS_SERVER_DN]); si.setVoName(tokens[VO_NAME]); return si; } catch (URISyntaxException e) { String msg = String.format( "Invalid VOMSES line: cannot build URL for voms " + "service: %s", e.getMessage()); throw new VOMSError(msg); } } private void validateTokens(String line) { // Validate port number try { int portNo = Integer.parseInt(tokens[VOMS_PORT]); if (portNo <= 0 || portNo > 65535) { String msg = String.format( "Invalid VOMSES line: invalid port number: %d. [line: %s]", portNo, line); throw new VOMSError(msg); } } catch (NumberFormatException e) { String msg = String.format("Invalid VOMSES line: invalid port number. " + "[line: %s]. Error: %s", line, e.getMessage()); throw new VOMSError(msg, e); } } public void tokenStart() { if (++tokenCount == VOMSES_FIELD_NAMES.length) throw new VOMSError("Invalid VOMSES line: too many fields!"); currentToken = new StringBuilder(); currentState = insideQuotes; tokenComplete = false; } public void tokenEnd() { if (currentToken.length() != 0) { tokens[tokenCount] = currentToken.toString(); currentState = outsideQuotes; tokenComplete = true; } else { String msg = String.format("Invalid VOMSES line: empty '%s' field.", VOMSES_FIELD_NAMES[tokenCount]); throw new VOMSError(msg); } } public void tokenChar(char c) { currentToken.append(c); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/impl/VOMSRequestFactory.java000066400000000000000000000145361477577347300317140ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.request.impl; import java.util.Iterator; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.request.VOMSACRequest; import org.italiangrid.voms.request.VOMSServerInfo; import org.italiangrid.voms.util.VOMSFQANNamingScheme; import org.w3c.dom.Document; import org.w3c.dom.DocumentFragment; import org.w3c.dom.Element; /** * * This class builds VOMS XML requests starting from {@link VOMSACRequest} * objects. * * @author Andrea Ceccanti * */ public class VOMSRequestFactory { private static volatile VOMSRequestFactory instance = null; private String orderString; private String targetString; private long lifetime = 0; protected DocumentBuilder docBuilder; public synchronized static VOMSRequestFactory instance() { if (instance == null) instance = new VOMSRequestFactory(); return instance; } private VOMSRequestFactory() { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setIgnoringComments(true); factory.setNamespaceAware(false); factory.setValidating(false); try { docBuilder = factory.newDocumentBuilder(); } catch (ParserConfigurationException e) { throw new VOMSError(e.getMessage()); } } public long getLifetime() { return lifetime; } public void setLifetime(long lifetime) { this.lifetime = lifetime; } public String getOrderString() { return orderString; } public void setOrderString(String orderString) { this.orderString = orderString; } public String getTargetString() { return targetString; } public void setTargetString(String targetString) { this.targetString = targetString; } private void setOptionsForRequest(VOMSRequestFragment fragment) { if (orderString != null && orderString != "") fragment.buildOrderElement(orderString); if (targetString != null && targetString != "") fragment.buildTargetsElement(targetString); fragment.buildLifetime(lifetime); } private void loadOptions(VOMSACRequest options) { lifetime = options.getLifetime(); } public Document buildRequest(VOMSACRequest acRequest, VOMSServerInfo endpoint) { loadOptions(acRequest); Document request = docBuilder.newDocument(); VOMSRequestFragment frag = new VOMSRequestFragment(request); if (acRequest.getRequestedFQANs().isEmpty()) { frag.groupCommand("/" + endpoint.getVoName()); setOptionsForRequest(frag); request.appendChild(frag.getFragment()); return request; } Iterator fqanIter = acRequest.getRequestedFQANs().iterator(); frag.buildBase64(); frag.buildVersion(); while (fqanIter.hasNext()) { String FQAN = fqanIter.next(); if (FQAN.equals("all")) { frag.allCommand(); } else if (VOMSFQANNamingScheme.isGroup(FQAN)) { frag.groupCommand(FQAN); } else if (VOMSFQANNamingScheme.isRole(FQAN)) { frag.roleCommand(VOMSFQANNamingScheme.getRoleName(FQAN)); } else if (VOMSFQANNamingScheme.isQualifiedRole(FQAN)) { frag.mappingCommand(VOMSFQANNamingScheme.getGroupName(FQAN), VOMSFQANNamingScheme.getRoleName(FQAN)); } } setOptionsForRequest(frag); request.appendChild(frag.getFragment()); return request; } } /** * Helper class to manage the creation of VOMS XML requests. * * @author andreaceccanti * */ class VOMSRequestFragment { private Document doc; DocumentFragment fragment; Element root; Element command; Element order; Element targets; Element lifetime; Element base64; Element version; public VOMSRequestFragment(Document doc) { this.doc = doc; fragment = doc.createDocumentFragment(); buildRootElement(); } protected void buildRootElement() { root = doc.createElement("voms"); fragment.appendChild(root); } private void appendTextChild(Element e, String text) { e.appendChild(doc.createTextNode(text)); } private String buildCompatibleOrderString(String s) { String[] FQANs = s.split(","); if (FQANs.length == 0) return ""; for (int i = 0; i < FQANs.length; i++) { if (VOMSFQANNamingScheme.isQualifiedRole(FQANs[i])) FQANs[i] = VOMSFQANNamingScheme.toOldQualifiedRoleSyntax(FQANs[i]); } StringBuilder fqansString = new StringBuilder(); for (int i = 0; i < FQANs.length; i++) { fqansString.append(FQANs); if (i < FQANs.length - 1) fqansString.append(","); } return fqansString.toString(); } void buildCommandElement(String cmdString) { command = doc.createElement("command"); appendTextChild(command, cmdString); root.appendChild(command); } void buildOrderElement(String orderString) { order = doc.createElement("order"); // Temporary compatibility hack appendTextChild(order, buildCompatibleOrderString(orderString)); root.appendChild(order); } void buildTargetsElement(String targetString) { targets = doc.createElement("targets"); appendTextChild(targets, targetString); root.appendChild(targets); } void buildLifetime(long lifetime) { buildLifetime(Long.toString(lifetime)); } void buildLifetime(String lifetimeString) { lifetime = doc.createElement("lifetime"); appendTextChild(lifetime, lifetimeString); root.appendChild(lifetime); } void buildBase64() { base64 = doc.createElement("base64"); appendTextChild(base64, "1"); root.appendChild(base64); } void buildVersion() { version = doc.createElement("version"); appendTextChild(version, "4"); root.appendChild(version); } public DocumentFragment getFragment() { return fragment; } public void groupCommand(String groupName) { buildCommandElement("G" + groupName); } public void roleCommand(String roleName) { buildCommandElement("R" + roleName); } public void mappingCommand(String groupName, String roleName) { buildCommandElement("B" + groupName + ":" + roleName); } public void allCommand() { buildCommandElement("A"); } public void listCommand() { buildCommandElement("N"); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/impl/package-info.java000066400000000000000000000003661477577347300305470ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 /** * This package provides the implementation logic for VOMS attributes requests. */ package org.italiangrid.voms.request.impl; voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/request/package-info.java000066400000000000000000000003741477577347300276050ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 /** * This package provides the API for requesting VOMS attribtues from a remote VOMS server. */ package org.italiangrid.voms.request; voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/store/000077500000000000000000000000001477577347300240565ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/store/LSCFileParser.java000066400000000000000000000024261477577347300273230ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.store; import java.io.File; import java.io.InputStream; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.store.impl.LSCFile; /** * This interface defines a parser for VOMS LSC files. * * @author Andrea Ceccanti * */ public interface LSCFileParser { /** * Parses an LSC file. * * @param vo * the name of the VO this LSC file is about * @param hostname * the name of host this LSC file is about * @param file * the LSC file * @return an {@link LSCFile} object * @throws VOMSError * in case of parsing errors */ public LSCFile parse(String vo, String hostname, File file); /** * Parses an LSC file from a generic input stream. * * @param vo * the name of the VO this LSC file is about * @param hostname * the name of host this LSC file is about * @param is * an {@link InputStream} that contains the LSC information * * @return an {@link LSCFile} object * @throws VOMSError * in case of parsing errors */ public LSCFile parse(String vo, String hostname, InputStream is); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/store/LSCInfo.java000066400000000000000000000040261477577347300261600ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.store; import java.security.cert.X509Certificate; import java.util.List; /** * The VOMS LSC information. * * @author Andrea Ceccanti * */ public interface LSCInfo { /** * Sets the name of the file from where this LSC info was parsed from. * * @param filename * the name of the file from where this LSC info was parsed from. */ public void setFilename(String filename); /** * Returns the name of file from where this LSC info was parsed from. * * @return the name of the file from where this LSC info was parsed from. */ public String getFilename(); /** * Returns the VO name this LSC info applies to. * * @return the VO name this LSC info applies to */ public String getVOName(); /** * Returns the host name of the VOMS AA this LSC info applies to. * * @return the host name of the VOMS AA this LSC info applies to */ public String getHostname(); /** * Returns the certificate chain description of the VOMS AA for the given VO * and hostname. * * The certificate chain description is a list of X.500 distinguished names * encoded as strings according to the OpenSSL slash-separated format, as in: * /C=IT/O=INFN/CN=INFN CA * * The first element in the description is the leaf certificate, while the * last is the CA certificate. * * @return the certificate chain description of the VOMS AA for the given VO * and hostname. */ public List getCertificateChainDescription(); /** * Checks if the certificate chain description maintained in the LSC * information matches the certificate chain passed as argument. * * @param certChain * the certificate chain to be checked * @return true if the description matches, false * otherwise */ public boolean matches(X509Certificate[] certChain); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/store/Updateable.java000066400000000000000000000012031477577347300267630ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.store; /** * Represents an object which can be periodically updated according to an update * frequency. * * @author Andrea Ceccanti * */ public interface Updateable { /** * @return the frequency (in milliseconds) currently set for this * {@link Updateable} object. */ public long getUpdateFrequency(); /** * Updates the object. */ public void update(); /** * Cancels the future updates of this {@link Updateable} object. */ public void cancel(); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/store/UpdatingVOMSTrustStore.java000066400000000000000000000005121477577347300312560ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.store; /** * A VOMS trust store that can be periodically refreshed. * * @author Andrea Ceccanti * */ public interface UpdatingVOMSTrustStore extends VOMSTrustStore, Updateable { } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/store/VOMSTrustStore.java000066400000000000000000000053121477577347300275650ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.store; import java.security.cert.X509Certificate; import java.util.List; import java.util.Map; import java.util.Set; import javax.security.auth.x500.X500Principal; /** * The VOMS trust store takes care of parsing local trusted information (being * certificates or LSC files) for known VOMS servers. * * @author Andrea Ceccanti * */ public interface VOMSTrustStore { /** * Returns the locally trusted directories where VOMS trust information (being * VOMS server certificates or LSC files) are searched for. * * @return a {@link List} of local paths */ public List getLocalTrustedDirectories(); /** * Returns the list of VOMS Attribute Authority certificates held in this * {@link VOMSTrustStore}. * * @return the collection of VOMS Attribute Authority certificates held in * this {@link VOMSTrustStore}, an empty list if no certificate was * found. */ public List getLocalAACertificates(); /** * Returns the VOMS Attribute Authority certificate held in this * {@link VOMSTrustStore} whose subject matches the subject passed as * argument. * * @param aaCertSubject * a certificate subject * @return the VOMS AA {@link X509Certificate} that matches the subject passed * as argument or null if no matching certificate is found in this * store */ public X509Certificate getAACertificateBySubject(X500Principal aaCertSubject); /** * Returns the LSC information held in this {@link VOMSTrustStore} for the vo * and hostname passed as arguments. * * @param voName * the name of the VO for which the LSC applies * @param hostname * the name of the host for which the LSC applies * @return a {@link LSCInfo} object, or null if no LSC matching the arguments * was found */ public LSCInfo getLSC(String voName, String hostname); /** * Returns all the LSC information held in this {@link VOMSTrustStore}. The * returned {@link Map} is keyed by VO name. * * @return a possibly empty map {@link LSCInfo} objects */ public Map> getAllLSCInfo(); /** * Loads trust information from the sources configured for this trust store. */ public void loadTrustInformation(); /** * Sets a {@link VOMSTrustStoreStatusListener} that is notified of events * related to this VOMS trust store * * @param statusListener * the status listener that will be notified */ public void setStatusListener(VOMSTrustStoreStatusListener statusListener); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/store/VOMSTrustStoreStatusListener.java000066400000000000000000000027441477577347300325050ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.store; import java.io.File; import java.security.cert.X509Certificate; /** * * This interface used to notify interested listeners in status changes of a * VOMS trust store. * * @author Andrea Ceccanti * */ public interface VOMSTrustStoreStatusListener { /** * Informs that certificates are being looked for in the directory passed as * argument * * @param dir * the directory where certificates are being looked for */ public void notifyCertficateLookupEvent(String dir); /** * Informs that VOMS LSC file information is being looked for in the directory * passed as argument. * * @param dir * the directory where certificates are being looked for */ public void notifyLSCLookupEvent(String dir); /** * Informs that a VOMS AA certificate has been loaded in the store * * @param cert * the VOMS AA certificate loaded * @param f * the file from which the certificate has been loaded */ public void notifyCertificateLoadEvent(X509Certificate cert, File f); /** * Informs that VOMS LSC information has been loaded in the store * * @param lsc * the loaded VOMS LSC information * @param f * the file from which the LSC information has been loaded */ public void notifyLSCLoadEvent(LSCInfo lsc, File f); } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/store/VOMSTrustStores.java000066400000000000000000000042211477577347300277460ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.store; import java.util.List; import org.italiangrid.voms.store.impl.DefaultUpdatingVOMSTrustStore; /** * A factory for VOMS trust stores * * @author cecco * */ public class VOMSTrustStores { /** * Creates a {@link VOMSTrustStore} configured with default settings. * * @return a {@link VOMSTrustStore} configured with default settings. */ public static VOMSTrustStore newTrustStore() { return new DefaultUpdatingVOMSTrustStore(); } /** * Creates a {@link VOMSTrustStore} configured according to the parameters * passed as argument * * @param localTrustDirs * the directory where voms information will be searched * @param updateFrequency * the trust store update frequency in milliseconds * @param statusListener * a listener that is notified of events related to the created trust * store * @return a {@link VOMSTrustStore} configured as requested. */ public static VOMSTrustStore newTrustStore(List localTrustDirs, long updateFrequency, VOMSTrustStoreStatusListener statusListener) { return new DefaultUpdatingVOMSTrustStore(localTrustDirs, updateFrequency, statusListener); } /** * Creates a {@link VOMSTrustStore} configured according to the parameters * passed as argument * * @param localTrustDirs * the directory where voms information will be searched * @return a {@link VOMSTrustStore} configured as requested. */ public static VOMSTrustStore newTrustStore(List localTrustDirs) { return new DefaultUpdatingVOMSTrustStore(localTrustDirs); } /** * Creates a {@link VOMSTrustStore} configured according to the parameters * passed as argument * * @param updateFrequency * the trust store update frequency in milliseconds * @return a {@link VOMSTrustStore} configured as requested. */ public static VOMSTrustStore newTrustStore(long updateFrequency) { return new DefaultUpdatingVOMSTrustStore(updateFrequency); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/store/impl/000077500000000000000000000000001477577347300250175ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/store/impl/DefaultLSCFileParser.java000066400000000000000000000063541477577347300315750ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.store.impl; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.store.LSCFileParser; /** * The default implementation for the LSC file parser. * * @author Andrea Ceccanti * */ public class DefaultLSCFileParser implements LSCFileParser { public static final String MALFORMED_LSC_FILE_ERROR_TEMPLATE = "LSC file parsing error: Malformed LSC file (vo=%s, host=%s): %s"; private void checkFileExistanceAndReadabilty(File f) { if (!f.exists()) { throw new VOMSError("LSC file does not exist: " + f.getAbsolutePath()); } if (!f.canRead()) { throw new VOMSError("LSC file is not readable: " + f.getAbsolutePath()); } } public synchronized LSCFile parse(String vo, String hostname, InputStream is) { final String NEXT_CHAIN = "------NEXT CHAIN------"; LSCFile lsc = new LSCFile(); lsc.setHostname(hostname); lsc.setVo(vo); try (BufferedReader reader = new BufferedReader(new InputStreamReader(is))) { List certificateChainDescription = new ArrayList(); String line; while ((line = reader.readLine()) != null) { if (line.trim().startsWith("#") || line.isBlank()) { continue; } if (line.equalsIgnoreCase(NEXT_CHAIN)) { /* This parser doesn't support multi-chain LSC files */ break; } if (line.startsWith("/")) { certificateChainDescription.add(line); } } validateChain(certificateChainDescription, vo, hostname); lsc.setCertificateChainDescription(certificateChainDescription); } catch (IOException e) { throw new VOMSError("LSC file parsing error: " + e.getMessage(), e); } if (lsc.getCertificateChainDescription().isEmpty()) { String errorMessage = String.format(MALFORMED_LSC_FILE_ERROR_TEMPLATE, vo, hostname, "No chains found."); throw new VOMSError(errorMessage); } return lsc; } private void validateChain(List certificateChainDescription, String vo, String hostname) { if (certificateChainDescription.size() % 2 != 0) { String errorMessage = String.format(MALFORMED_LSC_FILE_ERROR_TEMPLATE, vo, hostname, "Odd number of distinguished name entries."); throw new VOMSError(errorMessage); } if (certificateChainDescription.size() == 0) { String errorMessage = String.format(MALFORMED_LSC_FILE_ERROR_TEMPLATE, vo, hostname, "No distinguished name entries found."); throw new VOMSError(errorMessage); } } public LSCFile parse(String vo, String hostname, File file) { LSCFile lsc = null; try { checkFileExistanceAndReadabilty(file); lsc = parse(vo, hostname, new FileInputStream(file)); lsc.setFilename(file.getAbsolutePath()); } catch (IOException e) { throw new VOMSError("LSC file parsing error: " + e.getMessage(), e); } return lsc; } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/store/impl/DefaultUpdatingVOMSTrustStore.java000066400000000000000000000110241477577347300335240ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.store.impl; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.store.UpdatingVOMSTrustStore; import org.italiangrid.voms.store.VOMSTrustStoreStatusListener; import org.italiangrid.voms.util.NullListener; /** * A VOMS trust store that periodically updates itself. The update frequency is * set once at VOMS trust store creation time. * * * @author Andrea Ceccanti * */ public class DefaultUpdatingVOMSTrustStore extends DefaultVOMSTrustStore implements UpdatingVOMSTrustStore { /** * Default trust store update frequency (10 minutes). */ public static final long DEFAULT_UPDATE_FREQUENCY = TimeUnit.MINUTES .toMillis(10); /** * This trust store update frequency in milliseconds. */ private long updateFrequency; /** * The scheduler used to schedule the update tasks. */ private final ScheduledExecutorService scheduler = Executors .newSingleThreadScheduledExecutor(new VOMSNamedThreadFactory()); /** * Builds a trust store configured as defined in the parameters. * * @param localTrustDirs * where VOMS trust information will be looked for * @param updateFrequency * the update frequency in milliseconds * @param listener * a listener that is notified of interesting events related to this * store */ public DefaultUpdatingVOMSTrustStore(List localTrustDirs, long updateFrequency, VOMSTrustStoreStatusListener listener) { super(localTrustDirs, listener); updateFrequencySanityChecks(updateFrequency); this.updateFrequency = updateFrequency; scheduleUpdate(); } /** * Builds a trust store configured as defined in the parameters. * * @param updateFrequency * the update frequency in milliseconds * */ public DefaultUpdatingVOMSTrustStore(long updateFrequency) { this(buildDefaultTrustedDirs(), updateFrequency, NullListener.INSTANCE); } /** * Builds a trust store configured as defined in the parameters. * * @param localTrustDirs * where VOMS trust information will be looked for * @param updateFrequency * the update frequency in milliseconds * */ public DefaultUpdatingVOMSTrustStore(List localTrustDirs, long updateFrequency) { this(localTrustDirs, updateFrequency, NullListener.INSTANCE); } /** * Builds a trust store configured as defined in the parameters. * * @param localTrustDirs * where VOMS trust information will be looked for */ public DefaultUpdatingVOMSTrustStore(List localTrustDirs) { this(localTrustDirs, DEFAULT_UPDATE_FREQUENCY, NullListener.INSTANCE); } /** * Builds a trust store. VOMS information will be searched in the default VOMS * dir location ({@link DefaultVOMSTrustStore#DEFAULT_VOMS_DIR}). * * This store will be refreshed according to the value of * {@link #DEFAULT_UPDATE_FREQUENCY}. */ public DefaultUpdatingVOMSTrustStore() { this(buildDefaultTrustedDirs(), DEFAULT_UPDATE_FREQUENCY, NullListener.INSTANCE); } protected void updateFrequencySanityChecks(long updateFrequency) { if (updateFrequency <= 0) throw new VOMSError( "Please provide a positive value for this store update frequency!"); } protected void scheduleUpdate() { write.lock(); try { long frequency = getUpdateFrequency(); scheduler.scheduleWithFixedDelay(new Runnable() { // Just run update on the VOMS trust store and log any error public void run() { update(); } }, frequency, // First execution delay frequency, // Next iterations delay TimeUnit.MILLISECONDS); } finally { write.unlock(); } } /** * Returns the update frequency, in milliseconds, for this store. */ public long getUpdateFrequency() { read.lock(); try { return updateFrequency; } finally { read.unlock(); } } /** * Updates the information in this store */ public void update() { loadTrustInformation(); } /** * Cancel the background tasks which updates this store. */ public void cancel() { write.lock(); try { scheduler.shutdownNow(); } finally { write.unlock(); } } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/store/impl/DefaultVOMSTrustStore.java000066400000000000000000000270641477577347300320430ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.store.impl; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.FilenameFilter; import java.io.IOException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import javax.security.auth.x500.X500Principal; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.store.LSCInfo; import org.italiangrid.voms.store.VOMSTrustStore; import org.italiangrid.voms.store.VOMSTrustStoreStatusListener; import org.italiangrid.voms.util.NullListener; import eu.emi.security.authn.x509.helpers.trust.OpensslTruststoreHelper; import eu.emi.security.authn.x509.impl.CertificateUtils; import eu.emi.security.authn.x509.impl.CertificateUtils.Encoding; /** * * The default implementation for the VOMS trust store. This implementation * does not refresh the trust information on a periodic basis. For an * updating trust store see {@link DefaultUpdatingVOMSTrustStore}. * * @author Andrea Ceccanti * */ public class DefaultVOMSTrustStore implements VOMSTrustStore { /** * The default directory where local VOMS trust information is rooted: * {@value #DEFAULT_VOMS_DIR} **/ public static final String DEFAULT_VOMS_DIR = "/etc/grid-security/vomsdir"; /** * The filename suffix used to match certificates in the VOMS local trust * directories **/ public static final String CERTIFICATE_FILENAME_SUFFIX = ".pem"; /** * The filename suffix used to match LSC files in the VOMS local trust * directories **/ public static final String LSC_FILENAME_SUFFIX = ".lsc"; /** * The list of local trusted directories that is searched for trust * information (certs or LSC files) **/ private final List localTrustedDirs; /** Map of local parsed AA certificates keyed by certificate subject hash **/ private Map localAACertificatesByHash = new HashMap(); /** The set of local parsed LSC information keyed by VO **/ private Map> localLSCInfo = new HashMap>(); /** * The trust store status listener that will be notified of changes in this * trust store **/ private VOMSTrustStoreStatusListener listener; /** The read/write lock that implements thread safety for this store **/ protected final ReadWriteLock rwLock = new ReentrantReadWriteLock(); /** A reference to the read lock **/ protected final Lock read = rwLock.readLock(); /** A reference to the write lock **/ protected final Lock write = rwLock.writeLock(); /** A lock to guard the setting of the status listener **/ protected final Object listenerLock = new Object(); /** * Builds a list of trusted directories containing only * {@link #DEFAULT_VOMS_DIR}. * * @return a list of default trusted directory containing the * {@link #DEFAULT_VOMS_DIR} **/ protected static List buildDefaultTrustedDirs() { List tDirs = new ArrayList(); tDirs.add(DEFAULT_VOMS_DIR); return tDirs; } /** * * @param localTrustDirs * a non-null list of local trust directories * @param listener * the {@link VOMSTrustStoreStatusListener} to use for this trust * store * @throws IllegalArgumentException * when the list passed as argument is null * */ public DefaultVOMSTrustStore(List localTrustDirs, VOMSTrustStoreStatusListener listener) { if (localTrustDirs == null) throw new IllegalArgumentException( "Please provide a non-null list of local trust directories!"); this.localTrustedDirs = localTrustDirs; this.listener = listener; loadTrustInformation(); } public DefaultVOMSTrustStore(VOMSTrustStoreStatusListener listener) { this(buildDefaultTrustedDirs(), listener); } public DefaultVOMSTrustStore(List localTrustDirs) { this(localTrustDirs, NullListener.INSTANCE); } /** * Default constructor. * * Sets the local trusted directories to the default of * {@value #DEFAULT_VOMS_DIR}. * * */ public DefaultVOMSTrustStore() { this(buildDefaultTrustedDirs()); } public List getLocalTrustedDirectories() { read.lock(); try { return localTrustedDirs; } finally { read.unlock(); } } public List getLocalAACertificates() { read.lock(); try { return Collections.unmodifiableList(new ArrayList( localAACertificatesByHash.values())); } finally { read.unlock(); } } public LSCInfo getLSC(String voName, String hostname) { read.lock(); try { Set candidates = localLSCInfo.get(voName); if (candidates == null) return null; for (LSCInfo lsc : candidates) { if (lsc.getHostname().equals(hostname)) return lsc; } return null; } finally { read.unlock(); } } /** * Loads all the certificates in the local directory. Only files with the * extension matching the {@link #CERTIFICATE_FILENAME_PATTERN} are * considered. * * @param directory */ private void loadCertificatesFromDirectory(File directory) { directorySanityChecks(directory); synchronized (listenerLock) { listener.notifyCertficateLookupEvent(directory.getAbsolutePath()); } File[] certFiles = directory.listFiles(new FilenameFilter() { public boolean accept(File dir, String name) { return name.endsWith(CERTIFICATE_FILENAME_SUFFIX); } }); for (File f : certFiles) loadCertificateFromFile(f); } /** * Loads a VOMS AA certificate from a given file and stores this certificate * in the local map of trusted VOMS AA certificate. * * @param file */ private void loadCertificateFromFile(File file) { certificateFileSanityChecks(file); try { X509Certificate aaCert = CertificateUtils.loadCertificate( new FileInputStream(file), Encoding.PEM); // Get certificate subject hash, using the CANL implementation for CA // files String aaCertHash = getOpensslCAHash(aaCert.getSubjectX500Principal()); // Store certificate in the local map localAACertificatesByHash.put(aaCertHash, aaCert); synchronized (listenerLock) { listener.notifyCertificateLoadEvent(aaCert, file); } } catch (IOException e) { String errorMessage = String.format( "Error parsing VOMS trusted certificate from %s. Reason: %s", file.getAbsolutePath(), e.getMessage()); throw new VOMSError(errorMessage, e); } } /** * * @param directory */ private void loadLSCFromDirectory(File directory) { directorySanityChecks(directory); synchronized (listenerLock) { listener.notifyLSCLookupEvent(directory.getAbsolutePath()); } File[] lscFiles = directory.listFiles(new FilenameFilter() { public boolean accept(File dir, String name) { return name.endsWith(LSC_FILENAME_SUFFIX); } }); if (lscFiles.length == 0) return; DefaultLSCFileParser lscParser = new DefaultLSCFileParser(); // In the VOMS trust anchor structure, LSC files are contained in a // directory named // as the VO the LSC belongs to String voName = directory.getName(); for (File lsc : lscFiles) { String lscFileName = lsc.getName(); // In the VOMS trust anchor structure, LSC files are named as // .lsc where hostname // is the name of host where the VOMS AA is running String hostname = lscFileName.substring(0, lscFileName.indexOf(LSC_FILENAME_SUFFIX)); LSCInfo info = null; info = lscParser.parse(voName, hostname, lsc); Set localLscForVo = localLSCInfo.get(voName); if (localLscForVo == null) { localLscForVo = new HashSet(); localLSCInfo.put(voName, localLscForVo); } localLscForVo.add(info); listener.notifyLSCLoadEvent(info, lsc); } } /** * Performs basic sanity checks performed on a file supposed to hold a VOMS AA * certificate. * * @param certFile */ private void certificateFileSanityChecks(File certFile) { if (!certFile.exists()) throw new VOMSError("Local VOMS trusted certificate does not exist:" + certFile.getAbsolutePath()); if (!certFile.canRead()) throw new VOMSError("Local VOMS trusted certificate is not readable:" + certFile.getAbsolutePath()); } /** * Performs basic sanity checks on a directory that is supposed to contain * VOMS AA certificates and LSC files. * * @param directory */ private void directorySanityChecks(File directory) { if (!directory.exists()) throw new VOMSError("Local trust directory does not exists:" + directory.getAbsolutePath()); if (!directory.isDirectory()) throw new VOMSError("Local trust directory is not a directory:" + directory.getAbsolutePath()); if (!directory.canRead()) throw new VOMSError("Local trust directory is not readable:" + directory.getAbsolutePath()); if (!directory.canExecute()) throw new VOMSError("Local trust directory is not traversable:" + directory.getAbsolutePath()); } private void cleanupStores() { localAACertificatesByHash.clear(); localLSCInfo.clear(); } public void loadTrustInformation() { write.lock(); try { if (localTrustedDirs.isEmpty()) { throw new VOMSError( "No local trust directory was specified for this trust store. Please provide at least one path where LSC and VOMS service certificates will be searched for."); } cleanupStores(); for (String localDir : localTrustedDirs) { File baseTrustDir = new File(localDir); // Legacy VOMS dir structure put all the certificates in the base trust // directory loadCertificatesFromDirectory(baseTrustDir); // Load LSC and certificates files starting from each of the // sub-directory of the starting trust info directory File[] voDirs = baseTrustDir.listFiles(new FileFilter() { public boolean accept(File pathname) { return pathname.isDirectory(); } }); for (File voDir : voDirs) { loadLSCFromDirectory(voDir); loadCertificatesFromDirectory(voDir); } } } finally { write.unlock(); } } private String getOpensslCAHash(X500Principal principal) { return OpensslTruststoreHelper.getOpenSSLCAHash(principal, false); } public X509Certificate getAACertificateBySubject(X500Principal aaCertSubject) { read.lock(); try { String theCertHash = getOpensslCAHash(aaCertSubject); return localAACertificatesByHash.get(theCertHash); } finally { read.unlock(); } } public Map> getAllLSCInfo() { read.lock(); try { return Collections.unmodifiableMap(localLSCInfo); } finally { read.unlock(); } } public void setStatusListener(VOMSTrustStoreStatusListener statusListener) { synchronized (listenerLock) { this.listener = statusListener; } } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/store/impl/LSCFile.java000066400000000000000000000127611477577347300271120ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.store.impl; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import javax.security.auth.x500.X500Principal; import org.italiangrid.voms.store.LSCInfo; import eu.emi.security.authn.x509.impl.OpensslNameUtils; import eu.emi.security.authn.x509.impl.X500NameUtils; /** * Represents a VOMS LSC (Legacy Secure Channel) file. * *

The LSC file describes the certificate chain that a VOMS attribute authority * uses to sign a VOMS attribute certificate. The LSC mechanism helps in solving * the public key distribution problem for VOMS AA certificates and is used in * the VOMS validation process to validate the signature on the AC. It does this by * extracting the VOMS AA certificate included in the VOMS extension and ensuring * that the chain conforms to the description in the LSC file.

* *

Two {@link LSCFile} objects are considered equal if their VO and hostname fields match.

* */ public class LSCFile implements LSCInfo { /** The LSC filename. */ String filename; /** The VO (Virtual Organization) this LSC file is associated with. */ String vo; /** The hostname that this LSC file pertains to. */ String hostname; /** The certificate chain description contained in this LSC file. */ List certChainDescription = new ArrayList<>(); /** * Returns the VO name. * * @return the VO name */ public String getVOName() { return vo; } /** * Returns the hostname. * * @return the hostname */ public String getHostname() { return hostname; } /** * Returns the certificate chain description. * * @return a list of certificate chain descriptions */ public List getCertificateChainDescription() { return certChainDescription; } /** * Returns the filename of the LSC file. * * @return the LSC filename */ public String getFilename() { return filename; } /** * Sets the filename for this LSC file. * * @param filename the filename to set */ public void setFilename(String filename) { this.filename = filename; } /** * Sets the VO name. * * @param vo the VO name to set */ public void setVo(String vo) { this.vo = vo; } /** * Sets the hostname. * * @param hostname the hostname to set */ public void setHostname(String hostname) { this.hostname = hostname; } /** * Sets the certificate chain description. * * @param certChainDesc the certificate chain description to set */ public void setCertificateChainDescription(List certChainDesc) { this.certChainDescription = new ArrayList<>(certChainDesc); } /** * Computes the hash code for this LSC file. * * @return the hash code */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((hostname == null) ? 0 : hostname.hashCode()); result = prime * result + ((vo == null) ? 0 : vo.hashCode()); return result; } /** * Determines if two {@code LSCFile} objects are equal based on their VO and hostname. * * @param obj the object to compare with * @return {@code true} if the objects are equal, otherwise {@code false} */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; LSCFile other = (LSCFile) obj; if (hostname == null) { if (other.hostname != null) return false; } else if (!hostname.equals(other.hostname)) return false; if (vo == null) { if (other.vo != null) return false; } else if (!vo.equals(other.vo)) return false; return true; } /** * Returns a string representation of this LSC file. * * @return a string representation of this LSC file */ @Override public String toString() { return "LSCFile [filename=" + filename + ", vo=" + vo + ", hostname=" + hostname + ", certChainDescription=" + certChainDescription + "]"; } /** * Checks if the given certificate chain matches the description in this LSC file. * * @param certChain the certificate chain to verify * @return {@code true} if the certificate chain matches, otherwise {@code false} */ public boolean matches(X509Certificate[] certChain) { if (certChainDescription == null || certChainDescription.isEmpty()) { return false; } if (certChain == null || certChain.length == 0) { return false; } if (certChainDescription.size() != certChain.length * 2) { return false; } for (int i = 0; i < certChain.length; i++) { if (!matches(certChain[i].getSubjectX500Principal(), certChainDescription.get(2 * i))) { return false; } if (!matches(certChain[i].getIssuerX500Principal(), certChainDescription.get(2 * i + 1))) { return false; } } return true; } /** * Checks if a certificate distinguished name (DN) matches the expected DN in the LSC file. * * @param certDn the certificate DN * @param lscDn the expected DN in the LSC file * @return {@code true} if the DNs match, otherwise {@code false} */ @SuppressWarnings("deprecation") private boolean matches(X500Principal certDn, String lscDn) { return X500NameUtils.equal(certDn, OpensslNameUtils.opensslToRfc2253(lscDn)); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/store/impl/VOMSNamedThreadFactory.java000066400000000000000000000016271477577347300321010ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.store.impl; import java.lang.Thread.UncaughtExceptionHandler; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; /** * A simple thread factory to create named VOMS background threads. * * @author Andrea Ceccanti * */ public class VOMSNamedThreadFactory implements ThreadFactory { private static final AtomicInteger created = new AtomicInteger(); private static final String poolBaseName = "voms-thread"; private UncaughtExceptionHandler handler; public VOMSNamedThreadFactory(UncaughtExceptionHandler h) { this.handler = h; } public VOMSNamedThreadFactory() { } public Thread newThread(Runnable r) { return new VOMSThread(r, poolBaseName + "-" + created.incrementAndGet(), handler); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/store/impl/VOMSThread.java000066400000000000000000000016161477577347300276020ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.store.impl; /** * An helper class to create a named VOMS thread. This class just sets the name * for the thread and set an {@link java.lang.Thread.UncaughtExceptionHandler} * which logs the caught exception. * * @author Andrea Ceccanti * */ public class VOMSThread extends Thread { /** * Default constructor. * * @param target * the object whose run method is called. * @param name * the name of the new thread. * @param handler * the {@link java.lang.Thread.UncaughtExceptionHandler} * used for this thread */ public VOMSThread(Runnable target, String name, UncaughtExceptionHandler handler) { super(target, name); setUncaughtExceptionHandler(handler); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/store/impl/package-info.java000066400000000000000000000003571477577347300302130ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 /** * This package provides the implementation of VOMS trust store management. */ package org.italiangrid.voms.store.impl; voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/store/package-info.java000066400000000000000000000003371477577347300272500ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 /** * This package provides the API for managing VOMS trust stores. */ package org.italiangrid.voms.store; voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/util/000077500000000000000000000000001477577347300236775ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/util/CachingCertificateValidator.java000066400000000000000000000250011477577347300321050ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.util; import java.security.cert.CertPath; import java.security.cert.X509Certificate; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.italiangrid.voms.VOMSError; import eu.emi.security.authn.x509.ProxySupport; import eu.emi.security.authn.x509.RevocationParameters; import eu.emi.security.authn.x509.StoreUpdateListener; import eu.emi.security.authn.x509.ValidationErrorListener; import eu.emi.security.authn.x509.ValidationResult; import eu.emi.security.authn.x509.X509CertChainValidatorExt; import eu.emi.security.authn.x509.impl.CertificateUtils; import eu.emi.security.authn.x509.impl.FormatMode; /** * A Certificate validator that caches validation results for a configurable * period of time. The cache is keyed by the fingerprint of the certificate at * the top of the chain (likely the EEC). * * * @author andreaceccanti * */ public class CachingCertificateValidator implements X509CertChainValidatorExt { /** * Simple concurrent cache for validation results */ protected final ConcurrentMap validationResultsCache; /** * The wrapped CANL certificate validator */ protected final X509CertChainValidatorExt validator; /** * The cache entry lifetime for this validator */ protected final long cacheEntryLifetimeMsec; /** * Builds a caching validator wrapping the validator passed as argument. * * @param val * The CANL validator to be wrapped. * @param maxCacheEntryLifetime * the maximum cache entry lifetime (in msecs) */ public CachingCertificateValidator(X509CertChainValidatorExt val, long maxCacheEntryLifetime) { cacheEntryLifetimeMsec = maxCacheEntryLifetime; validator = val; validationResultsCache = new ConcurrentHashMap(); } /** * Checks whether the {@link CachedValidationResult} passed as argument has * expired with respect to the {@link #cacheEntryLifetimeMsec} defined for * this validator and the reference time passed as argument. * * @param cvr * a {@link CachedValidationResult} object * @param referenceTime * the reference time (msecs since the epoch) * @return true when expired, false otherwise */ public boolean cachedValidationResultHasExpired(CachedValidationResult cvr, long referenceTime) { return (referenceTime - cvr.getTimestamp() > cacheEntryLifetimeMsec); } /** * Gets a validation result from the memory cache * * @param certFingerprint * the certificate fingerprint for the certificate at the top of the * chain * @return the validation result, if found. null otherwise. */ protected ValidationResult getCachedResult(String certFingerprint) { CachedValidationResult cvr = validationResultsCache.get(certFingerprint); if (cvr == null) return null; if (!cachedValidationResultHasExpired(cvr, System.currentTimeMillis())) { return cvr.getResult(); } validationResultsCache.remove(certFingerprint, cvr); return null; } /** * Obvious sanity checks on input certificate chain * * @param certChain * the chain to be checked */ private void certChainSanityChecks(X509Certificate[] certChain) { if (certChain == null) throw new IllegalArgumentException("Cannot validate a null cert chain."); if (certChain.length == 0) throw new IllegalArgumentException( "Cannot validate a cert chain of length 0."); } /** * Validates a certificate chain using the wrapped validator, caching the * result for future validation calls. * * @param certChain * the certificate chain that will be validated * @return a possibly cached {@link ValidationResult} * @see eu.emi.security.authn.x509.X509CertChainValidator#validate(java.security.cert.X509Certificate[]) */ public ValidationResult validate(X509Certificate[] certChain) { certChainSanityChecks(certChain); String certFingerprint = null; try { certFingerprint = FingerprintHelper .getFingerprint(certChain[certChain.length - 1]); } catch (Throwable t) { String errorMsg = String.format("Error computing fingerprint for " + "certificate: %s. Cause: %s", CertificateUtils.format(certChain[0], FormatMode.COMPACT_ONE_LINE), t.getMessage()); throw new VOMSError(errorMsg, t); } ValidationResult res = getCachedResult(certFingerprint); if (res == null) { res = validator.validate(certChain); validationResultsCache.putIfAbsent(certFingerprint, new CachedValidationResult(certFingerprint, res)); } return res; } /** * @see eu.emi.security.authn.x509.X509CertChainValidatorExt#dispose() */ public void dispose() { validator.dispose(); } /** * @return the proxy support information * @see eu.emi.security.authn.x509.X509CertChainValidatorExt#getProxySupport() */ public ProxySupport getProxySupport() { return validator.getProxySupport(); } /** * @param certPath * the certificate path that will be validated * @return the {@link ValidationResult} * @see eu.emi.security.authn.x509.X509CertChainValidator#validate(java.security.cert.CertPath) */ public ValidationResult validate(CertPath certPath) { return validator.validate(certPath); } /** * @return revocation parameters for the wrapped validator * @see eu.emi.security.authn.x509.X509CertChainValidatorExt#getRevocationCheckingMode() */ public RevocationParameters getRevocationCheckingMode() { return validator.getRevocationCheckingMode(); } /** * @return trusted issuers from the wrapped validator * @see eu.emi.security.authn.x509.X509CertChainValidator#getTrustedIssuers() */ public X509Certificate[] getTrustedIssuers() { return validator.getTrustedIssuers(); } /** * @param listener * the {@link ValidationErrorListener} to be added to this validator * * @see eu.emi.security.authn.x509.X509CertChainValidator#addValidationListener(eu.emi.security.authn.x509.ValidationErrorListener) */ public void addValidationListener(ValidationErrorListener listener) { validator.addValidationListener(listener); } /** * @param listener * the {@link ValidationErrorListener} that must be removed from * this validator * @see eu.emi.security.authn.x509.X509CertChainValidator#removeValidationListener(eu.emi.security.authn.x509.ValidationErrorListener) */ public void removeValidationListener(ValidationErrorListener listener) { validator.removeValidationListener(listener); } /** * @param listener * the {@link StoreUpdateListener} that must be added to this * validator * * @see eu.emi.security.authn.x509.X509CertChainValidator#addUpdateListener(eu.emi.security.authn.x509.StoreUpdateListener) */ public void addUpdateListener(StoreUpdateListener listener) { validator.addUpdateListener(listener); } /** * @param listener * the {@link StoreUpdateListener} that must be removed from this * validator * * @see eu.emi.security.authn.x509.X509CertChainValidator#removeUpdateListener(eu.emi.security.authn.x509.StoreUpdateListener) */ public void removeUpdateListener(StoreUpdateListener listener) { validator.removeUpdateListener(listener); } } /** * A validation result cache entry. * * @author cecco * */ class CachedValidationResult { /** * Default constructor. * * @param certificateFingerprint * the certificate fingerprint for this entry * @param res * the validation result */ public CachedValidationResult(String certificateFingerprint, ValidationResult res) { certFingerprint = certificateFingerprint; result = res; timestamp = System.currentTimeMillis(); } /** The certificate fingerprint for this cache entry **/ private String certFingerprint; /** The validation result for this cache entry **/ private ValidationResult result; /** The cache entry creation timestamp **/ private long timestamp; /** * Returns the validation result for this entry. * * @return a {@link ValidationResult} */ public ValidationResult getResult() { return result; } /** * Sets the validation result for this entry * * @param result * a {@link ValidationResult} */ public void setResult(ValidationResult result) { this.result = result; } /** * Returns this entry creation timestamp. * * @return the timestamp expressed as milliseconds since epoch */ public long getTimestamp() { return timestamp; } /** * Sets this entry creation timestamp (in milliseconds since the epoch). * * @param timestamp * the timestamp */ public void setTimestamp(long timestamp) { this.timestamp = timestamp; } /** * Returns the certificate fingerprint for this entry. * * The certificate fingerprint is the SHA1 hash of the DER encoding of the * certificate. * * * * @return the fingerprint for this entry * @see FingerprintHelper */ public String getCertFingerprint() { return certFingerprint; } /** * * Sets the certificate finger for this entry. The certificate fingerprint is * the SHA1 hash of the DER encoding of the certificate. * * It can be computed with the * {@link FingerprintHelper#getFingerprint(X509Certificate)} method. * * @param certFingerprint * a certificate fingerprint describing a certificate */ public void setCertFingerprint(String certFingerprint) { this.certFingerprint = certFingerprint; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((certFingerprint == null) ? 0 : certFingerprint.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; CachedValidationResult other = (CachedValidationResult) obj; if (certFingerprint == null) { if (other.certFingerprint != null) return false; } else if (!certFingerprint.equals(other.certFingerprint)) return false; return true; } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/util/CertificateValidatorBuilder.java000066400000000000000000000426151477577347300321510ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.util; import java.util.Arrays; import org.italiangrid.voms.ac.impl.DefaultVOMSValidator; import eu.emi.security.authn.x509.CrlCheckingMode; import eu.emi.security.authn.x509.NamespaceCheckingMode; import eu.emi.security.authn.x509.OCSPCheckingMode; import eu.emi.security.authn.x509.OCSPParametes; import eu.emi.security.authn.x509.ProxySupport; import eu.emi.security.authn.x509.StoreUpdateListener; import eu.emi.security.authn.x509.ValidationErrorListener; import eu.emi.security.authn.x509.X509CertChainValidatorExt; import eu.emi.security.authn.x509.impl.CRLParameters; import eu.emi.security.authn.x509.impl.OpensslCertChainValidator; import eu.emi.security.authn.x509.impl.RevocationParametersExt; import eu.emi.security.authn.x509.impl.ValidatorParamsExt; /** * A utility class which provides convenient methods to build a certificate * validator with defaults that are meaningful for VOMS usage. * * @author cecco * */ public class CertificateValidatorBuilder { /** * This enum determine which hash function is configured for the canl * {@link OpensslCertChainValidator} to resolve CRLs and other trust anchors * files. */ public static enum OpensslHashFunction { MD5, SHA1 }; /** * The default Openssl hash function value. MD5 is chosen to ensure * compatibility with Openssl pre 1.0 deployments. */ public static final OpensslHashFunction DEFAULT_OPENSSL_HASH_FUNCTION = OpensslHashFunction.MD5; /** * The default CRL checking policy. */ public static final CrlCheckingMode DEFAULT_CRL_CHECKS = CrlCheckingMode.IF_VALID; /** * The default OCSP checking policy. */ public static final OCSPCheckingMode DEFAULT_OCSP_CHECKS = OCSPCheckingMode.IGNORE; /** * The default namespace checking policy. */ public static final NamespaceCheckingMode DEFAULT_NS_CHECKS = NamespaceCheckingMode.GLOBUS_EUGRIDPMA; /** * The default trust anchors directory. */ public static final String DEFAULT_TRUST_ANCHORS_DIR = "/etc/grid-security/certificates"; /** * By default this builder builds non-lazy validators */ public static final Boolean DEFAULT_VALIDATOR_IS_LAZY = Boolean.FALSE; /** * Default validator trust anchor update interval. */ public static final long DEFAULT_TRUST_ANCHORS_UPDATE_INTERVAL = 0L; private String trustAnchorsDir = DEFAULT_TRUST_ANCHORS_DIR; private ValidationErrorListener validationErrorListener = null; private StoreUpdateListener storeUpdateListener = null; private long trustAnchorsUpdateInterval = DEFAULT_TRUST_ANCHORS_UPDATE_INTERVAL; private boolean lazyAnchorsLoading = DEFAULT_VALIDATOR_IS_LAZY; private NamespaceCheckingMode namespaceChecks = DEFAULT_NS_CHECKS; private CrlCheckingMode crlChecks = DEFAULT_CRL_CHECKS; private OCSPCheckingMode ocspChecks = DEFAULT_OCSP_CHECKS; private OpensslHashFunction opensslHashFunction = DEFAULT_OPENSSL_HASH_FUNCTION; public CertificateValidatorBuilder() { } /** * Sets the openssl hash function for this builder * * @param f * the {@link OpensslHashFunction} * * @return the builder object */ public CertificateValidatorBuilder opensslHashFunction( OpensslHashFunction f) { opensslHashFunction = f; return this; } /** * Sets the store update listener for this builder * * @param l * the {@link StoreUpdateListener} * @return the builder object */ public CertificateValidatorBuilder storeUpdateListener( StoreUpdateListener l) { storeUpdateListener = l; return this; } /** * Sets the trust anchors dir for this builder * * @param dir * the trust anchors directory * @return the builder object */ public CertificateValidatorBuilder trustAnchorsDir(String dir) { trustAnchorsDir = dir; return this; } /** * Sets the validation error listener for this builder * * @param l * the {@link ValidationErrorListener} * @return the builder object */ public CertificateValidatorBuilder validationErrorListener( ValidationErrorListener l) { validationErrorListener = l; return this; } /** * Sets the trust anchors update interval for this builder * * @param interval * the update interval * @return the builder object */ public CertificateValidatorBuilder trustAnchorsUpdateInterval(long interval) { trustAnchorsUpdateInterval = interval; return this; } /** * Sets whether the created validator will be lazy in loading anchors * * @param lazyness * the boolean flag that determines if the validator will be lazy in * loading trust anchors * * @return the builder object */ public CertificateValidatorBuilder lazyAnchorsLoading(boolean lazyness) { lazyAnchorsLoading = lazyness; return this; } /** * Sets the namespace checking mode for this builder * * @param nsChecks * the {@link NamespaceCheckingMode} * @return the builder object */ public CertificateValidatorBuilder namespaceChecks( NamespaceCheckingMode nsChecks) { namespaceChecks = nsChecks; return this; } /** * Sets the crl checking mode for this builder * * @param crl * the {@link CrlCheckingMode} * @return the builder object */ public CertificateValidatorBuilder crlChecks(CrlCheckingMode crl) { crlChecks = crl; return this; } /** * Sets the ocsp checking mode for this builder * * @param ocsp * the {@link OCSPCheckingMode} * @return the builder object */ public CertificateValidatorBuilder ocspChecks(OCSPCheckingMode ocsp) { ocspChecks = ocsp; return this; } /** * Builds an {@link OpensslCertChainValidator} according to the parameters set * for this builder * * @return the {@link X509CertChainValidatorExt} */ public X509CertChainValidatorExt build() { RevocationParametersExt revocationParameters = new RevocationParametersExt( crlChecks, new CRLParameters(), new OCSPParametes(ocspChecks)); ValidatorParamsExt validationParams = new ValidatorParamsExt( revocationParameters, ProxySupport.ALLOW); if (storeUpdateListener != null){ validationParams.setInitialListeners(Arrays.asList(storeUpdateListener)); } boolean openssl1xMode = false; if (opensslHashFunction == OpensslHashFunction.SHA1){ openssl1xMode = true; } OpensslCertChainValidator validator = new OpensslCertChainValidator( trustAnchorsDir, openssl1xMode, namespaceChecks, trustAnchorsUpdateInterval, validationParams, lazyAnchorsLoading); if (validationErrorListener != null){ validator.addValidationListener(validationErrorListener); } return validator; } /** * Builds an Openssl-style certificate validator configured as specified in * the parameters * * @param trustAnchorsDir * the directory where trust anchors are loaded from * @param validationErrorListener * the listener that will receive notification about validation * errors * @param storeUpdateListener * the listener that will receive notifications about trust store * update events * @param updateInterval * the trust anchor store update interval * @param namespaceChecks * the namespace checking policy * @param crlChecks * the crl checking policy * @param ocspChecks * the ocsp checking policy * * @return an Openssl-style certificate validator configured as specified in * the parameters */ public static X509CertChainValidatorExt buildCertificateValidator( String trustAnchorsDir, ValidationErrorListener validationErrorListener, StoreUpdateListener storeUpdateListener, long updateInterval, NamespaceCheckingMode namespaceChecks, CrlCheckingMode crlChecks, OCSPCheckingMode ocspChecks) { return buildCertificateValidator(trustAnchorsDir, validationErrorListener, storeUpdateListener, updateInterval, namespaceChecks, crlChecks, ocspChecks, true); } /** * Builds an Openssl-style certificate validator configured as specified in * the parameters * * @param trustAnchorsDir * the directory where trust anchors are loaded from * @param validationErrorListener * the listener that will receive notification about validation * errors * @param storeUpdateListener * the listener that will receive notifications about trust store * update events * @param updateInterval * the trust anchor store update interval * @param namespaceChecks * the namespace checking policy * @param crlChecks * the crl checking policy * @param ocspChecks * the ocsp checking policy * @param lazy * whether the validator should be lazy in loading crls and * certificates * * @return an Openssl-style certificate validator configured as specified in * the parameters * * @deprecated Create a {@link CertificateValidatorBuilder} object instead. */ @Deprecated public static X509CertChainValidatorExt buildCertificateValidator( String trustAnchorsDir, ValidationErrorListener validationErrorListener, StoreUpdateListener storeUpdateListener, long updateInterval, NamespaceCheckingMode namespaceChecks, CrlCheckingMode crlChecks, OCSPCheckingMode ocspChecks, boolean lazy) { CertificateValidatorBuilder builder = new CertificateValidatorBuilder(); return builder.trustAnchorsDir(trustAnchorsDir) .validationErrorListener(validationErrorListener) .storeUpdateListener(storeUpdateListener) .trustAnchorsUpdateInterval(updateInterval) .namespaceChecks(namespaceChecks).crlChecks(crlChecks) .ocspChecks(ocspChecks).lazyAnchorsLoading(lazy).build(); } /** * Builds an Openssl-style certificate validator configured as specified in * the parameters * * @param trustAnchorsDir * the directory where trust anchors are loaded from * @param validationErrorListener * the listener that will receive notification about validation * errors * * @return an Openssl-style certificate validator configured as specified in * the parameters * * @deprecated Create a {@link CertificateValidatorBuilder} object instead. */ @Deprecated public static X509CertChainValidatorExt buildCertificateValidator( String trustAnchorsDir, ValidationErrorListener validationErrorListener) { return buildCertificateValidator(trustAnchorsDir, validationErrorListener, null, 0L, DEFAULT_NS_CHECKS, DEFAULT_CRL_CHECKS, DEFAULT_OCSP_CHECKS); } /** * Builds an Openssl-style certificate validator configured as specified in * the parameters * * @param trustAnchorsDir * the directory where trust anchors are loaded from * @param validationErrorListener * the listener that will receive notification about validation * errors * @param storeListener * the listener that will be informed of trust store load errors * * @return an Openssl-style certificate validator configured as specified in * the parameters * * @deprecated Create a {@link CertificateValidatorBuilder} object instead. */ @Deprecated public static X509CertChainValidatorExt buildCertificateValidator( String trustAnchorsDir, ValidationErrorListener validationErrorListener, StoreUpdateListener storeListener) { return buildCertificateValidator(trustAnchorsDir, validationErrorListener, storeListener, 0L, DEFAULT_NS_CHECKS, DEFAULT_CRL_CHECKS, DEFAULT_OCSP_CHECKS); } /** * Builds an Openssl-style certificate validator configured as specified in * the parameters * * @param trustAnchorsDir * the directory where trust anchors are loaded from * @param validationErrorListener * the listener that will receive notification about validation * errors * @param storeListener * the listener that will be informed of trust store load errors * * @param updateInterval * the trust anchor store update interval * * @param lazy * whether the certificate validator should be lazy in loading crls * and CAs * * @return an Openssl-style certificate validator configured as specified in * the parameters * * @deprecated Create a {@link CertificateValidatorBuilder} object instead. * */ @Deprecated public static X509CertChainValidatorExt buildCertificateValidator( String trustAnchorsDir, ValidationErrorListener validationErrorListener, StoreUpdateListener storeListener, long updateInterval, boolean lazy) { return buildCertificateValidator(trustAnchorsDir, validationErrorListener, storeListener, updateInterval, DEFAULT_NS_CHECKS, DEFAULT_CRL_CHECKS, DEFAULT_OCSP_CHECKS, lazy); } /** * Builds an Openssl-style certificate validator configured as specified in * the parameters * * @param trustAnchorsDir * the directory where trust anchors are loaded from * @param validationErrorListener * the listener that will receive notification about validation * errors * @param storeListener * the listener that will be informed of trust store load errors * * @param updateInterval * the trust anchor store update interval * * @return an Openssl-style certificate validator configured as specified in * the parameters * * @deprecated Create a {@link CertificateValidatorBuilder} object instead. * */ @Deprecated public static X509CertChainValidatorExt buildCertificateValidator( String trustAnchorsDir, ValidationErrorListener validationErrorListener, StoreUpdateListener storeListener, long updateInterval) { return buildCertificateValidator(trustAnchorsDir, validationErrorListener, storeListener, updateInterval, DEFAULT_NS_CHECKS, DEFAULT_CRL_CHECKS, DEFAULT_OCSP_CHECKS); } /** * Builds an Openssl-style certificate validator configured as specified in * the parameters * * @param trustAnchorsDir * the directory where trust anchors are loaded from * @param validationErrorListener * the listener that will receive notification about validation * errors * @param updateInterval * the trust anchor store update interval * @param lazy * whether the certificate validator should be lazy in loading crls * and CAs * * @return an Openssl-style certificate validator configured as specified in * the parameters * * @deprecated Create a {@link CertificateValidatorBuilder} object instead. * */ @Deprecated public static X509CertChainValidatorExt buildCertificateValidator( String trustAnchorsDir, ValidationErrorListener validationErrorListener, long updateInterval, boolean lazy) { return buildCertificateValidator(trustAnchorsDir, validationErrorListener, null, updateInterval, DEFAULT_NS_CHECKS, DEFAULT_CRL_CHECKS, DEFAULT_OCSP_CHECKS, lazy); } /** * Builds an Openssl-style certificate validator configured as specified in * the parameters * * @param trustAnchorsDir * the directory where trust anchors are loaded from * @param validationErrorListener * the listener that will receive notification about validation * errors * @param updateInterval * the trust anchor store update interval * * @return an Openssl-style certificate validator configured as specified in * the parameters * * @deprecated Create a {@link CertificateValidatorBuilder} object instead. * */ @Deprecated public static X509CertChainValidatorExt buildCertificateValidator( String trustAnchorsDir, ValidationErrorListener validationErrorListener, long updateInterval) { return buildCertificateValidator(trustAnchorsDir, validationErrorListener, null, updateInterval, DEFAULT_NS_CHECKS, DEFAULT_CRL_CHECKS, DEFAULT_OCSP_CHECKS); } /** * Builds an Openssl-style certificate validator configured as specified in * the parameters * * @param trustAnchorsDir * the directory where trust anchors are loaded from * * @return an Openssl-style certificate validator configured as specified in * the parameters * * @deprecated Create a {@link CertificateValidatorBuilder} object instead. */ @Deprecated public static X509CertChainValidatorExt buildCertificateValidator( String trustAnchorsDir) { return buildCertificateValidator(trustAnchorsDir, null, null, 0L, DEFAULT_NS_CHECKS, DEFAULT_CRL_CHECKS, DEFAULT_OCSP_CHECKS); } /** * Builds an Openssl-style certificate validator. * * @return an Openssl-style certificate validator configured as specified in * the parameters * * @deprecated Create a {@link CertificateValidatorBuilder} object instead. */ @Deprecated public static X509CertChainValidatorExt buildCertificateValidator() { return buildCertificateValidator( DefaultVOMSValidator.DEFAULT_TRUST_ANCHORS_DIR, null, null, 0L, DEFAULT_NS_CHECKS, DEFAULT_CRL_CHECKS, DEFAULT_OCSP_CHECKS); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/util/CredentialsUtils.java000066400000000000000000000165351477577347300300320ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.util; import static java.nio.file.StandardOpenOption.CREATE_NEW; import static java.nio.file.StandardOpenOption.WRITE; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.file.FileAlreadyExistsException; import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.nio.file.attribute.FileAttribute; import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.PosixFilePermissions; import java.security.PrivateKey; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; import eu.emi.security.authn.x509.X509Credential; import eu.emi.security.authn.x509.helpers.CertificateHelpers; import eu.emi.security.authn.x509.impl.CertificateUtils; import eu.emi.security.authn.x509.impl.CertificateUtils.Encoding; /** * An utility class for handling credentials * * @author Daniele Andreotti * @author Andrea Ceccanti * */ public class CredentialsUtils { /** * * The encoding used to serialize proxy credentials private key. * */ public enum PrivateKeyEncoding { PKCS_1, PKCS_8 } /** * The default encoding used when no encoding is specified by callers. */ public static final PrivateKeyEncoding DEFAULT_ENCONDING = PrivateKeyEncoding.PKCS_1; /** * Serializes a private key to an output stream according to an encoding. * * @param os * the target output stream * @param key * the key to be serialized * @param encoding * the encoding * * @throws IllegalArgumentException * for unsupported private key encodings * @throws IOException * if write fails for any reason on the output stream */ public static void savePrivateKey(OutputStream os, PrivateKey key, PrivateKeyEncoding encoding) throws IOException { switch (encoding) { case PKCS_1: savePrivateKeyPKCS1(os, key); break; case PKCS_8: savePrivateKeyPKCS8(os, key); break; default: throw new IllegalArgumentException("Unsupported private key encoding: " + encoding.name()); } } /** * Serializes a private key to an output stream following the pkcs8 encoding. * * This method just delegates to canl, but provides a much more understandable * signature. * * @param os * @param key * @throws IllegalArgumentException * @throws IOException */ private static void savePrivateKeyPKCS8(OutputStream os, PrivateKey key) throws IllegalArgumentException, IOException { CertificateUtils.savePrivateKey(os, key, Encoding.PEM, null, null); } /** * Serializes a private key to an output stream following the pkcs1 encoding. * * This method just delegates to canl, but provides a much more understandable * signature. * * @param os * @param key * @throws IllegalArgumentException * @throws IOException */ private static void savePrivateKeyPKCS1(OutputStream os, PrivateKey key) throws IllegalArgumentException, IOException { CertificateUtils.savePrivateKey(os, key, Encoding.PEM, null, new char[0], true); } /** * Saves user credentials as a plain text PEM data.
* Writes the user certificate chain first, then the user key. * * @param os * the output stream * @param uc * the user credential that must be serialized * @param encoding * the private key encoding * * * @throws IOException * in case of errors writing on the output stream */ public static void saveProxyCredentials(OutputStream os, X509Credential uc, PrivateKeyEncoding encoding) throws IOException { X509Certificate[] chain = CertificateHelpers.sortChain(Arrays.asList(uc .getCertificateChain())); PrivateKey key = uc.getKey(); X509Certificate cert = uc.getCertificate(); CertificateUtils.saveCertificate(os, cert, Encoding.PEM); if (key != null) savePrivateKey(os, key, encoding); X509Certificate c = null; for (int index = 1; index < chain.length; index++) { c = chain[index]; int basicConstraints = c.getBasicConstraints(); // Only save non-CA certs to proxy file if (basicConstraints < 0){ CertificateUtils.saveCertificate(os, c, Encoding.PEM); } } os.flush(); } /** * * Saves user credentials as a plain text PEM data.
* Writes the user certificate chain first, then the user key, using the * default encoding specified in {@link #DEFAULT_ENCONDING}. * * @param os * the output stream for the saved proxy * * @param uc * the user credential * * @throws IOException * in case of errors writing to the output stream * */ public static void saveProxyCredentials(OutputStream os, X509Credential uc) throws IOException { saveProxyCredentials(os, uc, DEFAULT_ENCONDING); } /** * Saves proxy credentials to a file. This method ensures that the stored * proxy is saved with the appropriate file permissions. * * @param proxyFileName * the file where the proxy will be saved * @param uc * the credential to be saved * @param encoding * the private key encoding * @throws IOException * in case of errors writing to the proxy file */ public static void saveProxyCredentials(String proxyFileName, X509Credential uc, PrivateKeyEncoding encoding) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); saveProxyCredentials(baos, uc, encoding); baos.close(); final ByteBuffer proxyBuffer = ByteBuffer.wrap(baos.toByteArray()); final Path proxyFilePath = Paths.get(proxyFileName); final FileAttribute> permissions = PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rw-------")); final Set options = new HashSet<>(); Collections.addAll(options, CREATE_NEW, WRITE); try { Files.delete(proxyFilePath); } catch (NoSuchFileException e) { // ignore } try (FileChannel fc = FileChannel.open(proxyFilePath, options, permissions)) { fc.write(proxyBuffer); } catch (FileAlreadyExistsException e) { throw new IOException("Cannot create proxy file safely"); } } /** * * Saves proxy credentials to a file. This method ensures that the stored * proxy is saved with the appropriate file permissions, using the default * encoding specified in {@link #DEFAULT_ENCONDING}. * * @param proxyFileName * the file where the proxy will be saved * @param uc * the credential to be saved * * @throws IOException * in case of errors writing the credential to the proxy file */ public static void saveProxyCredentials(String proxyFileName, X509Credential uc) throws IOException { saveProxyCredentials(proxyFileName, uc, DEFAULT_ENCONDING); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/util/FilePermissionHelper.java000066400000000000000000000206731477577347300306420ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.util; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.util.EnumSet; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.credential.FilePermissionError; /** * A helper class for performing basic Unix file permission checks. * *

* This class is intended to provide simple permission validation and modification for specific * files, such as private keys and proxy certificates. It relies on executing system commands to * fetch and update file permissions. *

* *

* Note: This implementation is a workaround until proper support for POSIX file permissions is * available in Java. *

* */ public class FilePermissionHelper { /** * Enumeration representing POSIX file permissions. */ public static enum PosixFilePermission { // @formatter:off /** Read-only permission for the user (chmod 400, stat -r--------). */ USER_RO ("400", "-r--------"), /** Read and write permission for the user (chmod 600, stat -rw-------). */ USER_RW ("600", "-rw-------"), /** Full permissions for the user (chmod 700, stat -rwx------). */ USER_ALL ("700", "-rwx------"), /** Full permissions for all users (chmod 777, stat -rwxrwxrwx). */ ALL_PERMS ("777", "-rwxrwxrwx"); // @formatter:off private String chmodForm; private String statForm; /** * Constructor for PosixFilePermission enum. * * @param chmodForm the chmod-style representation of the permission * @param statForm the stat-style representation of the permission */ private PosixFilePermission(String chmodForm, String statForm) { this.chmodForm = chmodForm; this.statForm = statForm; } /** * Gets the stat-style (symbolic) representation of the permission. * * @return the stat-formatted permission string (e.g., "-rw-------"). */ public String statForm() { return statForm; } /** * Gets the chmod-style (numeric) representation of the permission. * * @return the chmod-formatted permission string (e.g., "600"). */ public String chmodForm() { return chmodForm; } } /** * Required file permissions for the private key file */ public static final EnumSet PRIVATE_KEY_PERMS = EnumSet.of(PosixFilePermission.USER_RO, PosixFilePermission.USER_RW); /** * String representation of private key required permissions. */ public static final String PRIVATE_KEY_PERMS_STR = PosixFilePermission.USER_RO.chmodForm() + ", " + PosixFilePermission.USER_RW.chmodForm(); /** * The command used to retrieve file permissions for a given file */ public static final String LS_CMD_TEMPLATE = "ls -al %s"; /** * The command used to set file permissions on a given file */ public static final String CHMOD_CMD_TEMPLATE = "chmod %s %s"; /** * Checks whether a proxy file has the right permissions * * @param proxyFile the file to be checked * * @throws IOException if an error occurs checking file attributes * @throws FilePermissionError if permissions are not as expected */ public static void checkProxyPermissions(String proxyFile) throws IOException { matchesFilePermissions(proxyFile, PosixFilePermission.USER_RW); } /** * Checks whether a private key file has the 'right' permissions * * @param privateKeyFile the file to be checked * @throws IOException if an error occurs checking file attributes * @throws FilePermissionError if the permissions are not correct */ public static void checkPrivateKeyPermissions(String privateKeyFile) throws IOException { for (PosixFilePermission p : PRIVATE_KEY_PERMS) { try { matchesFilePermissions(privateKeyFile, p); return; } catch (FilePermissionError e) { } } final String errorMessage = String.format("Wrong file permissions on file %s. Required permissions are: %s ", privateKeyFile, PRIVATE_KEY_PERMS_STR); throw new FilePermissionError(errorMessage); } /** * Checks whether a pkcs12 file has the 'right' permissions * * @param pkcs12File the file to be checked * @throws IOException if an error occurs checking file attributes * @throws FilePermissionError if the permissions are not correct */ public static void checkPKCS12Permissions(String pkcs12File) throws IOException { matchesFilePermissions(pkcs12File, PosixFilePermission.USER_RW); } /** * Checks that a given file has the appropriate unix permissions. This naive implementation just * fetches the output of ls -al on a given file and matches the resulting string with the * permissionString passed as argument. * * So the permissionString must be something like: * *
   * -rw-------
   * 
* * @param filename the filename to be checked * @param expectedPerm the permission string that must be matched * @throws IOException if an error occurs checking file attributes * @throws FilePermissionError if file permissions are not as requested */ public static void matchesFilePermissions(String filename, PosixFilePermission expectedPerm) throws IOException { filenameSanityChecks(filename); if (expectedPerm == null) { throw new NullPointerException("Expected permission cannot be null."); } String filePerms = getFilePermissions(new File(filename).getCanonicalPath()); if (!filePerms.startsWith(expectedPerm.statForm())) { throw new FilePermissionError( String.format("Wrong file permissions on file %s. Expected: %s", filename, expectedPerm.chmodForm())); } } private static void filenameSanityChecks(String filename) { if (filename == null) { throw new NullPointerException("Filename cannot be null."); } File file = new File(filename); if (!file.exists()) { throw new VOMSError("File not found: " + filename); } } private static String getFilePermissions(String filename) { String cmd = String.format(LS_CMD_TEMPLATE, filename); ProcessBuilder pb = new ProcessBuilder(cmd.split(" ")); try { Process p = pb.start(); int exitStatus = p.waitFor(); if (exitStatus != 0) { throw new VOMSError("Failed to retrieve file properties: " + filename); } try (BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()))) { String permString = reader.readLine(); if (permString == null) { throw new VOMSError("No output received from command: " + cmd); } return permString; } } catch (IOException e) { throw new VOMSError("Error retrieving file permissions for " + filename, e); } catch (InterruptedException e) { return null; } } /** * Sets the default POSIX permissions on a proxy identified by filename. * * @param filename the file to modify */ public static void setProxyPermissions(String filename) { setFilePermissions(filename, PosixFilePermission.USER_RW); } /** * Sets the default POSIX permissions on a p12 identified by filename. * * @param filename the file to modify */ public static void setPKCS12Permissions(String filename) { setFilePermissions(filename, PosixFilePermission.USER_RW); } /** * Sets the default POSIX permissions on a private key identified by filename. * * @param filename the file to modify */ public static void setPrivateKeyPermissions(String filename) { setFilePermissions(filename, PosixFilePermission.USER_RO); } /** * Sets the specified POSIX permissions on a file. * * @param filename the file to modify * @param perm the permissions to apply */ public static void setFilePermissions(String filename, PosixFilePermission perm) { filenameSanityChecks(filename); String cmd = String.format(CHMOD_CMD_TEMPLATE, perm.chmodForm(), filename); ProcessBuilder pb = new ProcessBuilder(cmd.split(" ")); try { Process process = pb.start(); int exitStatus = process.waitFor(); if (exitStatus != 0) { throw new VOMSError("Failed to change file permissions: " + filename); } } catch (IOException | InterruptedException e) { throw new VOMSError("Error setting file permissions for " + filename, e); } } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/util/FingerprintHelper.java000066400000000000000000000042031477577347300301700ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.util; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; /** * A utility class for computing fingerprints of X.509 certificates. *

* This class provides methods to generate a cryptographic fingerprint (hash) of an X.509 * certificate using a specified digest algorithm. *

* *

* The default digest algorithm used is SHA-1. *

* */ public class FingerprintHelper { /** The default message digest algorithm used for computing fingerprints. */ public static final String DEFAULT_DIGEST_ALGORITHM = "SHA-1"; /** * Converts a byte array to a hexadecimal string representation. * * @param bytes the byte array to convert * @return a string containing the hexadecimal representation of the byte array */ private static String hexify(byte[] bytes) { char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; StringBuffer buf = new StringBuffer(bytes.length * 2); for (int i = 0; i < bytes.length; ++i) { buf.append(hexDigits[(bytes[i] & 0xf0) >> 4]); buf.append(hexDigits[bytes[i] & 0x0f]); } return buf.toString(); } /** * Computes the fingerprint of an X.509 certificate using the default digest algorithm. * * @param cert the X.509 certificate for which to compute the fingerprint * @return the fingerprint of the certificate as a hexadecimal string * @throws NoSuchAlgorithmException if the specified digest algorithm is not available * @throws CertificateEncodingException if encoding the certificate fails */ public static String getFingerprint(X509Certificate cert) throws NoSuchAlgorithmException, CertificateEncodingException { MessageDigest md = MessageDigest.getInstance(DEFAULT_DIGEST_ALGORITHM); byte[] der = cert.getEncoded(); md.update(der); byte[] digest = md.digest(); return hexify(digest); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/util/GaParser.java000066400000000000000000000027341477577347300262540ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.util; import static java.util.Collections.emptyList; import static java.util.Objects.isNull; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.italiangrid.voms.VOMSGenericAttribute; import org.italiangrid.voms.ac.impl.VOMSGenericAttributeImpl; public class GaParser { private static final String GA_TOKEN_REGEXP = "\\s*([a-zA-Z][a-zA-Z0-9_-]*)\\s*=\\s*(\\S+)\\s*"; private static final Pattern GA_TOKEN_PATTERN = Pattern.compile(GA_TOKEN_REGEXP); private GaParser() { // empty constructor } public static List parseGaString(String gaString) { if (isNull(gaString)) { throw new NullPointerException("Cannot parse a null gaString"); } if (gaString.isEmpty()) { return emptyList(); } List result = new ArrayList<>(); String[] gaTokens = gaString.split(","); for (String token: gaTokens) { Matcher m = GA_TOKEN_PATTERN.matcher(token); if (m.matches()) { String key = m.group(1); String value = m.group(2); VOMSGenericAttributeImpl ga = new VOMSGenericAttributeImpl(); ga.setName(key); ga.setValue(value); result.add(ga); } } return result; } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/util/NullListener.java000066400000000000000000000063311477577347300271650ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.util; import java.io.File; import java.lang.Thread.UncaughtExceptionHandler; import java.security.cert.X509Certificate; import java.util.List; import org.italiangrid.voms.ac.ACLookupListener; import org.italiangrid.voms.ac.VOMSValidationResult; import org.italiangrid.voms.ac.ValidationResultListener; import org.italiangrid.voms.credential.LoadCredentialsEventListener; import org.italiangrid.voms.request.VOMSACRequest; import org.italiangrid.voms.request.VOMSErrorMessage; import org.italiangrid.voms.request.VOMSProtocolListener; import org.italiangrid.voms.request.VOMSRequestListener; import org.italiangrid.voms.request.VOMSResponse; import org.italiangrid.voms.request.VOMSServerInfo; import org.italiangrid.voms.request.VOMSServerInfoStoreListener; import org.italiangrid.voms.request.VOMSWarningMessage; import org.italiangrid.voms.store.LSCInfo; import org.italiangrid.voms.store.VOMSTrustStore; import org.italiangrid.voms.store.VOMSTrustStoreStatusListener; /** * * A Singleton Listener which swallows notification. * * @author andreaceccanti * */ public enum NullListener implements ACLookupListener, ValidationResultListener, VOMSServerInfoStoreListener, LoadCredentialsEventListener, VOMSTrustStoreStatusListener, UncaughtExceptionHandler, VOMSRequestListener, VOMSProtocolListener { INSTANCE; public void notifyVOMSRequestStart(VOMSACRequest request, VOMSServerInfo si) { } public void notifyVOMSRequestSuccess(VOMSACRequest request, VOMSServerInfo endpoint) { } public void notifyVOMSRequestFailure(VOMSACRequest request, VOMSServerInfo endpoint, Throwable error) { } public void notifyErrorsInVOMSReponse(VOMSACRequest request, VOMSServerInfo si, VOMSErrorMessage[] errors) { } public void notifyWarningsInVOMSResponse(VOMSACRequest request, VOMSServerInfo si, VOMSWarningMessage[] warnings) { } public void uncaughtException(Thread t, Throwable e) { } public void notifyTrustStoreUpdate(VOMSTrustStore store) { } public void notifyCertficateLookupEvent(String dir) { } public void notifyLSCLookupEvent(String dir) { } public void notifyCertificateLoadEvent(X509Certificate cert, File f) { } public void notifyLSCLoadEvent(LSCInfo lsc, File f) { } public void notifyCredentialLookup(String... locations) { } public void notifyLoadCredentialSuccess(String... locations) { } public void notifyLoadCredentialFailure(Throwable error, String... locations) { } public void notifyNoValidVOMSESError(List searchedPaths) { } public void notifyVOMSESlookup(String vomsesPath) { } public void notifyVOMSESInformationLoaded(String vomsesPath, VOMSServerInfo info) { } public void notifyValidationResult(VOMSValidationResult result) { } public void notifyACLookupEvent(X509Certificate[] chain, int chainLevel) { } public void notifyACParseEvent(X509Certificate[] chain, int chainLevel) { } public void notifyHTTPRequest(String url) { } public void notifyLegacyRequest(String xmlLegacyRequest) { } public void notifyReceivedResponse(VOMSResponse r) { } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/util/TimeUtils.java000066400000000000000000000050761477577347300264710ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.util; import static java.util.Objects.isNull; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.time.format.ResolverStyle; import java.util.Calendar; import java.util.Date; /** * Time utilities. * * @author cecco * */ public class TimeUtils { public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ISO_DATE_TIME.withResolverStyle(ResolverStyle.LENIENT); private TimeUtils() { } /** * Checks that a date falls in the interval allowing for a certain clock skew expressed in * minutes. The interval defined by (startDate, endDate) is modified to be (startDate - * skewInMinutes, endDate + skewInMinutes). * * @param timeToCheck the time to be checked * @param startDate the start date of the time range * @param endDate the end date of the time range * @param skewInMinutes the clock skew in minutes to take into account * * @throws IllegalArgumentException if passed an illegal time range * @return true, if the time is in the given range, false otherwise */ public static boolean checkTimeInRangeWithSkew(Date timeToCheck, Date startDate, Date endDate, int skewInMinutes) { if (startDate.after(endDate) || startDate.equals(endDate)) { String msg = String.format( "Illegal time interval: start date must be before end date. [start date: %s, end date: %s]", startDate, endDate); throw new IllegalArgumentException(msg); } Calendar cal = Calendar.getInstance(); cal.setTime(startDate); cal.add(Calendar.MINUTE, -skewInMinutes); Date skewedStartDate = cal.getTime(); cal.clear(); cal.setTime(endDate); cal.add(Calendar.MINUTE, skewInMinutes); Date skewedEndDate = cal.getTime(); return skewedEndDate.after(timeToCheck) && skewedStartDate.before(timeToCheck); } /** * Parses a date from string * * @param date the date string representation; * @return the parsed date * @throws NullPointerException if date is null * @throws java.time.format.DateTimeParseException if the date is in the wrong format */ public static Date parseDate(String date) { if (isNull(date)) { throw new NullPointerException("Cannot parse a null date"); } LocalDateTime dateTime = LocalDateTime.parse(date, DATE_FORMATTER); return Date.from(dateTime.atZone(ZoneOffset.UTC).toInstant()); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/util/VOMSBase64Decoder.java000066400000000000000000000052421477577347300275640ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.util; // Gidon Moont // Imperial College London // Copyright (C) April 2006 // Voms uses a non-standard Base-64 algorithm. Hmmm... import org.bouncycastle.util.encoders.Base64; /** * * This class implements a decoder for the non-standard Base-64 algorithm used * by voms. * * * @author Gidon Moont * @author Vincenzo Ciaschini * */ public class VOMSBase64Decoder { // matrix out of src/common/xml.c private static int[] decodemapint = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 62, 0, 63, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0 }; private static byte[] decodemapbyte = new byte[128]; static { for (int i = 0; i < 128; i++) { decodemapbyte[i] = (byte) decodemapint[i]; } } public static byte[] decode(String s) { if (s.indexOf('\n') != -1) { return Base64.decode(s.trim().replaceAll("\n", "")); } else return mydecode(s); } private static byte[] mydecode(String s) { char[] in = s.toCharArray(); int iLen = in.length; // cuts off end - do I need this? // while (iLen > 0 && in[iLen-1] == '=') iLen--; int oLen = (iLen * 3) / 4; byte[] out = new byte[oLen]; int ip = 0; int op = 0; while (ip < iLen) { int i0 = in[ip++]; int i1 = in[ip++]; int i2 = ip < iLen ? in[ip++] : 'A'; int i3 = ip < iLen ? in[ip++] : 'A'; if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) throw new IllegalArgumentException( "Illegal character in Base64 encoded data."); int b0 = decodemapbyte[i0]; int b1 = decodemapbyte[i1]; int b2 = decodemapbyte[i2]; int b3 = decodemapbyte[i3]; if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) throw new IllegalArgumentException( "Illegal character in Base64 encoded data."); // ???????????? int o0 = (b0 << 2) | (b1 >>> 4); int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2); int o2 = ((b2 & 3) << 6) | b3; out[op++] = (byte) o0; if (op < oLen) out[op++] = (byte) o1; if (op < oLen) out[op++] = (byte) o2; } return out; } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/util/VOMSFQANNamingScheme.java000066400000000000000000000146361477577347300302650ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.util; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.italiangrid.voms.VOMSError; /** * This class provides utility methods that are used for parsing, matching voms * FQANs (Fully Qualified Attribute Names). * * @author Karoly Lorentey * @author Andrea Ceccanti * * */ public class VOMSFQANNamingScheme { public static final String fqanSyntax = "^(/[\\w.-]+)+|((/[\\w.-]+)+/)?(Role=[\\w.-]+)|(Capability=[\\w\\s.-]+)$"; public static final String groupSyntax = "^(/[\\w.-]+)+$"; public static final String roleSyntax = "^Role=[\\w.-]+$"; public static final String qualifiedRoleSyntax = "^(/[\\w.-]+)+/Role=[\\w.-]+$"; public static final String capabilitySyntax = "^Capability=[\\w\\s.-]+$"; public static final Pattern fqanPattern = Pattern.compile(fqanSyntax); public static final Pattern groupPattern = Pattern.compile(groupSyntax); public static final Pattern rolePattern = Pattern.compile(roleSyntax); public static final Pattern qualifiedRolePattern = Pattern .compile(qualifiedRoleSyntax); public static final Pattern capabilityPattern = Pattern .compile(capabilitySyntax); /** * This methods checks that the string passed as argument complies with the * voms FQAN syntax. * * @param fqan * the string that must be checked for compatibility with FQAN * syntax. * @throws VOMSError * If there's an error in the FQAN syntax. */ public static void checkSyntax(String fqan) { if (fqan.length() > 255) throw new VOMSError("fqan.length() > 255"); if (!fqanPattern.matcher(fqan).matches()) throw new VOMSError("Syntax error in fqan: " + fqan); } /** * * This methods checks that the fqan passed as argument complies with the * syntax used by voms to identify groups. * * @param fqan * the string that has to be checked. * @throws VOMSError * If the string passed as argument doens not comply with the voms * sytax. */ public static void checkGroup(String fqan) { checkSyntax(fqan); if (!groupPattern.matcher(fqan).matches()) throw new VOMSError("Syntax error in group name: " + fqan); } /** * This methods checks that the string passed as argument complies with the * syntax used by voms to identify roles. * * * @param roleName * the name of the role * @throws VOMSError * If the string passed as argument doens not comply with the voms * sytax. */ public static void checkRole(String roleName) { if (roleName.length() > 255) throw new VOMSError("roleName.length()>255"); if (!rolePattern.matcher(roleName).matches()) throw new VOMSError("Syntax error in role name: " + roleName); } /** * This methods checks that the FQAN passed as argument identifies a voms * group. * * @param groupName * the string to check. * @return
    *
  • true, if the string passed as argument identifies a voms group. *
  • false, otherwise. *
*/ public static boolean isGroup(String groupName) { checkSyntax(groupName); return groupPattern.matcher(groupName).matches(); } /** * This methods checks that the FQAN passed as argument identifies a voms * role. * * @param roleName * the string to check. * @return
    *
  • true, if the string passed as argument identifies a voms role. *
  • false, otherwise. *
*/ public static boolean isRole(String roleName) { checkSyntax(roleName); return rolePattern.matcher(roleName).matches(); } /** * This methods checks that the FQAN passed as argument identifies a qualified * voms role, i.e., a role defined in the context of a voms group. * * @param fqan * the string to check. * @return
    *
  • true, if the string passed as argument identifies a qualified * voms role. *
  • false, otherwise. *
*/ public static boolean isQualifiedRole(String fqan) { checkSyntax(fqan); return qualifiedRolePattern.matcher(fqan).matches(); } /** * This method extracts the role name information from the FQAN passed as * argument. * * @param containerName * the FQAN * @return
    *
  • A string containing the role name, if found
  • *
  • null, if no role information is contained in the FQAN passed as * argument *
*/ public static String getRoleName(String containerName) { if (!isRole(containerName) && !isQualifiedRole(containerName)) throw new VOMSError("No role specified in \"" + containerName + "\" voms syntax."); Matcher m = fqanPattern.matcher(containerName); if (m.matches()) { String roleGroup = m.group(4); return roleGroup .substring(roleGroup.indexOf('=') + 1, roleGroup.length()); } return null; } /** * This method extracts group name information from the FQAN passed as * argument. * * @param containerName * the FQAN * @return
    *
  • A string containing the group name, if found
  • *
  • null, if no group information is contained in the FQAN passed * as argument *
*/ public static String getGroupName(String containerName) { checkSyntax(containerName); // If it's a container and it's not a role or a qualified role, then // it's a group! if (!isRole(containerName) && !isQualifiedRole(containerName)) return containerName; Matcher m = fqanPattern.matcher(containerName); if (m.matches()) { String groupName = m.group(2); if (groupName.endsWith("/")) return groupName.substring(0, groupName.length() - 1); else return groupName; } return null; } public static String toOldQualifiedRoleSyntax(String qualifiedRole) { checkSyntax(qualifiedRole); if (!isQualifiedRole(qualifiedRole)) throw new VOMSError("String passed as argument is not a qualified role!"); return getGroupName(qualifiedRole) + ":" + getRoleName(qualifiedRole); } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/util/XMLUtils.java000066400000000000000000000017501477577347300262260ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.util; import java.io.StringWriter; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.italiangrid.voms.VOMSError; import org.w3c.dom.Document; public class XMLUtils { public static String documentAsString(Document doc) { try { Transformer transformer = TransformerFactory.newInstance() .newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); StreamResult result = new StreamResult(new StringWriter()); DOMSource source = new DOMSource(doc); transformer.transform(source, result); return result.getWriter().toString(); } catch (Throwable e) { throw new VOMSError(e.getMessage(), e); } } } voms-api-java-3.3.5/src/main/java/org/italiangrid/voms/util/package-info.java000066400000000000000000000003361477577347300270700ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 /** * This package provides utility classes used in other packages. */ package org.italiangrid.voms.util; voms-api-java-3.3.5/src/main/resources/000077500000000000000000000000001477577347300177515ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/resources/org/000077500000000000000000000000001477577347300205405ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/resources/org/italiangrid/000077500000000000000000000000001477577347300230275ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/resources/org/italiangrid/voms/000077500000000000000000000000001477577347300240135ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/resources/org/italiangrid/voms/error/000077500000000000000000000000001477577347300251445ustar00rootroot00000000000000voms-api-java-3.3.5/src/main/resources/org/italiangrid/voms/error/validationErrors.properties000066400000000000000000000027221477577347300326140ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare # # SPDX-License-Identifier: Apache-2.0 ## Other other = Validation error: {0} ## CAnL canlError = CAnL certificate validation error: {0} ## Validity acNotValidAtCurrentTime = AC validity check failed: AC not valid at current time. [AC start time: {0}, AC end time: {1}, now: {2}] ## LSC lscFileNotFound = LSC validation failed: LSC file matching VOMS attributes not found in store. emptyAcCertsExtension = LSC validation failed: AC certs extension is empty. lscDescriptionDoesntMatchAcCert = LSC validation failed: LSC chain description does not match AA certificate chain embedded in the VOMS AC! invalidAcCert = LSC validation failed: AA certificate chain embedded in the VOMS AC failed certificate validation! acCertFailsSignatureVerification = LSC signature validation failed: matching AA cert {0} fails signature verification. ## Local AA cert aaCertNotFound = AC signature verification failure: no valid VOMS server credential found. invalidAaCert = AC signature verification failure: local AA cert failed certificate validation! aaCertFailsSignatureVerification = Signature validation failed: matching AA cert {0} fails signature verification. ## Holder check acHolderDoesntMatchCertChain = AC holder check failed: AC holder {0} does not match certificate chain subject {1}. ## Targets check localhostDoesntMatchAcTarget = AC target check failed: local host {0} is not in the AC target list {1}. voms-api-java-3.3.5/src/test/000077500000000000000000000000001477577347300157725ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/java/000077500000000000000000000000001477577347300167135ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/java/org/000077500000000000000000000000001477577347300175025ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/java/org/italiangrid/000077500000000000000000000000001477577347300217715ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/000077500000000000000000000000001477577347300227555ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/000077500000000000000000000000001477577347300237345ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/TestDefaultVOMSTrustStore.java000066400000000000000000000052611477577347300316130ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 /** * */ package org.italiangrid.voms.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.Collections; import java.util.List; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.store.impl.DefaultVOMSTrustStore; import org.junit.Test; import eu.emi.security.authn.x509.impl.CertificateUtils; import eu.emi.security.authn.x509.impl.CertificateUtils.Encoding; /** * @author Andrea Ceccanti * */ public class TestDefaultVOMSTrustStore { @Test(expected = VOMSError.class) public void testEmptyTrustDirsFailure() { @SuppressWarnings({ "unused", "unchecked" }) DefaultVOMSTrustStore store = new DefaultVOMSTrustStore( Collections.EMPTY_LIST); } @Test(expected = VOMSError.class) public void testNonExistentTrustDirsFailure() { List trustDirs = Arrays.asList(new String[] { "/etc/do/not/exist", "/etc/grid-security/vomsdir" }); @SuppressWarnings("unused") DefaultVOMSTrustStore store = new DefaultVOMSTrustStore(trustDirs); } // FIXME: This test assumes /etc/grid-security/vomsdir exists in the machine // where the test run. Disabling it // for now. public void testDefaultTrustDir() { DefaultVOMSTrustStore store = new DefaultVOMSTrustStore(); List trustDirs = store.getLocalTrustedDirectories(); assertEquals(1, trustDirs.size()); assertEquals(DefaultVOMSTrustStore.DEFAULT_VOMS_DIR, trustDirs.get(0)); } @Test public void testEmptyTrustDir() { List trustDirs = Arrays.asList("src/test/resources/empty-vomsdir"); @SuppressWarnings("unused") DefaultVOMSTrustStore store = new DefaultVOMSTrustStore(trustDirs); } @Test public void testCertificateParsing() throws FileNotFoundException, IOException { String vomsDir = "src/test/resources/vomsdir"; String certFileName = "src/test/resources/vomsdir/test-host.cnaf.infn.it.pem"; X509Certificate cert = CertificateUtils.loadCertificate( new FileInputStream(certFileName), Encoding.PEM); List trustDirs = Arrays.asList(new String[] { vomsDir }); DefaultVOMSTrustStore store = new DefaultVOMSTrustStore(trustDirs); assertEquals(1, store.getLocalAACertificates().size()); assertTrue(cert.getSubjectX500Principal().equals( store.getLocalAACertificates().get(0).getSubjectX500Principal())); } public void testUpdatingVOMSTrustStore() { } } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/TestFilePermissionHelper.java000066400000000000000000000040561477577347300315340ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test; import java.io.IOException; import org.italiangrid.voms.credential.FilePermissionError; import org.italiangrid.voms.util.FilePermissionHelper; import org.italiangrid.voms.util.FilePermissionHelper.PosixFilePermission; import org.junit.BeforeClass; import org.junit.Test; public class TestFilePermissionHelper { public static final String keyWithRightPerms = "src/test/resources/perm-test/test0.key.pem"; public static final String p12WithRightPerms = "src/test/resources/perm-test/test0.p12"; public static final String keyWithWrongPerms = "src/test/resources/perm-test/test1.key.pem"; public static final String p12WithWrongPerms = "src/test/resources/perm-test/test1.p12"; public static final String keyWith600Perms = "src/test/resources/perm-test/test2.key.pem"; @BeforeClass public static void setupPermissions() { FilePermissionHelper.setPrivateKeyPermissions(keyWithRightPerms); FilePermissionHelper.setPKCS12Permissions(p12WithRightPerms); FilePermissionHelper.setFilePermissions(keyWithWrongPerms, PosixFilePermission.ALL_PERMS); FilePermissionHelper.setFilePermissions(p12WithWrongPerms, PosixFilePermission.ALL_PERMS); FilePermissionHelper.setFilePermissions(keyWith600Perms, PosixFilePermission.USER_RW); } @Test public void testFilePermissions() throws IOException { FilePermissionHelper.checkPrivateKeyPermissions(keyWithRightPerms); FilePermissionHelper.checkPrivateKeyPermissions(keyWith600Perms); FilePermissionHelper.checkPKCS12Permissions(p12WithRightPerms); } @Test(expected = FilePermissionError.class) public void testFilePermissionsFailureKey() throws IOException { FilePermissionHelper.checkPrivateKeyPermissions(keyWithWrongPerms); } @Test(expected = FilePermissionError.class) public void testFilePermissionsFailureP12() throws IOException { FilePermissionHelper.checkPKCS12Permissions(p12WithWrongPerms); } } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/TestFingerprint.java000066400000000000000000000022541477577347300277310ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import org.italiangrid.voms.util.FingerprintHelper; import org.junit.Test; import eu.emi.security.authn.x509.impl.PEMCredential; public class TestFingerprint { public static final String keyPassword = "pass"; public static final String pemCert = "src/test/resources/certs/test0.cert.pem"; public static final String pemKey = "src/test/resources/certs/test0.key.pem"; @Test public void testGetFingerprint() throws KeyStoreException, CertificateException, FileNotFoundException, IOException, NoSuchAlgorithmException { PEMCredential cred = new PEMCredential(new FileInputStream(pemKey), new FileInputStream(pemCert), keyPassword.toCharArray()); String fingerprint = FingerprintHelper .getFingerprint(cred.getCertificate()); System.out.println(fingerprint); } } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/TestLSCParser.java000066400000000000000000000106541477577347300272430ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; import java.io.ByteArrayInputStream; import java.io.File; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.store.impl.DefaultLSCFileParser; import org.italiangrid.voms.store.impl.LSCFile; import org.junit.Test; public class TestLSCParser { @Test public void testParse() { DefaultLSCFileParser parser = new DefaultLSCFileParser(); String lscContent = "# First line is a comment \n" + "--- second line should skipped \n" + "/C=it/O=org/CN=commonName\n" + " \t\n" + "/C=it/O=org/CN=CA\n"; LSCFile f = parser.parse("vo", "host", new ByteArrayInputStream(lscContent.getBytes())); assertNull(f.getFilename()); assertEquals("vo", f.getVOName()); assertEquals("host", f.getHostname()); assertNotNull(f.getCertificateChainDescription()); assertEquals(2, f.getCertificateChainDescription().size()); assertEquals("/C=it/O=org/CN=commonName", f.getCertificateChainDescription().get(0)); assertEquals("/C=it/O=org/CN=CA", f.getCertificateChainDescription().get(1)); } @Test public void testOddLSCFileParseError() { String singleEntryLSCFile = "# This is a comment \n" + "/C=it/O=org/CN=commonName\n"; String errorMessage = "LSC file parsing error: " + "Malformed LSC file (vo=vo, host=host): " + "Odd number of distinguished name entries."; DefaultLSCFileParser parser = new DefaultLSCFileParser(); try { @SuppressWarnings("unused") LSCFile f = parser.parse("vo", "host", new ByteArrayInputStream( singleEntryLSCFile.getBytes())); } catch (VOMSError e) { assertEquals(errorMessage, e.getMessage()); return; } fail("No error caught for malformed, single line LSC file parsing."); } @Test public void testEmptyLSCFileParseError() { DefaultLSCFileParser parser = new DefaultLSCFileParser(); String emptyLSCContent = "# This is a comment"; String errorMessage = "LSC file parsing error: " + "Malformed LSC file (vo=vo, host=host): " + "No distinguished name entries found."; try { @SuppressWarnings("unused") LSCFile f = parser.parse("vo", "host", new ByteArrayInputStream( emptyLSCContent.getBytes())); } catch (VOMSError e) { assertEquals(errorMessage, e.getMessage()); return; } fail("No error caught for malformed, empty LSC file parsing."); } @Test public void testSlashInsideCommonNameIsIgnored() { DefaultLSCFileParser parser = new DefaultLSCFileParser(); String malformedLSCContent = "/C=it/O=org/CN=commonName\n" + "/C=it/O=org/CN=common/Name"; LSCFile f = parser.parse("vo", "host", new ByteArrayInputStream(malformedLSCContent.getBytes())); assertEquals(2, f.getCertificateChainDescription().size()); } @Test public void testUnsupportedMultichainLSCFileParseSuccess() { DefaultLSCFileParser parser = new DefaultLSCFileParser(); String multichainLSCContent = "/C=IT/O=IGI/CN=test-host.cnaf.infn.it\n" + "/C=IT/O=IGI/CN=Test CA\n" + "------NEXT CHAIN------\n" + "/C=IT/O=IGI/CN=test-host2.cnaf.infn.it\n" + "/C=IT/O=IGI/CN=Test CA"; try { LSCFile f = parser.parse("vo", "host", new ByteArrayInputStream(multichainLSCContent.getBytes())); assertEquals(2, f.getCertificateChainDescription().size()); assertEquals("/C=IT/O=IGI/CN=test-host.cnaf.infn.it", f.getCertificateChainDescription().get(0)); assertEquals("/C=IT/O=IGI/CN=Test CA", f.getCertificateChainDescription().get(1)); } catch (VOMSError e) { fail("No error expected for malformed, empty LSC file parsing."); return; } } @Test public void testNonExistingFileParse() { DefaultLSCFileParser parser = new DefaultLSCFileParser(); String nonExistentFile = "/this/file/doesnt/exist"; try { @SuppressWarnings("unused") LSCFile f = parser.parse("vo", "host", new File(nonExistentFile)); } catch (VOMSError e) { assertEquals("LSC file does not exist: " + nonExistentFile, e.getMessage()); return; } fail("VOMS error not thrown for non existing LSC file parsing attempt."); } } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/TestOpensslHashFunction.java000066400000000000000000000070541477577347300314020ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test; import java.io.IOException; import java.security.KeyStoreException; import java.security.cert.CertificateException; import org.italiangrid.voms.util.CertificateValidatorBuilder; import org.italiangrid.voms.util.CertificateValidatorBuilder.OpensslHashFunction; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import eu.emi.security.authn.x509.ValidationResult; import eu.emi.security.authn.x509.impl.PEMCredential; public class TestOpensslHashFunction { static final String trustAnchorsDir = "src/test/resources/trust-anchors"; static final String md5TrustAnchorsDir = "src/test/resources/md5-trust-anchors"; static final String sha1TrustAnchorsDir = "src/test/resources/sha1-trust-anchors"; static final String keyPassword = "pass"; static final String userCert = "src/test/resources/certs/test0.cert.pem"; static final String userKey = "src/test/resources/certs/test0.key.pem"; static PEMCredential cred; @BeforeClass public static void init() throws KeyStoreException, CertificateException, IOException { cred = new PEMCredential(userKey, userCert, keyPassword.toCharArray()); } @Test public void testDefaultHashIsMD5() { CertificateValidatorBuilder builder = new CertificateValidatorBuilder(); builder.trustAnchorsDir(md5TrustAnchorsDir); ValidationResult result = builder.build() .validate(cred.getCertificateChain()); Assert.assertTrue(result.isValid()); } @Test public void testSHA1Hash() { CertificateValidatorBuilder builder = new CertificateValidatorBuilder(); builder.trustAnchorsDir(sha1TrustAnchorsDir) .opensslHashFunction(OpensslHashFunction.SHA1); ValidationResult result = builder.build() .validate(cred.getCertificateChain()); Assert.assertTrue(result.isValid()); } @Test public void testMD5HashFailsOnSHA1Dir() { CertificateValidatorBuilder builder = new CertificateValidatorBuilder(); builder.trustAnchorsDir(sha1TrustAnchorsDir); ValidationResult result = builder.build() .validate(cred.getCertificateChain()); Assert.assertFalse(result.isValid()); Assert.assertEquals(2, result.getErrors().size()); Assert.assertEquals( "No trusted CA certificate was found for the certificate chain", result.getErrors().get(0).getMessage()); Assert.assertEquals( "Trusted issuer of this certificate was not established", result.getErrors().get(1).getMessage()); Assert.assertEquals(cred.getCertificate().getSubjectX500Principal(), result.getErrors().get(1).getChain()[0].getSubjectX500Principal()); } @Test public void testSHA1FailsOnMD5Dir() { CertificateValidatorBuilder builder = new CertificateValidatorBuilder(); builder.trustAnchorsDir(md5TrustAnchorsDir) .opensslHashFunction(OpensslHashFunction.SHA1); ValidationResult result = builder.build() .validate(cred.getCertificateChain()); Assert.assertFalse(result.isValid()); Assert.assertEquals(2, result.getErrors().size()); Assert.assertEquals( "No trusted CA certificate was found for the certificate chain", result.getErrors().get(0).getMessage()); Assert.assertEquals( "Trusted issuer of this certificate was not established", result.getErrors().get(1).getMessage()); Assert.assertEquals(cred.getCertificate().getSubjectX500Principal(), result.getErrors().get(1).getChain()[0].getSubjectX500Principal()); } } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/TestTimeUtils.java000066400000000000000000000037421477577347300273640ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test; import java.util.Calendar; import java.util.Date; import org.junit.Assert; import org.italiangrid.voms.util.TimeUtils; import org.junit.Test; public class TestTimeUtils { @Test public void testSuccessfulCompute() { Calendar cal = Calendar.getInstance(); Date now = cal.getTime(); cal.add(Calendar.MINUTE, 1); Date nowPlus1Minute = cal.getTime(); Assert.assertTrue(TimeUtils.checkTimeInRangeWithSkew(now, now, nowPlus1Minute, 1)); } @Test(expected = IllegalArgumentException.class) public void testSameArgumentFailure() { Calendar cal = Calendar.getInstance(); Date now = cal.getTime(); TimeUtils.checkTimeInRangeWithSkew(now, now, now, 1); } @Test(expected = IllegalArgumentException.class) public void testInvertedIntervalFailure() { Calendar cal = Calendar.getInstance(); Date now = cal.getTime(); cal.add(Calendar.MINUTE, -5); Date fiveMinutesAgo = cal.getTime(); TimeUtils.checkTimeInRangeWithSkew(now, now, fiveMinutesAgo, 1); } @Test public void testLowerBound() { Calendar cal = Calendar.getInstance(); Date now = cal.getTime(); cal.add(Calendar.MINUTE, 2); Date nowPlus2minute = cal.getTime(); cal.add(Calendar.YEAR, 1); Date inOneYear = cal.getTime(); Assert.assertFalse(TimeUtils.checkTimeInRangeWithSkew(now, nowPlus2minute, inOneYear, 2)); Assert.assertTrue(TimeUtils.checkTimeInRangeWithSkew(now, nowPlus2minute, inOneYear, 3)); } @Test public void testUpperBound() { Calendar cal = Calendar.getInstance(); Date now = cal.getTime(); cal.add(Calendar.YEAR, -1); Date oneYearAgo = cal.getTime(); Assert.assertFalse(TimeUtils.checkTimeInRangeWithSkew(now, oneYearAgo, now, 0)); Assert.assertTrue(TimeUtils.checkTimeInRangeWithSkew(now, oneYearAgo, now, 1)); } } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/TestVOMSESLineParser.java000066400000000000000000000144211477577347300304420ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.net.URISyntaxException; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.request.VOMSServerInfo; import org.italiangrid.voms.request.impl.VOMSESLineParser; import org.junit.Test; public class TestVOMSESLineParser { @Test public void nullLineFailure() throws URISyntaxException { String line = null; try { VOMSESLineParser p = new VOMSESLineParser(); p.parse(line); fail("No error raised."); } catch (VOMSError e) { assertNotNull("Got a null error message", e.getMessage()); assertEquals("Cannot parse a null VOMSES line", e.getMessage()); } } @Test public void emptyLineReturnsNull() throws URISyntaxException { String line = ""; VOMSESLineParser p = new VOMSESLineParser(); VOMSServerInfo i = p.parse(line); assertNull(i); } @Test public void emptyAlias() { String line = "\"\""; try { VOMSESLineParser p = new VOMSESLineParser(); p.parse(line); fail("No error raised."); } catch (VOMSError e) { assertNotNull("Got a null error message", e.getMessage()); assertTrue(e.getMessage().contains("Invalid VOMSES line: empty 'vo alias' field.")); } } @Test public void incompleteAlias() { String line = "\"incomplete-alias"; try { VOMSESLineParser p = new VOMSESLineParser(); p.parse(line); fail("No error raised."); } catch (VOMSError e) { assertNotNull("Got a null error message", e.getMessage()); assertTrue(e.getMessage().contains("Invalid VOMSES line: incomplete 'vo alias' field.")); } } @Test public void incompleteHost() { String line = "\"alias\" \"voms.cnaf.infn.it"; try { VOMSESLineParser p = new VOMSESLineParser(); p.parse(line); fail("No error raised."); } catch (VOMSError e) { assertNotNull("Got a null error message", e.getMessage()); assertTrue(e.getMessage().contains("Invalid VOMSES line: incomplete 'voms host' field.")); } } @Test public void onlyAlias() { String line = "\"ciccio\" "; try { VOMSESLineParser p = new VOMSESLineParser(); p.parse(line); fail("No error raised."); } catch (VOMSError e) { assertNotNull("Got a null error message", e.getMessage()); assertTrue(e.getMessage().contains("Invalid VOMSES line: incomplete information")); } } @Test public void minimumInfoFailure() { String line = "\t\"a\" \"voms.cern.ch\" \t \"15000\" \"DN=Illo\""; try { VOMSESLineParser p = new VOMSESLineParser(); p.parse(line); fail("No error raised."); } catch (VOMSError e) { assertNotNull("Got a null error message", e.getMessage()); assertTrue(e.getMessage().contains("Invalid VOMSES line: incomplete information")); } } @Test public void minimumInfo() { String line = "\t\"a\" \"voms.cern.ch\" \t \"15000\" \"DN=Illo\" \"alice\" "; VOMSESLineParser p = new VOMSESLineParser(); VOMSServerInfo i = p.parse(line); assertEquals("a", i.getAlias()); assertEquals("voms://voms.cern.ch:15000", i.getURL().toString()); assertEquals("alice", i.getVoName()); assertEquals("DN=Illo", i.getVOMSServerDN()); } @Test public void whitespaceHandling() { String line = "\t\"a\" \"voms.cern.ch\" \t \"15000\" \"DN=Illo\" \"alice\" \"24\""; VOMSESLineParser p = new VOMSESLineParser(); VOMSServerInfo i = p.parse(line); assertEquals("a", i.getAlias()); assertEquals("voms://voms.cern.ch:15000", i.getURL().toString()); assertEquals("alice", i.getVoName()); assertEquals("DN=Illo", i.getVOMSServerDN()); } @Test public void tooManyFields() { String line = "\t\"a\" \"voms.cern.ch\" \t \"15000\" \"DN=Illo\" \"alice\" \"24\" \"Too much\""; try { VOMSESLineParser p = new VOMSESLineParser(); p.parse(line); fail("No error raised."); } catch (VOMSError e) { assertNotNull("Got a null error message", e.getMessage()); assertTrue(e.getMessage().contains("Invalid VOMSES line: too many fields!")); } } @Test public void invalidPort() { String line = "\t\"a\" \"voms.cern.ch\" \t \"ciccio\" \"DN=Illo\" \"alice\""; try { VOMSESLineParser p = new VOMSESLineParser(); p.parse(line); fail("No error raised."); } catch (VOMSError e) { assertNotNull("Got a null error message", e.getMessage()); assertTrue(e.getMessage().contains("Invalid VOMSES line: invalid port number.")); } } @Test public void portOutOfRange1() { String line = "\t\"a\" \"voms.cern.ch\" \t \"-1\" \"DN=Illo\" \"alice\""; try { VOMSESLineParser p = new VOMSESLineParser(); p.parse(line); fail("No error raised."); } catch (VOMSError e) { assertNotNull("Got a null error message", e.getMessage()); assertTrue(e.getMessage().contains("Invalid VOMSES line: invalid port number: -1")); } } @Test public void portOutOfRange2() { String line = "\t\"a\" \"voms.cern.ch\" \t \"65536\" \"DN=Illo\" \"alice\""; try { VOMSESLineParser p = new VOMSESLineParser(); p.parse(line); fail("No error raised."); } catch (VOMSError e) { assertNotNull("Got a null error message", e.getMessage()); assertTrue(e.getMessage().contains("Invalid VOMSES line: invalid port number: 65536")); } } @Test public void tooMultiCall() { String line0 = "\"a\" \"voms.cern.ch\" \"15000\" \"DN=Illo\" \"alice\""; String line1 = "\"b\" \"voms.cern.ch\" \"15001\" \"DN=IllY\" \"bolice\""; VOMSESLineParser p = new VOMSESLineParser(); VOMSServerInfo i0 = p.parse(line0); VOMSServerInfo i1 = p.parse(line1); assertEquals("a", i0.getAlias()); assertEquals("voms://voms.cern.ch:15000", i0.getURL().toString()); assertEquals("alice", i0.getVoName()); assertEquals("b", i1.getAlias()); assertEquals("voms://voms.cern.ch:15001", i1.getURL().toString()); assertEquals("bolice", i1.getVoName()); } } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/TestVOMSESLookupStrategy.java000066400000000000000000000014441477577347300313730ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test; import java.io.File; import java.util.Arrays; import java.util.List; import org.junit.Assert; import org.italiangrid.voms.request.VOMSESLookupStrategy; import org.italiangrid.voms.request.impl.BaseVOMSESLookupStrategy; import org.junit.Test; public class TestVOMSESLookupStrategy { @Test public void testLookupVomsesInfo() { VOMSESLookupStrategy strategy = new BaseVOMSESLookupStrategy(Arrays.asList( "src/test/resources/vomses", "/non/existent/path")); List paths = strategy.lookupVomsesInfo(); Assert.assertEquals(1, paths.size()); Assert.assertTrue(paths.contains(new File("src/test/resources/vomses"))); } } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/TestVOMSESParser.java000066400000000000000000000076121477577347300276360ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test; import java.io.File; import java.io.StringReader; import java.net.URI; import java.net.URISyntaxException; import java.util.List; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.request.VOMSESParser; import org.italiangrid.voms.request.VOMSESParserFactory; import org.italiangrid.voms.request.VOMSServerInfo; import org.junit.Assert; import org.junit.Test; public class TestVOMSESParser { @Test public void testNonExistingFileParser() { String nonExistentFile = "/this/file/doesnt/exist"; VOMSESParser parser = VOMSESParserFactory.newVOMSESParser(); try { @SuppressWarnings("unused") List info = parser.parse(new File(nonExistentFile)); } catch (VOMSError e) { Assert.assertEquals("VOMSES file does not exist: " + nonExistentFile, e.getMessage()); return; } Assert.fail("Parsing of non existent VOMSES file succeeded."); } @Test public void testValidStringParsing() throws URISyntaxException { String validVomsesString = "\"alice\" \"lcg-voms.cern.ch\" \"15000\" \"/DC=ch/DC=cern/OU=computers/CN=lcg-voms.cern.ch\" \"alice\" \"24\""; VOMSESParser parser = VOMSESParserFactory.newVOMSESParser(); List info = parser .parse(new StringReader(validVomsesString)); Assert.assertEquals(1, info.size()); VOMSServerInfo aliceInfo = info.get(0); Assert.assertEquals("alice", aliceInfo.getAlias()); Assert.assertEquals("alice", aliceInfo.getVoName()); Assert.assertEquals(new URI("voms://lcg-voms.cern.ch:15000"), aliceInfo.getURL()); Assert.assertEquals("/DC=ch/DC=cern/OU=computers/CN=lcg-voms.cern.ch", aliceInfo.getVOMSServerDN()); } @Test public void testValidFileParsing() throws URISyntaxException { String vomsesFile = "src/test/resources/vomses/eumed"; VOMSESParser parser = VOMSESParserFactory.newVOMSESParser(); List info = parser.parse(new File(vomsesFile)); Assert.assertEquals(2, info.size()); VOMSServerInfo pdVoms = info.get(0); Assert.assertEquals("eumed", pdVoms.getAlias()); Assert.assertEquals("eumed", pdVoms.getVoName()); Assert.assertEquals(new URI("voms://voms-02.pd.infn.it:15016"), pdVoms.getURL()); Assert.assertEquals("/C=IT/O=INFN/OU=Host/L=Padova/CN=voms-02.pd.infn.it", pdVoms.getVOMSServerDN()); VOMSServerInfo cnafVoms = info.get(1); Assert.assertEquals("eumed", cnafVoms.getAlias()); Assert.assertEquals("eumed", cnafVoms.getVoName()); Assert.assertEquals(new URI("voms://voms2.cnaf.infn.it:15016"), cnafVoms.getURL()); Assert.assertEquals("/C=IT/O=INFN/OU=Host/L=CNAF/CN=voms2.cnaf.infn.it", cnafVoms.getVOMSServerDN()); } @Test public void testValidDirectoryParsing() throws URISyntaxException { String vomsesDir = "src/test/resources/vomses"; VOMSESParser parser = VOMSESParserFactory.newVOMSESParser(); List info = parser.parse(new File(vomsesDir)); Assert.assertEquals(5, info.size()); } @Test public void testSingleCharAliasParsing() throws URISyntaxException { String validVomsesString = "\"a\" \"lcg-voms.cern.ch\" \"15000\" \"/DC=ch/DC=cern/OU=computers/CN=lcg-voms.cern.ch\" \"alice\" \"24\""; VOMSESParser parser = VOMSESParserFactory.newVOMSESParser(); List info = parser .parse(new StringReader(validVomsesString)); Assert.assertEquals(1, info.size()); VOMSServerInfo aliceInfo = info.get(0); Assert.assertEquals("a", aliceInfo.getAlias()); Assert.assertEquals("alice", aliceInfo.getVoName()); Assert.assertEquals(new URI("voms://lcg-voms.cern.ch:15000"), aliceInfo.getURL()); Assert.assertEquals("/DC=ch/DC=cern/OU=computers/CN=lcg-voms.cern.ch", aliceInfo.getVOMSServerDN()); } } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/TestVOMSServerInfoStore.java000066400000000000000000000045511477577347300312500ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test; import static org.junit.Assert.assertEquals; import java.util.Arrays; import java.util.Set; import org.italiangrid.voms.request.VOMSESLookupStrategy; import org.italiangrid.voms.request.VOMSServerInfo; import org.italiangrid.voms.request.impl.BaseVOMSESLookupStrategy; import org.italiangrid.voms.request.impl.DefaultVOMSServerInfoStore; import org.junit.Assert; import org.junit.Test; public class TestVOMSServerInfoStore { @Test public void testExistingVOMSESParsingSuccess() { VOMSESLookupStrategy strategy = new BaseVOMSESLookupStrategy( Arrays.asList("src/test/resources/vomses")); DefaultVOMSServerInfoStore store = new DefaultVOMSServerInfoStore.Builder() .lookupStrategy(strategy).build(); assertEquals(3, store.getVOMSServerInfo("atlas").size()); assertEquals(2, store.getVOMSServerInfo("eumed").size()); Assert.assertTrue(store.getVOMSServerInfo("non-existing-vo").isEmpty()); assertEquals(5, store.getVOMSServerInfo().size()); } @Test public void testVOMSESAliasLookup() { VOMSESLookupStrategy strategy = new BaseVOMSESLookupStrategy( Arrays.asList("src/test/resources/vomses-alias")); DefaultVOMSServerInfoStore store = new DefaultVOMSServerInfoStore.Builder() .lookupStrategy(strategy).build(); assertEquals(3, store.getVOMSServerInfo("atlas").size()); assertEquals(2, store.getVOMSServerInfo("eumed").size()); Assert.assertTrue(store.getVOMSServerInfo("non-existing-vo").isEmpty()); Set infos = store.getVOMSServerInfo("my-atlas"); Assert.assertFalse(infos.isEmpty()); Assert.assertEquals(2, infos.size()); } @Test public void testVOMSESSingleCharAliasLookup() { VOMSESLookupStrategy strategy = new BaseVOMSESLookupStrategy( Arrays.asList("src/test/resources/vomses-alias-singlechar")); DefaultVOMSServerInfoStore store = new DefaultVOMSServerInfoStore.Builder() .lookupStrategy(strategy).build(); assertEquals(1, store.getVOMSServerInfo("atlas").size()); Assert.assertTrue(store.getVOMSServerInfo("non-existing-vo").isEmpty()); Set infos = store.getVOMSServerInfo("a"); Assert.assertFalse(infos.isEmpty()); Assert.assertEquals(1, infos.size()); } } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/ac/000077500000000000000000000000001477577347300243175ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/ac/TestACGeneration.java000066400000000000000000000343201477577347300303230ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test.ac; import static org.italiangrid.voms.error.VOMSValidationErrorCode.aaCertNotFound; import static org.italiangrid.voms.error.VOMSValidationErrorCode.canlError; import static org.italiangrid.voms.error.VOMSValidationErrorCode.invalidAcCert; import static org.italiangrid.voms.error.VOMSValidationErrorCode.lscDescriptionDoesntMatchAcCert; import static org.italiangrid.voms.error.VOMSValidationErrorMessage.newErrorMessage; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.SignatureException; import java.security.cert.CRLException; import java.security.cert.CertificateException; import java.security.cert.CertificateParsingException; import java.security.cert.X509CRL; import java.security.cert.X509CRLEntry; import java.security.cert.X509Certificate; import java.security.cert.CertificateFactory; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Set; import java.util.function.Supplier; import org.bouncycastle.asn1.x509.AttributeCertificate; import org.bouncycastle.cert.X509AttributeCertificateHolder; import org.bouncycastle.operator.OperatorCreationException; import org.italiangrid.voms.VOMSAttribute; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.VOMSGenericAttribute; import org.italiangrid.voms.VOMSValidators; import org.italiangrid.voms.ac.VOMSACValidator; import org.italiangrid.voms.ac.VOMSValidationResult; import org.italiangrid.voms.ac.ValidationResultListener; import org.italiangrid.voms.ac.impl.VOMSGenericAttributeImpl; import org.italiangrid.voms.asn1.VOMSACGenerator; import org.italiangrid.voms.asn1.VOMSACUtils; import org.italiangrid.voms.error.VOMSValidationErrorMessage; import org.italiangrid.voms.store.VOMSTrustStore; import org.italiangrid.voms.store.impl.DefaultVOMSTrustStore; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import eu.emi.security.authn.x509.impl.OpensslCertChainValidator; import eu.emi.security.authn.x509.impl.PEMCredential; import eu.emi.security.authn.x509.proxy.ProxyCertificate; import eu.emi.security.authn.x509.proxy.ProxyCertificateOptions; import eu.emi.security.authn.x509.proxy.ProxyGenerator; public class TestACGeneration { static final String keyPassword = "pass"; static final String aaCert = "src/test/resources/certs/test_host_cnaf_infn_it.cert.pem"; static final String aaKey = "src/test/resources/certs/test_host_cnaf_infn_it.key.pem"; static final String aaCert2 = "src/test/resources/certs/wilco_cnaf_infn_it.cert.pem"; static final String aaKey2 = "src/test/resources/certs/wilco_cnaf_infn_it.key.pem"; static final String expiredCert = "src/test/resources/certs/expired.cert.pem"; static final String expiredKey = "src/test/resources/certs/expired.key.pem"; static final String revokedCert = "src/test/resources/certs/revoked.cert.pem"; static final String revokedKey = "src/test/resources/certs/revoked.key.pem"; static final String holderCert = "src/test/resources/certs/test0.cert.pem"; static final String holderKey = "src/test/resources/certs/test0.key.pem"; static final String defaultVO = "test.vo"; static final String defaultHost = "test-host.cnaf.infn.it"; static final int port = 15000; static final String vomsdir = "src/test/resources/vomsdir"; static final String trustAnchorsDir = "src/test/resources/trust-anchors"; static final String testCaCrl = "src/test/resources/trust-anchors/igi_test_ca.crl"; static final List defaultFQANs = Arrays.asList("/test.vo", "/test.vo/G1", "/test.vo/G2"); final List defaultGAs = Arrays.asList( buildGA("test", "value", defaultVO), buildGA("test2", "value", defaultVO)); static PEMCredential aaCredential = null; static PEMCredential aaCredential2 = null; static PEMCredential expiredCredential = null; static PEMCredential revokedCredential = null; static PEMCredential holderCredential = null; static VOMSTrustStore trustStore; static OpensslCertChainValidator certValidator = null; static VOMSValidationErrorMessage expiredCertErrorMessage; static VOMSValidationErrorMessage expiredCertCRLErrorMessage; static VOMSValidationErrorMessage revokedCertErrorMessage; static VOMSACGenerator defaultGenerator; @BeforeClass static public void classTestSetup() throws KeyStoreException, CertificateException, FileNotFoundException, IOException, CRLException { aaCredential = new PEMCredential(new FileInputStream(aaKey), new FileInputStream(aaCert), (char[]) null); aaCredential2 = new PEMCredential(new FileInputStream(aaKey2), new FileInputStream(aaCert2), (char[]) null); expiredCredential = new PEMCredential(new FileInputStream(expiredKey), new FileInputStream(expiredCert), keyPassword.toCharArray()); revokedCredential = new PEMCredential(new FileInputStream(revokedKey), new FileInputStream(revokedCert), keyPassword.toCharArray()); holderCredential = new PEMCredential(new FileInputStream(holderKey), new FileInputStream(holderCert), keyPassword.toCharArray()); trustStore = new DefaultVOMSTrustStore(Arrays.asList(vomsdir)); certValidator = new OpensslCertChainValidator(trustAnchorsDir); final String expirationMessage = String.format( "Certificate has expired on: %s", expiredCredential.getCertificate() .getNotAfter()); expiredCertErrorMessage = newErrorMessage(canlError, expirationMessage); expiredCertCRLErrorMessage = newErrorMessage( canlError, "CRL for an expired certificate was not resolved Cause: No CRLs found for issuer \"cn=Test CA,o=IGI,c=IT\""); final Date revocationDate = ((Supplier) () -> { try (FileInputStream fis = new FileInputStream(testCaCrl)) { CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509CRL crl = (X509CRL) cf.generateCRL(fis); Set revokedCertificates = crl.getRevokedCertificates(); X509CRLEntry entry = revokedCertificates.iterator().next(); return entry.getRevocationDate(); } catch (CertificateException | CRLException | IOException e) { throw new RuntimeException(e.getMessage()); } }).get(); final String revocationMessage = String.format( "Certificate was revoked at: " + "%s, the reason reported is: unspecified", revocationDate); revokedCertErrorMessage = newErrorMessage(canlError, revocationMessage); defaultGenerator = new VOMSACGenerator(aaCredential); } @AfterClass static public void classTestShutdown() { certValidator.dispose(); } private AttributeCertificate createAC(PEMCredential aaCredential, List fqans, List gas, String vo, String host) { VOMSACGenerator gen = new VOMSACGenerator(aaCredential); Calendar cal = Calendar.getInstance(); Date now = cal.getTime(); cal.add(Calendar.HOUR, 12); Date expiration = cal.getTime(); X509AttributeCertificateHolder ac = gen.generateVOMSAttributeCertificate( fqans, gas, null, holderCredential.getCertificate(), BigInteger.ONE, now, expiration, vo, host, port); return ac.toASN1Structure(); } private VOMSGenericAttribute buildGA(String name, String value, String context) { VOMSGenericAttributeImpl ga = new VOMSGenericAttributeImpl(); ga.setName(name); ga.setValue(value); ga.setContext(context); return ga; } @Test public void testGeneratedACParsing() throws KeyStoreException, CertificateException, FileNotFoundException, IOException, OperatorCreationException { AttributeCertificate ac = createAC(aaCredential, defaultFQANs, defaultGAs, defaultVO, defaultHost); VOMSAttribute attrs = VOMSACUtils.deserializeVOMSAttributes(ac); // Check holder assertEquals(holderCredential.getCertificate().getSubjectX500Principal(), attrs.getHolder()); // Check holder serial number assertEquals(holderCredential.getCertificate().getSerialNumber(), attrs.getHolderSerialNumber()); // Check issuer assertEquals(aaCredential.getCertificate().getSubjectX500Principal(), attrs.getIssuer()); // Check policyAuthority assertEquals(defaultVO, attrs.getVO()); assertEquals(defaultHost, attrs.getHost()); assertEquals(port, attrs.getPort()); // Check FQANs ordered equality for (int i = 0; i < defaultFQANs.size(); i++) assertEquals(defaultFQANs.get(i), attrs.getFQANs().get(i)); // Check GAs ordered equality for (int i = 0; i < defaultGAs.size(); i++) assertEquals(defaultGAs.get(i), attrs.getGenericAttributes().get(i)); // Check targets assertTrue(attrs.getTargets().isEmpty()); } @Test public void testACValidation() { ValidationResultChecker c = new ValidationResultChecker(true); VOMSACValidator validator = VOMSValidators.newValidator(trustStore, certValidator, c); AttributeCertificate ac = createAC(aaCredential, defaultFQANs, defaultGAs, defaultVO, defaultHost); List validatedAttrs = validator.validateACs(Arrays .asList(ac)); assertEquals(validatedAttrs.size(), 1); } @Test public void testLSCValidationFailure() { ValidationResultChecker c = new ValidationResultChecker(false, newErrorMessage(lscDescriptionDoesntMatchAcCert), newErrorMessage(aaCertNotFound)); VOMSACValidator validator = VOMSValidators.newValidator(trustStore, certValidator, c); AttributeCertificate ac = createAC(aaCredential2, Arrays.asList("/test.vo.1"), defaultGAs, "test.vo.1", "wilco.cnaf.infn.it"); List validatedAttrs = validator.validateACs(Arrays .asList(ac)); assertEquals(validatedAttrs.size(), 0); } @Test public void testExpiredAACertValidationFailure() throws OperatorCreationException { ValidationResultChecker c = new ValidationResultChecker(false, expiredCertErrorMessage, expiredCertCRLErrorMessage, newErrorMessage(invalidAcCert), newErrorMessage(aaCertNotFound)); VOMSACValidator validator = VOMSValidators.newValidator(trustStore, certValidator, c); AttributeCertificate ac = createAC(expiredCredential, Arrays.asList("/test.vo"), defaultGAs, defaultVO, "test-expired.cnaf.infn.it"); List validatedAttrs = validator.validateACs(Arrays .asList(ac)); assertEquals(validatedAttrs.size(), 0); } @Test public void testRevokedAACertValidationFailure() { ValidationResultChecker c = new ValidationResultChecker(false, revokedCertErrorMessage, newErrorMessage(invalidAcCert), newErrorMessage(aaCertNotFound)); VOMSACValidator validator = VOMSValidators.newValidator(trustStore, certValidator, c); AttributeCertificate ac = createAC(revokedCredential, Arrays.asList("/test.vo"), defaultGAs, defaultVO, "test-revoked.cnaf.infn.it"); List validatedAttrs = validator.validateACs(Arrays .asList(ac)); assertEquals(validatedAttrs.size(), 0); } @Test public void testSuccesfullACExtractionFromProxy() { ValidationResultChecker c = new ValidationResultChecker(true); VOMSACValidator validator = VOMSValidators.newValidator(trustStore, certValidator, c); AttributeCertificate ac = createAC(aaCredential, defaultFQANs, defaultGAs, defaultVO, defaultHost); X509Certificate[] chain; try { chain = createVOMSProxy(holderCredential, new AttributeCertificate[] { ac }); } catch (Exception e) { throw new VOMSError("Error generating VOMS proxy:" + e.getMessage(), e); } List attrs = validator.validate(chain); assertEquals(1, attrs.size()); } private X509Certificate[] createVOMSProxy(PEMCredential holder, AttributeCertificate[] acs) throws InvalidKeyException, CertificateParsingException, SignatureException, NoSuchAlgorithmException, IOException { ProxyCertificateOptions proxyOptions = new ProxyCertificateOptions( holder.getCertificateChain()); proxyOptions.setAttributeCertificates(acs); ProxyCertificate proxy = ProxyGenerator.generate(proxyOptions, holder.getKey()); return proxy.getCertificateChain(); } } class ValidationResultChecker implements ValidationResultListener { final List expectedErrorMessages; boolean expectedValidationResult; public ValidationResultChecker(boolean valid, VOMSValidationErrorMessage... expectedMessages) { expectedValidationResult = valid; expectedErrorMessages = Arrays.asList(expectedMessages); } private String errorMessage(String message, VOMSValidationResult result) { return String.format("%s. VOMSValidationResult: <%s>", message, result); } public void notifyValidationResult(VOMSValidationResult result) { assertEquals( errorMessage("ValidationResult validity check failed.", result), expectedValidationResult, result.isValid()); assertEquals(errorMessage("ValidationResult error message size check " + "failed.", result), expectedErrorMessages.size(), result .getValidationErrors().size()); List errorMessages = new ArrayList( result.getValidationErrors()); for (VOMSValidationErrorMessage expectedMessage : expectedErrorMessages) { String failureMessage = errorMessage(String.format( "<%s> was not found in error messages. Error messages: <%s>", expectedMessage, result.getValidationErrors()), result); assertTrue(failureMessage, result.getValidationErrors().contains(expectedMessage)); } if (errorMessages.size() > 0) { errorMessages.removeAll(expectedErrorMessages); assertTrue(errorMessage("ValidationResult check failed. " + "Got more error messages than expected.", result), errorMessages.isEmpty()); } } }voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/ac/TestACGenerationParams.java000066400000000000000000000075351477577347300314770ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test.ac; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; import static org.italiangrid.voms.request.impl.FakeVOMSACServiceProperties.GAS; import static org.italiangrid.voms.request.impl.FakeVOMSACServiceProperties.NOT_AFTER; import static org.italiangrid.voms.request.impl.FakeVOMSACServiceProperties.NOT_BEFORE; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.time.format.DateTimeParseException; import java.util.Date; import org.italiangrid.voms.request.impl.ACGenerationParams; import org.italiangrid.voms.request.impl.FakeVOMSACServiceProperties; import org.italiangrid.voms.util.TimeUtils; import org.junit.After; import org.junit.Test; public class TestACGenerationParams { public static final String JAN_FIRST_2020_00_00_00_S = "2020-01-01T00:00:00"; public static final String JAN_FIRST_2020_00_00_10_S = "2020-01-01T00:00:10"; public static final Date JAN_FIRST_2020_00_00_00 = Date.from(LocalDateTime.parse(JAN_FIRST_2020_00_00_00_S, TimeUtils.DATE_FORMATTER) .toInstant(ZoneOffset.UTC)); public static final Date JAN_FIRST_2020_00_00_10 = Date.from(LocalDateTime.parse(JAN_FIRST_2020_00_00_10_S, TimeUtils.DATE_FORMATTER) .toInstant(ZoneOffset.UTC)); @After public void after() { // Cleanup system properties for (FakeVOMSACServiceProperties p : FakeVOMSACServiceProperties.values()) { System.getProperties().remove(p.getPropertyName()); } } @Test public void testNoPropertySetsSucceeds() { ACGenerationParams.fromSystemProperties(); } @Test(expected = NullPointerException.class) public void testNotAfterNullDateRaisesNullPointerException() { System.setProperty(NOT_AFTER.getPropertyName(), null); ACGenerationParams.fromSystemProperties(); } @Test(expected = NullPointerException.class) public void testNotBeforeNullDateRaisesNullPointerException() { System.setProperty(NOT_BEFORE.getPropertyName(), null); ACGenerationParams.fromSystemProperties(); } @Test(expected = DateTimeParseException.class) public void testNotAfterDateParsingError() { System.setProperty(NOT_AFTER.getPropertyName(), "ciccio"); ACGenerationParams.fromSystemProperties(); } @Test(expected = DateTimeParseException.class) public void testNotBeforeDateParsingError() { System.setProperty(NOT_BEFORE.getPropertyName(), "ciccio"); ACGenerationParams.fromSystemProperties(); } @Test public void testDateParsing() { System.setProperty(NOT_BEFORE.getPropertyName(), JAN_FIRST_2020_00_00_00_S); System.setProperty(NOT_AFTER.getPropertyName(), JAN_FIRST_2020_00_00_10_S); ACGenerationParams params = ACGenerationParams.fromSystemProperties(); assertThat(params.getNotBefore(), equalTo(JAN_FIRST_2020_00_00_00)); assertThat(params.getNotAfter(), equalTo(JAN_FIRST_2020_00_00_10)); } @Test public void testGaParsing() { System.setProperty(GAS.getPropertyName(), "one = uno, two = due, three = tre"); ACGenerationParams params = ACGenerationParams.fromSystemProperties(); assertThat(params.getGas().size(), equalTo(3)); assertThat(params.getGas().get(0).getName(), equalTo("one")); assertThat(params.getGas().get(0).getValue(), equalTo("uno")); assertThat(params.getGas().get(0).getContext(), equalTo("test")); assertThat(params.getGas().get(1).getName(), equalTo("two")); assertThat(params.getGas().get(1).getValue(), equalTo("due")); assertThat(params.getGas().get(1).getContext(), equalTo("test")); assertThat(params.getGas().get(2).getName(), equalTo("three")); assertThat(params.getGas().get(2).getValue(), equalTo("tre")); assertThat(params.getGas().get(2).getContext(), equalTo("test")); } } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/ac/TestACParser.java000066400000000000000000000044351477577347300274700ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test.ac; import java.io.IOException; import java.security.KeyStoreException; import java.security.cert.CertificateException; import java.util.Collections; import java.util.List; import org.junit.Assert; import org.italiangrid.voms.VOMSAttribute; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.ac.impl.DefaultVOMSACParser; import org.italiangrid.voms.test.utils.Fixture; import org.italiangrid.voms.test.utils.Utils; import org.italiangrid.voms.test.utils.VOMSAA; import org.junit.BeforeClass; import org.junit.Test; import eu.emi.security.authn.x509.impl.PEMCredential; import eu.emi.security.authn.x509.proxy.ProxyCertificate; public class TestACParser implements Fixture { static VOMSAA aa; static PEMCredential holder; @BeforeClass public static void setup() throws KeyStoreException, CertificateException, IOException { aa = Utils.getVOMSAA(); } @Test public void test() throws Exception { PEMCredential holder = Utils.getTestUserCredential(); ProxyCertificate proxy = aa.createVOMSProxy(holder, defaultVOFqans); DefaultVOMSACParser parser = new DefaultVOMSACParser(); List attrs = parser.parse(proxy.getCertificateChain()); Assert.assertFalse(attrs.isEmpty()); Assert.assertEquals(1, attrs.size()); Assert.assertEquals(defaultVOFqans, attrs.get(0).getFQANs()); } @Test(expected = NullPointerException.class) public void testParseNullChainFailure() { DefaultVOMSACParser parser = new DefaultVOMSACParser(); parser.parse(null); } @Test public void testEmptyFqansParsing() throws Exception { PEMCredential holder = Utils.getTestUserCredential(); List fqans = Collections.emptyList(); ProxyCertificate proxy = aa.createVOMSProxy(holder, fqans); DefaultVOMSACParser parser = new DefaultVOMSACParser(); try { parser.parse(proxy.getCertificateChain()); } catch (VOMSError e) { Assert .assertEquals( "Non conformant VOMS Attribute certificate: unsupported attribute values encoding.", e.getMessage()); return; } Assert.fail("No exception raised when parsing invalid VOMS AC!"); } } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/ac/TestACParsingContext.java000066400000000000000000000024201477577347300311740ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test.ac; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import org.bouncycastle.asn1.x509.AttributeCertificate; import org.italiangrid.voms.ac.ACParsingContext; import org.italiangrid.voms.test.utils.Fixture; import org.junit.Test; public class TestACParsingContext implements Fixture { @Test public void testGettersAndSetters() { X509Certificate[] emptyChain = new X509Certificate[5]; ACParsingContext ctxt = new ACParsingContext(null, 0, emptyChain); assertNull(ctxt.getACs()); assertEquals(0, ctxt.getCertChainPostion()); assertArrayEquals(emptyChain, ctxt.getCertChain()); X509Certificate[] nullChain = null; List emptyAttrs = new ArrayList(); ctxt.setACs(emptyAttrs); ctxt.setCertChain(nullChain); ctxt.setCertChainPostion(2); assertNull(ctxt.getCertChain()); assertEquals(emptyAttrs, ctxt.getACs()); assertEquals(2, ctxt.getCertChainPostion()); } } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/ac/TestACSupport.java000066400000000000000000000040071477577347300277030ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test.ac; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.security.KeyStoreException; import java.security.cert.CertificateException; import eu.emi.security.authn.x509.impl.PEMCredential; public class TestACSupport { static final String keyPassword = "pass"; static final String aaCert = "src/test/resources/certs/test_host_cnaf_infn_it.cert.pem"; static final String aaKey = "src/test/resources/certs/test_host_cnaf_infn_it.key.pem"; static final String aaCert2 = "src/test/resources/certs/wilco_cnaf_infn_it.cert.pem"; static final String aaKey2 = "src/test/resources/certs/wilco_cnaf_infn_it.key.pem"; static final String expiredCert = "src/test/resources/certs/expired.cert.pem"; static final String expiredKey = "src/test/resources/certs/expired.key.pem"; static final String revokedCert = "src/test/resources/certs/revoked.cert.pem"; static final String revokedKey = "src/test/resources/certs/revoked.key.pem"; static final String holderCert = "src/test/resources/certs/test0.cert.pem"; static final String holderKey = "src/test/resources/certs/test0.key.pem"; static final String defaultVO = "test.vo"; static final String defaultHost = "test-host.cnaf.infn.it"; static final int port = 15000; static final String vomsdir = "src/test/resources/vomsdir"; static final String trustAnchorsDir = "src/test/resources/trust-anchors"; static PEMCredential aaCredential; static PEMCredential holderCredential; static void initializeCredentials() throws KeyStoreException, CertificateException, FileNotFoundException, IOException { aaCredential = new PEMCredential(new FileInputStream(aaKey), new FileInputStream(aaCert), (char[]) null); holderCredential = new PEMCredential(new FileInputStream(holderKey), new FileInputStream(holderCert), keyPassword.toCharArray()); } } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/ac/TestACValidator.java000066400000000000000000000336301477577347300301600ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test.ac; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import java.security.KeyStoreException; import java.security.cert.CertificateException; import java.util.Arrays; import java.util.Date; import java.util.EnumSet; import java.util.List; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.VOMSValidators; import org.italiangrid.voms.ac.VOMSACValidator; import org.italiangrid.voms.ac.VOMSValidationResult; import org.italiangrid.voms.ac.impl.LocalHostnameResolver; import org.italiangrid.voms.asn1.VOMSACGenerator.ACGenerationProperties; import org.italiangrid.voms.error.VOMSValidationErrorCode; import org.italiangrid.voms.error.VOMSValidationErrorMessage; import org.italiangrid.voms.store.impl.DefaultVOMSTrustStore; import org.italiangrid.voms.test.utils.Fixture; import org.italiangrid.voms.test.utils.Utils; import org.italiangrid.voms.test.utils.VOMSAA; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import eu.emi.security.authn.x509.X509CertChainValidatorExt; import eu.emi.security.authn.x509.impl.PEMCredential; import eu.emi.security.authn.x509.proxy.ProxyCertificate; public class TestACValidator implements Fixture { static PEMCredential holder, holder2; static VOMSACValidator validator; @BeforeClass public static void setup() throws KeyStoreException, CertificateException, IOException { holder = Utils.getTestUserCredential(); holder2 = Utils.getTest1UserCredential(); validator = Utils.getVOMSValidator(); } @Test public void testValidityCheckSuccess() throws Exception { ProxyCertificate proxy = Utils.getVOMSAA().createVOMSProxy(holder, defaultVOFqans); List results = validator.validateWithResult(proxy.getCertificateChain()); assertTrue(results.size() == 1); assertTrue(results.get(0).isValid()); assertEquals(defaultVOFqans, results.get(0).getAttributes().getFQANs()); } @Test public void testTimeValidityFailure() throws Exception { Date start = Utils.getDate(1975, 12, 1); Date end = Utils.getDate(1975, 12, 2); ProxyCertificate proxy = Utils.getVOMSAA() .setAcNotBefore(start) .setAcNotAfter(end) .createVOMSProxy(holder, defaultVOFqans); List results = validator.validateWithResult(proxy.getCertificateChain()); assertTrue(results.size() == 1); VOMSValidationResult result = results.get(0); Assert.assertFalse(result.isValid()); Assert.assertTrue(result.getValidationErrors().size() == 1); VOMSValidationErrorMessage m = result.getValidationErrors().get(0); Assert.assertEquals(VOMSValidationErrorCode.acNotValidAtCurrentTime, m.getErrorCode()); } @Test public void testHolderCheckFailure() throws Exception { ProxyCertificate proxy = Utils.getVOMSAA().createVOMSProxy(holder, holder2, defaultVOFqans, null, null); List results = validator.validateWithResult(proxy.getCertificateChain()); assertTrue(results.size() == 1); VOMSValidationResult result = results.get(0); Assert.assertFalse(result.isValid()); Assert.assertTrue(result.getValidationErrors().size() == 1); VOMSValidationErrorMessage m = result.getValidationErrors().get(0); Assert.assertEquals(VOMSValidationErrorCode.acHolderDoesntMatchCertChain, m.getErrorCode()); } @Test public void testSignatureCheckFailure() throws Exception { ProxyCertificate proxy = Utils.getVOMSAA().createVOMSProxy(holder, defaultVOFqans); VOMSACValidator validator = Utils.getVOMSValidator(vomsdir_fake_aa_cert); List results = validator.validateWithResult(proxy.getCertificateChain()); assertTrue(results.size() == 1); VOMSValidationResult result = results.get(0); Assert.assertFalse(result.isValid()); Assert.assertTrue(result.getValidationErrors().size() == 2); Assert.assertEquals(VOMSValidationErrorCode.lscFileNotFound, result.getValidationErrors().get(0).getErrorCode()); Assert.assertEquals(VOMSValidationErrorCode.other, result.getValidationErrors().get(1).getErrorCode()); Assert.assertEquals( "Validation error: AuthorityKeyIdentifier in the AC does not match AA certificate subject key identifier!", result.getValidationErrors().get(1).getMessage()); } @Test public void testExpiredAACredFailure() throws Exception { ProxyCertificate proxy = Utils.getVOMSAA() .setCredential(Utils.getExpiredCredential()) .createVOMSProxy(holder, defaultVOFqans); X509CertChainValidatorExt certValidator = Utils.getCertificateValidator(); VOMSACValidator validator = VOMSValidators.newValidator( new DefaultVOMSTrustStore(Arrays.asList(vomsdir_expired_aa_cert)), certValidator); List results = validator.validateWithResult(proxy.getCertificateChain()); assertTrue(results.size() == 1); VOMSValidationResult result = results.get(0); Assert.assertFalse(result.isValid()); Assert.assertEquals(4, result.getValidationErrors().size()); Assert.assertEquals(VOMSValidationErrorCode.lscFileNotFound, result.getValidationErrors().get(0).getErrorCode()); // Certificate expired notification from CAnL Assert.assertEquals(VOMSValidationErrorCode.canlError, result.getValidationErrors().get(1).getErrorCode()); // This is probably a bug in CAnL: No valid CRL was found for the CA which // issued the chain. But this happens only when validating the expired cert. Assert.assertEquals(VOMSValidationErrorCode.canlError, result.getValidationErrors().get(2).getErrorCode()); Assert.assertEquals(VOMSValidationErrorCode.invalidAaCert, result.getValidationErrors().get(3).getErrorCode()); } @Test public void testEmptyACCertsExtensionSuccess() throws Exception { VOMSAA aa = Utils.getVOMSAA(); aa.setGenerationProperties(EnumSet.of(ACGenerationProperties.INCLUDE_EMPTY_AC_CERTS_EXTENSION)); ProxyCertificate proxy = aa.createVOMSProxy(holder, defaultVOFqans); List results = validator.validateWithResult(proxy.getCertificateChain()); Assert.assertEquals(1, results.size()); VOMSValidationResult r = results.get(0); Assert.assertTrue(r.isValid()); Assert.assertEquals(1, r.getValidationErrors().size()); Assert.assertEquals(VOMSValidationErrorCode.emptyAcCertsExtension, r.getValidationErrors().get(0).getErrorCode()); } @Test public void testMissingACCertsExtensionFailure() throws Exception { VOMSAA aa = Utils.getVOMSAA(); aa.setGenerationProperties(EnumSet.of(ACGenerationProperties.SKIP_AC_CERTS_EXTENSION)); aa.setVoName("test.vo.2"); aa.setHost("wilco.cnaf.infn.it"); aa.setCredential(Utils.getAACredential2()); VOMSACValidator validator = Utils.getVOMSValidator(); ProxyCertificate proxy = aa.createVOMSProxy(Utils.getTestUserCredential(), Arrays.asList("/test.vo.2")); List results = validator.validateWithResult(proxy.getCertificateChain()); Assert.assertEquals(1, results.size()); VOMSValidationResult r = results.get(0); Assert.assertFalse(r.isValid()); Assert.assertEquals(2, r.getValidationErrors().size()); Assert.assertEquals(VOMSValidationErrorCode.emptyAcCertsExtension, r.getValidationErrors().get(0).getErrorCode()); Assert.assertEquals(VOMSValidationErrorCode.aaCertNotFound, r.getValidationErrors().get(1).getErrorCode()); } @Test public void testInvalidLSCSignatureFailure() throws Exception { VOMSAA aa = Utils.getVOMSAA(); aa.setVoName("test.vo.2"); aa.setHost("wilco.cnaf.infn.it"); aa.setCredential(Utils.getAACredential2()); aa.setGenerationProperties(EnumSet.of(ACGenerationProperties.FAKE_SIGNATURE_BITS)); VOMSACValidator validator = Utils.getVOMSValidator(); ProxyCertificate proxy = aa.createVOMSProxy(Utils.getTestUserCredential(), Arrays.asList("/test.vo.2")); List results = validator.validateWithResult(proxy.getCertificateChain()); Assert.assertEquals(1, results.size()); VOMSValidationResult r = results.get(0); Assert.assertFalse(r.isValid()); Assert.assertEquals(2, r.getValidationErrors().size()); Assert.assertEquals(VOMSValidationErrorCode.acCertFailsSignatureVerification, r.getValidationErrors().get(0).getErrorCode()); Assert.assertEquals(VOMSValidationErrorCode.aaCertNotFound, r.getValidationErrors().get(1).getErrorCode()); } @Test public void testUnknownCriticalExtensionFailure() throws Exception { VOMSAA aa = Utils.getVOMSAA(); aa.setGenerationProperties(EnumSet.of(ACGenerationProperties.INCLUDE_FAKE_CRITICAL_EXTENSION)); VOMSACValidator validator = Utils.getVOMSValidator(); ProxyCertificate proxy = aa.createVOMSProxy(Utils.getTestUserCredential(), Arrays.asList("/test.vo")); List results = validator.validateWithResult(proxy.getCertificateChain()); Assert.assertEquals(1, results.size()); VOMSValidationResult r = results.get(0); Assert.assertFalse(r.isValid()); Assert.assertEquals(1, r.getValidationErrors().size()); Assert.assertEquals(VOMSValidationErrorCode.other, r.getValidationErrors().get(0).getErrorCode()); Assert.assertEquals( "Validation error: unknown critical extension found in VOMS AC: 1.3.6.1.4.1.8005.100.120.82", r.getValidationErrors().get(0).getMessage()); } @Test public void testCriticalAKIDFailure() throws Exception { VOMSAA aa = Utils.getVOMSAA(); aa.setGenerationProperties(EnumSet.of(ACGenerationProperties.INCLUDE_CRITICAL_AKID_EXTENSION)); VOMSACValidator validator = Utils.getVOMSValidator(); ProxyCertificate proxy = aa.createVOMSProxy(Utils.getTestUserCredential(), Arrays.asList("/test.vo")); List results = validator.validateWithResult(proxy.getCertificateChain()); Assert.assertEquals(1, results.size()); VOMSValidationResult r = results.get(0); Assert.assertFalse(r.isValid()); Assert.assertEquals(VOMSValidationErrorCode.other, r.getValidationErrors().get(0).getErrorCode()); Assert.assertEquals("Validation error: AuthorityKeyIdentifier AC extension cannot be critical!", r.getValidationErrors().get(0).getMessage()); } @Test public void testCriticalNoRevAvailFailure() throws Exception { VOMSAA aa = Utils.getVOMSAA(); aa.setGenerationProperties( EnumSet.of(ACGenerationProperties.INCLUDE_CRITICAL_NO_REV_AVAIL_EXTENSION)); VOMSACValidator validator = Utils.getVOMSValidator(); ProxyCertificate proxy = aa.createVOMSProxy(Utils.getTestUserCredential(), Arrays.asList("/test.vo")); List results = validator.validateWithResult(proxy.getCertificateChain()); Assert.assertEquals(1, results.size()); VOMSValidationResult r = results.get(0); Assert.assertFalse(r.isValid()); Assert.assertEquals(VOMSValidationErrorCode.other, r.getValidationErrors().get(0).getErrorCode()); Assert.assertEquals("Validation error: NoRevAvail AC extension cannot be critical!", r.getValidationErrors().get(0).getMessage()); } @Test public void testTargetValidationSuccess() throws Exception { VOMSAA aa = Utils.getVOMSAA(); String localhostName; try { localhostName = InetAddress.getLocalHost().getCanonicalHostName(); } catch (UnknownHostException e) { throw new VOMSError("Error resolving local hostname: " + e.getMessage(), e); } VOMSACValidator validator = Utils.getVOMSValidator(); ProxyCertificate proxy = aa.createVOMSProxy(Utils.getTestUserCredential(), Arrays.asList("/test.vo"), null, Arrays.asList(localhostName)); List results = validator.validateWithResult(proxy.getCertificateChain()); Assert.assertEquals(1, results.size()); VOMSValidationResult r = results.get(0); Assert.assertTrue(r.isValid()); } @Test public void testTargetValidationFailure() throws Exception { VOMSAA aa = Utils.getVOMSAA(); VOMSACValidator validator = Utils.getVOMSValidator(); ProxyCertificate proxy = aa.createVOMSProxy(Utils.getTestUserCredential(), Arrays.asList("/test.vo"), null, Arrays.asList("camaghe.cnaf.infn.it")); List results = validator.validateWithResult(proxy.getCertificateChain()); Assert.assertEquals(1, results.size()); VOMSValidationResult r = results.get(0); Assert.assertFalse(r.isValid()); Assert.assertEquals(1, r.getValidationErrors().size()); Assert.assertEquals(VOMSValidationErrorCode.localhostDoesntMatchAcTarget, r.getValidationErrors().get(0).getErrorCode()); } @Test public void testResolveHostnameException() throws Exception { VOMSAA aa = Utils.getVOMSAA(); VOMSACValidator validator = Utils.getVOMSValidator(new LocalHostnameResolver() { public String resolveLocalHostname() throws UnknownHostException { throw new UnknownHostException("misconfigured machine!"); } }); ProxyCertificate proxy = aa.createVOMSProxy(Utils.getTestUserCredential(), Arrays.asList("/test.vo"), null, Arrays.asList("camaghe.cnaf.infn.it")); List results = validator.validateWithResult(proxy.getCertificateChain()); Assert.assertEquals(1, results.size()); VOMSValidationResult r = results.get(0); Assert.assertFalse(r.isValid()); Assert.assertEquals(1, r.getValidationErrors().size()); Assert.assertEquals(VOMSValidationErrorCode.other, r.getValidationErrors().get(0).getErrorCode()); Assert.assertEquals("Validation error: Error resolving localhost name: misconfigured machine!", r.getValidationErrors().get(0).getMessage()); } } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/ac/TestFakeVOMSACService.java000066400000000000000000000050371477577347300311270ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test.ac; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; import java.io.FileNotFoundException; import java.io.IOException; import java.math.BigInteger; import java.security.KeyStoreException; import java.security.cert.CertificateException; import java.time.LocalDate; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.util.Date; import org.bouncycastle.asn1.x509.AttributeCertificate; import org.italiangrid.voms.VOMSAttribute; import org.italiangrid.voms.asn1.VOMSACUtils; import org.italiangrid.voms.request.VOMSACRequest; import org.italiangrid.voms.request.impl.ACGenerationParams; import org.italiangrid.voms.request.impl.DefaultVOMSACRequest; import org.italiangrid.voms.request.impl.FakeVOMSACService; import org.italiangrid.voms.util.NullListener; import org.junit.BeforeClass; import org.junit.Test; public class TestFakeVOMSACService extends TestACSupport { public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ISO_DATE; public static final Date JAN_FIRST_2010 = Date .from(LocalDate.parse("2010-01-01", DATE_FORMATTER).atStartOfDay().toInstant(ZoneOffset.UTC)); public static final Date JAN_TEN_2010 = Date .from(LocalDate.parse("2010-01-10", DATE_FORMATTER).atStartOfDay().toInstant(ZoneOffset.UTC)); @BeforeClass public static void suiteInit() throws KeyStoreException, CertificateException, FileNotFoundException, IOException { initializeCredentials(); } @Test public void testFakeAcServiceCreation() { ACGenerationParams params = ACGenerationParams.builder() .vo("fake") .fqan("/fake") .notBefore(JAN_FIRST_2010) .notAfter(JAN_TEN_2010) .serialNo(189) .build(); FakeVOMSACService acService = FakeVOMSACService.newInstance(aaCredential, params, NullListener.INSTANCE); VOMSACRequest req = new DefaultVOMSACRequest.Builder("test").build(); AttributeCertificate ac = acService.getVOMSAttributeCertificate(holderCredential, req); VOMSAttribute attrs = VOMSACUtils.deserializeVOMSAttributes(ac); assertThat(attrs.getVO(), equalTo("test")); assertThat(attrs.getNotBefore(), equalTo(JAN_FIRST_2010)); assertThat(attrs.getNotAfter(), equalTo(JAN_TEN_2010)); assertThat(attrs.getPrimaryFQAN(), equalTo("/fake")); assertThat(attrs.getVOMSAC().getSerialNumber(), equalTo(BigInteger.valueOf(189))); } } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/ac/TestGaParser.java000066400000000000000000000033501477577347300275270ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test.ac; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; import static org.italiangrid.voms.util.GaParser.parseGaString; import java.util.List; import org.italiangrid.voms.VOMSGenericAttribute; import org.junit.Test; public class TestGaParser { @Test public void testEmptyString() { List result = parseGaString(""); assertThat(result.isEmpty(), equalTo(true)); } @Test(expected=NullPointerException.class) public void testNullString() { parseGaString(null); } @Test public void testInvalidStrings() { assertThat(parseGaString("dsa").isEmpty(), equalTo(true)); assertThat(parseGaString("=, a == d").isEmpty(), equalTo(true)); } @Test public void testValidStrings() { List gas = parseGaString("ciccio = paglia"); assertThat(gas.size(), equalTo(1)); assertThat(gas.get(0).getName(), equalTo("ciccio")); assertThat(gas.get(0).getValue(), equalTo("paglia")); assertThat(gas.get(0).getContext(), nullValue()); gas =parseGaString(" c= p , pippo =franco,a8_d2=789"); assertThat(gas.size(), equalTo(3)); assertThat(gas.get(0).getName(), equalTo("c")); assertThat(gas.get(0).getValue(), equalTo("p")); assertThat(gas.get(1).getName(), equalTo("pippo")); assertThat(gas.get(1).getValue(), equalTo("franco")); assertThat(gas.get(2).getName(), equalTo("a8_d2")); assertThat(gas.get(2).getValue(), equalTo("789")); } } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/ac/TestNoExtensionValidation.java000066400000000000000000000035001477577347300323040ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test.ac; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.SignatureException; import java.security.cert.CertificateParsingException; import java.util.List; import org.junit.Assert; import org.italiangrid.voms.VOMSAttribute; import org.italiangrid.voms.ac.VOMSACValidator; import org.italiangrid.voms.test.utils.Fixture; import org.italiangrid.voms.test.utils.Utils; import org.junit.After; import org.junit.Before; import org.junit.Test; import eu.emi.security.authn.x509.impl.PEMCredential; import eu.emi.security.authn.x509.proxy.ProxyCertificate; import eu.emi.security.authn.x509.proxy.ProxyCertificateOptions; import eu.emi.security.authn.x509.proxy.ProxyGenerator; import eu.emi.security.authn.x509.proxy.ProxyType; import java.io.IOException; public class TestNoExtensionValidation implements Fixture{ PEMCredential cred; @Before public void setUp() throws Exception { cred = new PEMCredential(holderKey, holderCert, keyPassword.toCharArray()); } @After public void tearDown() throws Exception { cred = null; } @Test public void testNoExtensionValidation() throws InvalidKeyException, CertificateParsingException, SignatureException, NoSuchAlgorithmException, IOException { ProxyCertificateOptions options = new ProxyCertificateOptions(cred.getCertificateChain()); options.setType(ProxyType.LEGACY); ProxyCertificate proxy = ProxyGenerator.generate(options, cred.getKey()); VOMSACValidator validator = Utils.getVOMSValidator(); List attrs = validator.validate(proxy.getCertificateChain()); Assert.assertNotNull(attrs); Assert.assertTrue(attrs.isEmpty()); } } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/ac/TestVOMSValidationResult.java000066400000000000000000000012351477577347300320210ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test.ac; import static org.junit.Assert.*; import org.italiangrid.voms.ac.VOMSValidationResult; import org.junit.Test; public class TestVOMSValidationResult { @Test public void testGettersAndSetters() { VOMSValidationResult r = new VOMSValidationResult(null, false); assertFalse(r.isValid()); assertNull(r.getAttributes()); assertTrue(r.getValidationErrors().isEmpty()); assertEquals( "VOMSValidationResult [valid=false, validationErrors=[], attributes=null]", r.toString()); } } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/cred/000077500000000000000000000000001477577347300246515ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/cred/TestLoadCredential.java000066400000000000000000000063621477577347300312350ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test.cred; import eu.emi.security.authn.x509.helpers.PasswordSupplier; import org.italiangrid.voms.credential.impl.AbstractLoadCredentialsStrategy; import org.italiangrid.voms.credential.impl.DefaultLoadCredentialsStrategy; import org.italiangrid.voms.util.FilePermissionHelper; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import eu.emi.security.authn.x509.X509Credential; import eu.emi.security.authn.x509.impl.X500NameUtils; public class TestLoadCredential { public static final String keyPassword = "pass"; public static final String pemCert = "src/test/resources/certs/test0.cert.pem"; public static final String pemKey = "src/test/resources/certs/test0.key.pem"; public static final String pkcs12Cred = "src/test/resources/certs/test0.p12"; public static final String TEST_CERT_SUBJECT = "CN=test0, O=IGI, C=IT"; public static final String PROXY_TMP_PATH = "/tmp/tempProxy"; public static final String emptyHome = "src/test/resources/homes/empty"; public static final String emptyGlobusHome = "src/test/resources/homes/empty.globus"; public static final String pemCredsHome = "src/test/resources/homes/pem-creds"; public static final String pkcs12CredsHome = "src/test/resources/homes/pkcs12-creds"; @BeforeClass public static void setupFilePermissions() { FilePermissionHelper.setPrivateKeyPermissions(pemCredsHome + "/.globus/userkey.pem"); FilePermissionHelper.setPKCS12Permissions(pkcs12CredsHome + "/.globus/usercred.p12"); } static class TestPasswordFinder implements PasswordSupplier { public char[] getPassword() { return keyPassword.toCharArray(); } } static class NullPasswordSupplier implements PasswordSupplier { public char[] getPassword() { return null; } } @Test public void testNoCredentialsFoundSuccess() { AbstractLoadCredentialsStrategy strategy = new DefaultLoadCredentialsStrategy( emptyHome); X509Credential cred = strategy.loadCredentials(new NullPasswordSupplier()); Assert.assertNull(cred); } @Test public void testNoCredentialsFoundEmptyGlobusSuccess() { AbstractLoadCredentialsStrategy strategy = new DefaultLoadCredentialsStrategy( emptyGlobusHome); X509Credential cred = strategy.loadCredentials(new NullPasswordSupplier()); Assert.assertNull(cred); } @Test public void testPEMCredentialLoadingSuccess() { AbstractLoadCredentialsStrategy strategy = new DefaultLoadCredentialsStrategy( pemCredsHome); X509Credential cred = strategy.loadCredentials(new TestPasswordFinder()); Assert.assertNotNull(cred); Assert.assertTrue(X500NameUtils.equal(cred.getCertificate() .getSubjectX500Principal(), TEST_CERT_SUBJECT)); } @Test public void testPKCS12CredentialLoadingSuccess() { AbstractLoadCredentialsStrategy strategy = new DefaultLoadCredentialsStrategy( pkcs12CredsHome); X509Credential cred = strategy.loadCredentials(new TestPasswordFinder()); Assert.assertNotNull(cred); Assert.assertTrue(X500NameUtils.equal(cred.getCertificate() .getSubjectX500Principal(), TEST_CERT_SUBJECT)); } } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/cred/package-info.java000066400000000000000000000003111477577347300300330ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 /** * */ /** * @author andreaceccanti * */ package org.italiangrid.voms.test.cred;voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/mt/000077500000000000000000000000001477577347300243545ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/mt/TestConcurrentValidation.java000066400000000000000000000174651477577347300322310ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test.mt; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.security.InvalidKeyException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.SignatureException; import java.security.cert.CertificateException; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Random; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import org.junit.Assert; import org.italiangrid.voms.VOMSAttribute; import org.italiangrid.voms.VOMSValidators; import org.italiangrid.voms.ac.VOMSACValidator; import org.italiangrid.voms.store.UpdatingVOMSTrustStore; import org.italiangrid.voms.store.impl.DefaultUpdatingVOMSTrustStore; import org.italiangrid.voms.test.utils.VOMSAA; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import eu.emi.security.authn.x509.NamespaceCheckingMode; import eu.emi.security.authn.x509.X509CertChainValidatorExt; import eu.emi.security.authn.x509.impl.OpensslCertChainValidator; import eu.emi.security.authn.x509.impl.PEMCredential; import eu.emi.security.authn.x509.proxy.ProxyCertificate; public class TestConcurrentValidation { static X509CertChainValidatorExt sharedCertificateValidator; static UpdatingVOMSTrustStore sharedVOMSTrustStore; static final String trustAnchorsDir = "src/test/resources/trust-anchors"; static final long trustAnchorsRefreshInterval = TimeUnit.SECONDS.toMillis(15); static final String vomsTrustStoreDir = "src/test/resources/vomsdir"; static final long trustStoreRefreshInterval = TimeUnit.SECONDS.toMillis(5); static final int numHolderCredentials = 5; static PEMCredential[] holderCerts; static VOMSAA testVO_1, testVO_2; static final String aaCert = "src/test/resources/certs/test_host_cnaf_infn_it.cert.pem"; static final String aaKey = "src/test/resources/certs/test_host_cnaf_infn_it.key.pem"; static final String aaCert2 = "src/test/resources/certs/wilco_cnaf_infn_it.cert.pem"; static final String aaKey2 = "src/test/resources/certs/wilco_cnaf_infn_it.key.pem"; static final long NUM_ITERATIONS = 10; static final int NUM_WORKERS = 10; static final CyclicBarrier barrier = new CyclicBarrier(NUM_WORKERS + 1); static final ExecutorService pool = Executors.newCachedThreadPool(); static final String[][] fqans = { { "/test.vo" }, { "/test.vo.2" } }; static VOMSACValidator sharedValidator; static List testProxies; static final Random r = new Random(); static void loadHolderCredentials() throws KeyStoreException, CertificateException, FileNotFoundException, IOException { holderCerts = new PEMCredential[numHolderCredentials]; for (int i = 0; i < numHolderCredentials; i++) { String baseFileName = String.format("src/test/resources/certs/test%d", i); holderCerts[i] = new PEMCredential(new FileInputStream(baseFileName + ".key.pem"), new FileInputStream(baseFileName + ".cert.pem"), "pass".toCharArray()); } } static void initVOs() throws KeyStoreException, CertificateException, FileNotFoundException, IOException { PEMCredential aaCred1 = new PEMCredential(new FileInputStream(aaKey), new FileInputStream(aaCert), (char[]) null); PEMCredential aaCred2 = new PEMCredential(new FileInputStream(aaKey2), new FileInputStream(aaCert2), (char[]) null); testVO_1 = new VOMSAA(aaCred1, "test.vo", "test-host.cnaf.infn.it", 15000); testVO_2 = new VOMSAA(aaCred2, "test.vo.2", "wilco.cnaf.infn.it", 15001); } static void initVOMSProxies() throws InvalidKeyException, CertificateParsingException, SignatureException, NoSuchAlgorithmException, IOException { testProxies = new ArrayList(); for (int i = 0; i < numHolderCredentials; i++) for (int j = 0; j < 2; j++) { VOMSAA vo = (j == 0 ? testVO_1 : testVO_2); PEMCredential cert = holderCerts[i]; ProxyCertificate proxy = vo.createVOMSProxy(cert, Arrays.asList(fqans[j])); testProxies.add(proxy); } } static X509Certificate[] getRandomProxy() { int randomIndex = r.nextInt(testProxies.size()); return testProxies.get(randomIndex).getCertificateChain(); } @BeforeClass public static void setup() throws KeyStoreException, CertificateException, FileNotFoundException, IOException, InvalidKeyException, SignatureException, NoSuchAlgorithmException { sharedVOMSTrustStore = new DefaultUpdatingVOMSTrustStore( Arrays.asList(vomsTrustStoreDir), trustStoreRefreshInterval); sharedCertificateValidator = new OpensslCertChainValidator(trustAnchorsDir, NamespaceCheckingMode.EUGRIDPMA_AND_GLOBUS, trustAnchorsRefreshInterval); loadHolderCredentials(); initVOs(); initVOMSProxies(); sharedValidator = VOMSValidators.newValidator(sharedVOMSTrustStore, sharedCertificateValidator); System.out.println("Setup done."); } @AfterClass public static void tearDown() { } @Test public void test() throws InterruptedException, BrokenBarrierException { long start = System.currentTimeMillis(); System.out.format("Workers: %d. Iterations: %d\n", NUM_WORKERS, NUM_ITERATIONS); for (int i = 0; i < NUM_WORKERS; i++) pool.execute(new ValidatorWorker()); barrier.await(); barrier.await(); pool.shutdown(); sharedVOMSTrustStore.cancel(); sharedCertificateValidator.dispose(); long duration = System.currentTimeMillis() - start; System.out .format( "Done. Test duration: %d milliseconds. Avg validation duration: %d milliseconds.\n", duration, duration / (NUM_WORKERS * NUM_ITERATIONS)); } class ValidatorWorker implements Runnable { private volatile boolean shutdownRequested = false; private long iterations = 0; public void run() { try { barrier.await(); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (BrokenBarrierException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } while (true) { if (iterations++ > NUM_ITERATIONS) break; if (shutdownRequested) return; VOMSACValidator validator = getValidator(); try { X509Certificate[] chain = getRandomProxy(); List attrs = validator.validate(chain); Assert.assertEquals(1, attrs.size()); } catch (Exception e) { System.err.println(e.getMessage()); } } try { barrier.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (BrokenBarrierException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public synchronized void shutdown() { shutdownRequested = true; } } static X509Certificate[] buildProxy(int credentialIndex, int voIndex) throws InvalidKeyException, CertificateParsingException, SignatureException, NoSuchAlgorithmException, IOException { VOMSAA vo = (voIndex == 0 ? testVO_1 : testVO_2); PEMCredential cert = holderCerts[credentialIndex]; ProxyCertificate proxy = vo.createVOMSProxy(cert, Arrays.asList(fqans[voIndex])); return proxy.getCertificateChain(); } static VOMSACValidator getValidator() { return sharedValidator; } } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/package-info.java000066400000000000000000000003571477577347300271300ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 /** * This package (and inner packages) provides unit tests for the VOMS * Java API. */ package org.italiangrid.voms.test; voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/req/000077500000000000000000000000001477577347300245235ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/req/TestRequests.java000066400000000000000000000144671477577347300300550ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test.req; import java.util.Arrays; import java.util.List; import java.util.Random; import org.bouncycastle.asn1.x509.AttributeCertificate; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.ac.VOMSACValidator; import org.italiangrid.voms.request.VOMSACRequest; import org.italiangrid.voms.request.VOMSACService; import org.italiangrid.voms.request.VOMSProtocol; import org.italiangrid.voms.request.VOMSProtocolError; import org.italiangrid.voms.request.VOMSResponse; import org.italiangrid.voms.request.VOMSServerInfo; import org.italiangrid.voms.request.impl.DefaultVOMSACRequest; import org.italiangrid.voms.test.utils.EchoVOMSProtocol; import org.italiangrid.voms.test.utils.Fixture; import org.italiangrid.voms.test.utils.Utils; import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; import eu.emi.security.authn.x509.X509Credential; import eu.emi.security.authn.x509.impl.PEMCredential; public class TestRequests implements Fixture { @Test public void testEchoRequest() throws Exception { VOMSACService acService = Utils.buildACService(new EchoVOMSProtocol(Utils.getAACredential())); VOMSACRequest req = new DefaultVOMSACRequest.Builder("test.vo").build(); PEMCredential holder = Utils.getTestUserCredential(); AttributeCertificate ac = acService.getVOMSAttributeCertificate(holder, req); VOMSACValidator validator = Utils.getVOMSValidator(); List acs = validator.validateACs(Arrays.asList(ac)); Assert.assertFalse(acs.isEmpty()); } @Test public void testFailureIfVOIsNotKnown() throws Exception { VOMSACService acService = Utils.buildACService(new EchoVOMSProtocol(Utils.getAACredential())); VOMSACRequest req = new DefaultVOMSACRequest.Builder("test.unknown.vo").build(); PEMCredential holder = Utils.getTestUserCredential(); try { acService.getVOMSAttributeCertificate(holder, req); } catch (VOMSError e) { Assert.assertEquals( "VOMS server for VO test.unknown.vo is not known! Check your vomses configuration.", e.getMessage()); return; } Assert.fail("No exceptions raised for unknown VO"); } @Test public void testNullACBytesHandling() throws Exception { VOMSProtocol nullBytesProtocol = new VOMSProtocol() { public VOMSResponse doRequest(VOMSServerInfo endpoint, X509Credential credential, VOMSACRequest request) { VOMSResponse r = Mockito.mock(VOMSResponse.class); return r; } }; VOMSACService acService = Utils.buildACService(nullBytesProtocol); VOMSACRequest req = new DefaultVOMSACRequest.Builder("test.vo").build(); AttributeCertificate ac = acService.getVOMSAttributeCertificate(Utils.getTestUserCredential(), req); Assert.assertNull(ac); } @Test public void testRandomACBytesHandling() throws Exception { VOMSProtocol nullBytesProtocol = new VOMSProtocol() { public VOMSResponse doRequest(VOMSServerInfo endpoint, X509Credential credential, VOMSACRequest request) { Random r = new Random(); byte[] acBytes = new byte[2048]; r.nextBytes(acBytes); VOMSResponse response = Mockito.mock(VOMSResponse.class); Mockito.when(response.getAC()).thenReturn(acBytes); return response; } }; VOMSACService acService = Utils.buildACService(nullBytesProtocol); VOMSACRequest req = new DefaultVOMSACRequest.Builder("test.vo").build(); AttributeCertificate ac = acService.getVOMSAttributeCertificate(Utils.getTestUserCredential(), req); Assert.assertNull(ac); } @Test public void testProtocolFallback() throws Exception { VOMSProtocol exceptionProtocol = Mockito.mock(VOMSProtocol.class); Mockito .when(exceptionProtocol.doRequest(Mockito.any(VOMSServerInfo.class), Mockito.any(X509Credential.class), Mockito.any(VOMSACRequest.class))) .thenReturn(null); VOMSProtocol fallBackProtocol = Mockito.mock(VOMSProtocol.class); VOMSACService acService = Utils.buildACService(exceptionProtocol, fallBackProtocol); VOMSACRequest req = new DefaultVOMSACRequest.Builder("test.vo").build(); AttributeCertificate ac = acService.getVOMSAttributeCertificate(Utils.getTestUserCredential(), req); Mockito.verify(fallBackProtocol, Mockito.atLeastOnce()) .doRequest(Mockito.any(VOMSServerInfo.class), Mockito.any(X509Credential.class), Mockito.any(VOMSACRequest.class)); Assert.assertNull(ac); } @Test public void testProtocolFallbackDisabled() throws Exception { VOMSProtocol exceptionProtocol = Mockito.mock(VOMSProtocol.class); Mockito .when(exceptionProtocol.doRequest(Mockito.any(VOMSServerInfo.class), Mockito.any(X509Credential.class), Mockito.any(VOMSACRequest.class))) .thenReturn(null); VOMSProtocol fallBackProtocol = Mockito.mock(VOMSProtocol.class); VOMSACService acService = Utils.buildACService(exceptionProtocol, fallBackProtocol, false); VOMSACRequest req = new DefaultVOMSACRequest.Builder("test.vo").build(); AttributeCertificate ac = acService.getVOMSAttributeCertificate(Utils.getTestUserCredential(), req); Mockito.verifyNoMoreInteractions(fallBackProtocol); Assert.assertNull(ac); } @Test public void testProtocolFallback2() throws Exception { VOMSProtocol exceptionProtocol = Mockito.mock(VOMSProtocol.class); Mockito .when(exceptionProtocol.doRequest(Mockito.any(VOMSServerInfo.class), Mockito.any(X509Credential.class), Mockito.any(VOMSACRequest.class))) .thenThrow(new VOMSProtocolError("protocol error", null, null, null, null)); VOMSProtocol fallBackProtocol = Mockito.mock(VOMSProtocol.class); VOMSACService acService = Utils.buildACService(exceptionProtocol, fallBackProtocol); VOMSACRequest req = new DefaultVOMSACRequest.Builder("test.vo").build(); AttributeCertificate ac = acService.getVOMSAttributeCertificate(Utils.getTestUserCredential(), req); Mockito.verify(fallBackProtocol, Mockito.atLeastOnce()) .doRequest(Mockito.any(VOMSServerInfo.class), Mockito.any(X509Credential.class), Mockito.any(VOMSACRequest.class)); Assert.assertNull(ac); } } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/utils/000077500000000000000000000000001477577347300250745ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/utils/EchoVOMSProtocol.java000066400000000000000000000035651477577347300310550ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test.utils; import java.io.IOException; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import org.bouncycastle.asn1.x509.AttributeCertificate; import org.italiangrid.voms.VOMSError; import org.italiangrid.voms.request.VOMSACRequest; import org.italiangrid.voms.request.VOMSProtocol; import org.italiangrid.voms.request.VOMSResponse; import org.italiangrid.voms.request.VOMSServerInfo; import org.mockito.Mockito; import eu.emi.security.authn.x509.X509Credential; import eu.emi.security.authn.x509.impl.PEMCredential; public class EchoVOMSProtocol implements VOMSProtocol { PEMCredential aaCredential; public EchoVOMSProtocol(PEMCredential aaCredential) { this.aaCredential = aaCredential; } public VOMSResponse doRequest(VOMSServerInfo endpoint, X509Credential credential, VOMSACRequest request) { VOMSAA aa = new VOMSAA(aaCredential, endpoint.getVoName(), endpoint .getURL().getHost(), endpoint.getURL().getPort()); int lifetimeInSeconds = request.getLifetime(); Calendar cal = Calendar.getInstance(); Date now = cal.getTime(); cal.add(Calendar.SECOND, lifetimeInSeconds); Date endTime = cal.getTime(); List fqans; if (request.getRequestedFQANs().isEmpty()) { fqans = new ArrayList(); fqans.add("/" + request.getVoName()); } else fqans = request.getRequestedFQANs(); AttributeCertificate ac = aa.getAC(credential, fqans, null, request.getTargets(), now, endTime); VOMSResponse r = Mockito.mock(VOMSResponse.class); try { Mockito.when(r.getAC()).thenReturn(ac.getEncoded()); } catch (IOException e) { throw new VOMSError(e.getMessage(), e); } return r; } } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/utils/Fixture.java000066400000000000000000000034301477577347300273650ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test.utils; import java.util.Arrays; import java.util.List; public interface Fixture { static final String keyPassword = "pass"; static final String aaCert = "src/test/resources/certs/test_host_cnaf_infn_it.cert.pem"; static final String aaKey = "src/test/resources/certs/test_host_cnaf_infn_it.key.pem"; static final String aaCert2 = "src/test/resources/certs/wilco_cnaf_infn_it.cert.pem"; static final String aaKey2 = "src/test/resources/certs/wilco_cnaf_infn_it.key.pem"; static final String expiredCert = "src/test/resources/certs/expired.cert.pem"; static final String expiredKey = "src/test/resources/certs/expired.key.pem"; static final String revokedCert = "src/test/resources/certs/revoked.cert.pem"; static final String revokedKey = "src/test/resources/certs/revoked.key.pem"; static final String holderCert = "src/test/resources/certs/test0.cert.pem"; static final String holderKey = "src/test/resources/certs/test0.key.pem"; static final String holderCert2 = "src/test/resources/certs/test1.cert.pem"; static final String holderKey2 = "src/test/resources/certs/test1.key.pem"; static final String vomsdir = "src/test/resources/vomsdir"; static final String vomsdir_fake_aa_cert = "src/test/resources/vomsdir-fake-aa-cert"; static final String vomsdir_expired_aa_cert = "src/test/resources/vomsdir-expired-aa-cert"; static final String trustAnchorsDir = "src/test/resources/trust-anchors"; static final String defaultVO = "test.vo"; static final String defaultVOHost = "test-host.cnaf.infn.it"; static final int defaultVOPort = 15000; static final List defaultVOFqans = Arrays.asList("/test.vo"); } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/utils/LogListener.java000066400000000000000000000031471477577347300301730ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test.utils; import org.italiangrid.voms.request.VOMSACRequest; import org.italiangrid.voms.request.VOMSErrorMessage; import org.italiangrid.voms.request.VOMSRequestListener; import org.italiangrid.voms.request.VOMSServerInfo; import org.italiangrid.voms.request.VOMSWarningMessage; public enum LogListener implements VOMSRequestListener { INSTANCE; public void notifyVOMSRequestStart(VOMSACRequest request, VOMSServerInfo si) { System.out .format("Contacting %s for VO %s.\n", si.getURL(), si.getVoName()); } public void notifyVOMSRequestSuccess(VOMSACRequest request, VOMSServerInfo endpoint) { System.out.format("Request for VO %s succeded.\n", endpoint.getVoName()); } public void notifyVOMSRequestFailure(VOMSACRequest request, VOMSServerInfo endpoint, Throwable error) { System.out.format("Request for VO %s failed: %s.\n", request.getVoName(), error); } public void notifyErrorsInVOMSReponse(VOMSACRequest request, VOMSServerInfo si, VOMSErrorMessage[] errors) { System.out.format("Errors in voms response for VO %s.\n", si.getVoName()); for (VOMSErrorMessage e : errors) System.out.println(e.getMessage()); } public void notifyWarningsInVOMSResponse(VOMSACRequest request, VOMSServerInfo si, VOMSWarningMessage[] warnings) { System.out.format("Warnings in voms response for VO %s.\n", si.getVoName()); for (VOMSWarningMessage m : warnings) System.out.println(m.getMessage()); }; } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/utils/Utils.java000066400000000000000000000127731477577347300270510ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test.utils; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.security.KeyStoreException; import java.security.cert.CertificateException; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.HashSet; import java.util.Set; import org.italiangrid.voms.VOMSValidators; import org.italiangrid.voms.ac.VOMSACValidator; import org.italiangrid.voms.ac.impl.DefaultVOMSValidationStrategy; import org.italiangrid.voms.ac.impl.DefaultVOMSValidator; import org.italiangrid.voms.ac.impl.LocalHostnameResolver; import org.italiangrid.voms.request.VOMSACService; import org.italiangrid.voms.request.VOMSProtocol; import org.italiangrid.voms.request.VOMSServerInfo; import org.italiangrid.voms.request.VOMSServerInfoStore; import org.italiangrid.voms.request.impl.DefaultVOMSACService; import org.italiangrid.voms.request.impl.DefaultVOMSServerInfo; import org.italiangrid.voms.store.VOMSTrustStore; import org.italiangrid.voms.store.impl.DefaultVOMSTrustStore; import org.italiangrid.voms.util.CertificateValidatorBuilder; import org.mockito.Mockito; import eu.emi.security.authn.x509.X509CertChainValidatorExt; import eu.emi.security.authn.x509.impl.PEMCredential; public class Utils implements Fixture { private Utils() { } public static VOMSACService buildACService(VOMSProtocol main, VOMSProtocol fallback, boolean legacyProtocolEnabled) throws Exception { VOMSServerInfoStore store = Mockito.mock(VOMSServerInfoStore.class); Set testVOEndpoints = new HashSet(); testVOEndpoints.add(getTestVOEndpoint()); Mockito.when(store.getVOMSServerInfo("test.vo")) .thenReturn(testVOEndpoints); DefaultVOMSACService acService = new DefaultVOMSACService.Builder( getCertificateValidator()).serverInfoStore(store) .requestListener(LogListener.INSTANCE).httpProtocol(main) .legacyProtocol(fallback) .legacyProtocolEnabled(legacyProtocolEnabled) .build(); return acService; } public static VOMSACService buildACService(VOMSProtocol main, VOMSProtocol fallback) throws Exception { return buildACService(main, fallback, true); } public static VOMSACService buildACService(VOMSProtocol protocol) throws Exception { return buildACService(protocol, null); } public static VOMSServerInfo getTestVOEndpoint() throws URISyntaxException { DefaultVOMSServerInfo si = new DefaultVOMSServerInfo(); si.setAlias("test.vo"); si.setVoName("test.vo"); si.setURL(new URI("http://localhost:15000")); si.setVOMSServerDN("Not checked"); return si; } public static X509CertChainValidatorExt getCertificateValidator() { return new CertificateValidatorBuilder().trustAnchorsDir(trustAnchorsDir) .build(); } public static VOMSACValidator getVOMSValidator(LocalHostnameResolver resolver) { X509CertChainValidatorExt validator = new CertificateValidatorBuilder() .trustAnchorsDir(trustAnchorsDir).build(); VOMSTrustStore ts = new DefaultVOMSTrustStore(Arrays.asList(vomsdir)); return new DefaultVOMSValidator.Builder().validationStrategy( new DefaultVOMSValidationStrategy(ts, validator, resolver)).build(); } public static VOMSACValidator getVOMSValidator() { X509CertChainValidatorExt validator = new CertificateValidatorBuilder() .trustAnchorsDir(trustAnchorsDir).build(); return VOMSValidators.newValidator( new DefaultVOMSTrustStore(Arrays.asList(vomsdir)), validator); } public static VOMSACValidator getVOMSValidator(String vomsDir) { X509CertChainValidatorExt validator = new CertificateValidatorBuilder() .trustAnchorsDir(trustAnchorsDir).build(); return VOMSValidators.newValidator( new DefaultVOMSTrustStore(Arrays.asList(vomsDir)), validator); } public static PEMCredential getAACredential() throws KeyStoreException, CertificateException, IOException { return new PEMCredential(aaKey, aaCert, keyPassword.toCharArray()); } public static PEMCredential getAACredential2() throws KeyStoreException, CertificateException, IOException { return new PEMCredential(aaKey2, aaCert2, keyPassword.toCharArray()); } public static PEMCredential getTestUserCredential() throws KeyStoreException, CertificateException, IOException { return new PEMCredential(holderKey, holderCert, keyPassword.toCharArray()); } public static PEMCredential getTest1UserCredential() throws KeyStoreException, CertificateException, IOException { return new PEMCredential(holderKey2, holderCert2, keyPassword.toCharArray()); } public static PEMCredential getExpiredCredential() throws KeyStoreException, CertificateException, IOException { return new PEMCredential(expiredKey, expiredCert, keyPassword.toCharArray()); } public static VOMSAA getVOMSAA() throws KeyStoreException, CertificateException, IOException { return new VOMSAA(getAACredential(), defaultVO, defaultVOHost, defaultVOPort); } public static Date getDate(int year, int month, int day, int hour, int minute, int second) { Calendar cal = Calendar.getInstance(); cal.set(year, month, day, hour, minute, second); return cal.getTime(); } public static Date getDate(int year, int month, int day) { Calendar cal = Calendar.getInstance(); cal.set(year, month, day); return cal.getTime(); } } voms-api-java-3.3.5/src/test/java/org/italiangrid/voms/test/utils/VOMSAA.java000066400000000000000000000120341477577347300267250ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare // // SPDX-License-Identifier: Apache-2.0 package org.italiangrid.voms.test.utils; import java.io.IOException; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.SignatureException; import java.security.cert.CertificateParsingException; import java.util.Calendar; import java.util.Date; import java.util.EnumSet; import java.util.List; import org.bouncycastle.asn1.x509.AttributeCertificate; import org.bouncycastle.cert.X509AttributeCertificateHolder; import org.italiangrid.voms.VOMSGenericAttribute; import org.italiangrid.voms.asn1.VOMSACGenerator; import org.italiangrid.voms.asn1.VOMSACGenerator.ACGenerationProperties; import eu.emi.security.authn.x509.X509Credential; import eu.emi.security.authn.x509.impl.PEMCredential; import eu.emi.security.authn.x509.proxy.ProxyCertificate; import eu.emi.security.authn.x509.proxy.ProxyCertificateOptions; import eu.emi.security.authn.x509.proxy.ProxyGenerator; public class VOMSAA { X509Credential credential; String voName; String host; int port; Date acNotBefore; Date acNotAfter; EnumSet generationProperties = VOMSACGenerator.defaultGenerationProperties; private volatile long serial = 0L; public VOMSAA(X509Credential cred, String vo, String host, int port) { credential = cred; voName = vo; this.host = host; this.port = port; } private synchronized BigInteger getAndIncrementSerial() { return BigInteger.valueOf(serial++); } public ProxyCertificate createVOMSProxy(PEMCredential holder, List fqans, List gas, List targets) throws InvalidKeyException, CertificateParsingException, SignatureException, NoSuchAlgorithmException, IOException { return createVOMSProxy(holder, holder, fqans, gas, targets); } public ProxyCertificate createVOMSProxy(PEMCredential holder, List fqans) throws InvalidKeyException, CertificateParsingException, SignatureException, NoSuchAlgorithmException, IOException { return createVOMSProxy(holder, holder, fqans, null, null); } public AttributeCertificate getAC(X509Credential holder, List fqans, List attrs, List targets, Date notBefore, Date notAfter) { return getAC(credential, holder, voName, host, port, fqans, attrs, targets, notBefore, notAfter); } public AttributeCertificate getAC(X509Credential aaCredential, X509Credential holder, String voName, String host, int port, List fqans, List attrs, List targets, Date notBefore, Date notAfter) { VOMSACGenerator generator = new VOMSACGenerator(aaCredential); X509AttributeCertificateHolder acHolder = generator .generateVOMSAttributeCertificate(generationProperties, fqans, attrs, targets, holder.getCertificate(), getAndIncrementSerial(), notBefore, notAfter, voName, host, port); return acHolder.toASN1Structure(); } public ProxyCertificate createVOMSProxy(PEMCredential holder, PEMCredential proxyHolder, List fqans, List attrs, List targets) throws InvalidKeyException, CertificateParsingException, SignatureException, NoSuchAlgorithmException, IOException { Calendar cal = Calendar.getInstance(); Date startDate = acNotBefore; Date endDate = acNotAfter; if (startDate == null) startDate = cal.getTime(); if (endDate == null) { cal.add(Calendar.HOUR, 12); endDate = cal.getTime(); } AttributeCertificate ac = getAC(credential, holder, voName, host, port, fqans, attrs, targets, startDate, endDate); return createVOMSProxy(proxyHolder, new AttributeCertificate[] { ac }); } public ProxyCertificate createVOMSProxy(PEMCredential holder, AttributeCertificate[] acs) throws InvalidKeyException, CertificateParsingException, SignatureException, NoSuchAlgorithmException, IOException { ProxyCertificateOptions proxyOptions = new ProxyCertificateOptions( holder.getCertificateChain()); proxyOptions.setAttributeCertificates(acs); ProxyCertificate proxy = ProxyGenerator.generate(proxyOptions, holder.getKey()); return proxy; } public VOMSAA setCredential(PEMCredential credential) { this.credential = credential; return this; } public VOMSAA setVoName(String voName) { this.voName = voName; return this; } public VOMSAA setHost(String host) { this.host = host; return this; } public VOMSAA setPort(int port) { this.port = port; return this; } public VOMSAA setAcNotBefore(Date acNotBefore) { this.acNotBefore = acNotBefore; return this; } public VOMSAA setAcNotAfter(Date acNotAfter) { this.acNotAfter = acNotAfter; return this; } public VOMSAA setGenerationProperties(EnumSet props) { this.generationProperties = props; return this; } } voms-api-java-3.3.5/src/test/resources/000077500000000000000000000000001477577347300200045ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/resources/conf.d/000077500000000000000000000000001477577347300211535ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/resources/conf.d/expired.conf000066400000000000000000000013771477577347300234720ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2024 Istituto Nazionale di Fisica Nucleare # # SPDX-License-Identifier: EUPL-1.2 [ expired ] default_bits = 2048 default_keyfile = ${ENV::CA_NAME}/certs/expired.key.pem distinguished_name = expired_dn prompt = no output_password = pass default_md = sha512 x509_extensions = expired_extensions [ expired_dn ] C = IT O = IGI CN = Expired [ expired_extensions ] basicConstraints = critical,CA:FALSE subjectKeyIdentifier = hash keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment authorityKeyIdentifier = keyid, issuer subjectAltName = email:expired@cnaf.infn.it voms-api-java-3.3.5/src/test/resources/conf.d/igi_test_ca.conf000066400000000000000000000020141477577347300242710ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2024 Istituto Nazionale di Fisica Nucleare # # SPDX-License-Identifier: EUPL-1.2 [ igi_test_ca ] dir = ${ENV::CA_NAME} certs = $dir/certs database = $dir/index.txt serial = $dir/serial certificate = $dir/ca.crt private_key = $dir/private/ca.key default_crl_days = 30 default_md = sha512 [ igi_test_ca_cert ] default_bits = 2048 default_keyfile = ${ENV::CA_NAME}/private/ca.key distinguished_name = ${ENV::CA_NAME}_dn prompt = no encrypt_key = no default_md = sha512 x509_extensions = ${ENV::CA_NAME}_extensions [ igi_test_ca_dn ] C = IT O = IGI CN = Test CA [ igi_test_ca_extensions ] subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer:always basicConstraints = critical, CA:true keyUsage = critical, cRLSign, keyCertSign voms-api-java-3.3.5/src/test/resources/conf.d/revoked.conf000066400000000000000000000013771477577347300234710ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2024 Istituto Nazionale di Fisica Nucleare # # SPDX-License-Identifier: EUPL-1.2 [ revoked ] default_bits = 2048 default_keyfile = ${ENV::CA_NAME}/certs/revoked.key.pem distinguished_name = revoked_dn prompt = no output_password = pass default_md = sha512 x509_extensions = revoked_extensions [ revoked_dn ] C = IT O = IGI CN = Revoked [ revoked_extensions ] basicConstraints = critical,CA:FALSE subjectKeyIdentifier = hash keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment authorityKeyIdentifier = keyid, issuer subjectAltName = email:revoked@cnaf.infn.it voms-api-java-3.3.5/src/test/resources/conf.d/test0.conf000066400000000000000000000013571477577347300230670ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2024 Istituto Nazionale di Fisica Nucleare # # SPDX-License-Identifier: EUPL-1.2 [ test0 ] default_bits = 2048 default_keyfile = ${ENV::CA_NAME}/certs/test0.key.pem distinguished_name = test0_dn prompt = no output_password = pass default_md = sha512 x509_extensions = test0_extensions [ test0_dn ] C = IT O = IGI CN = Test0 [ test0_extensions ] basicConstraints = critical,CA:FALSE subjectKeyIdentifier = hash keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment authorityKeyIdentifier = keyid, issuer subjectAltName = email:test0@cnaf.infn.it voms-api-java-3.3.5/src/test/resources/conf.d/test1.conf000066400000000000000000000013571477577347300230700ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2024 Istituto Nazionale di Fisica Nucleare # # SPDX-License-Identifier: EUPL-1.2 [ test1 ] default_bits = 2048 default_keyfile = ${ENV::CA_NAME}/certs/test1.key.pem distinguished_name = test1_dn prompt = no output_password = pass default_md = sha512 x509_extensions = test1_extensions [ test1_dn ] C = IT O = IGI CN = Test1 [ test1_extensions ] basicConstraints = critical,CA:FALSE subjectKeyIdentifier = hash keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment authorityKeyIdentifier = keyid, issuer subjectAltName = email:test1@cnaf.infn.it voms-api-java-3.3.5/src/test/resources/conf.d/test2.conf000066400000000000000000000013571477577347300230710ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2024 Istituto Nazionale di Fisica Nucleare # # SPDX-License-Identifier: EUPL-1.2 [ test2 ] default_bits = 2048 default_keyfile = ${ENV::CA_NAME}/certs/test2.key.pem distinguished_name = test2_dn prompt = no output_password = pass default_md = sha512 x509_extensions = test2_extensions [ test2_dn ] C = IT O = IGI CN = Test2 [ test2_extensions ] basicConstraints = critical,CA:FALSE subjectKeyIdentifier = hash keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment authorityKeyIdentifier = keyid, issuer subjectAltName = email:test2@cnaf.infn.it voms-api-java-3.3.5/src/test/resources/conf.d/test3.conf000066400000000000000000000013571477577347300230720ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2024 Istituto Nazionale di Fisica Nucleare # # SPDX-License-Identifier: EUPL-1.2 [ test3 ] default_bits = 2048 default_keyfile = ${ENV::CA_NAME}/certs/test3.key.pem distinguished_name = test3_dn prompt = no output_password = pass default_md = sha512 x509_extensions = test3_extensions [ test3_dn ] C = IT O = IGI CN = Test3 [ test3_extensions ] basicConstraints = critical,CA:FALSE subjectKeyIdentifier = hash keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment authorityKeyIdentifier = keyid, issuer subjectAltName = email:test3@cnaf.infn.it voms-api-java-3.3.5/src/test/resources/conf.d/test4.conf000066400000000000000000000013571477577347300230730ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2024 Istituto Nazionale di Fisica Nucleare # # SPDX-License-Identifier: EUPL-1.2 [ test4 ] default_bits = 2048 default_keyfile = ${ENV::CA_NAME}/certs/test4.key.pem distinguished_name = test4_dn prompt = no output_password = pass default_md = sha512 x509_extensions = test4_extensions [ test4_dn ] C = IT O = IGI CN = Test4 [ test4_extensions ] basicConstraints = critical,CA:FALSE subjectKeyIdentifier = hash keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment authorityKeyIdentifier = keyid, issuer subjectAltName = email:test4@cnaf.infn.it voms-api-java-3.3.5/src/test/resources/conf.d/test5.conf000066400000000000000000000013571477577347300230740ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2024 Istituto Nazionale di Fisica Nucleare # # SPDX-License-Identifier: EUPL-1.2 [ test5 ] default_bits = 2048 default_keyfile = ${ENV::CA_NAME}/certs/test5.key.pem distinguished_name = test5_dn prompt = no output_password = pass default_md = sha512 x509_extensions = test5_extensions [ test5_dn ] C = IT O = IGI CN = Test5 [ test5_extensions ] basicConstraints = critical,CA:FALSE subjectKeyIdentifier = hash keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment authorityKeyIdentifier = keyid, issuer subjectAltName = email:test5@cnaf.infn.it voms-api-java-3.3.5/src/test/resources/conf.d/test_host_2_cnaf_infn_it.conf000066400000000000000000000016011477577347300267520ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2024 Istituto Nazionale di Fisica Nucleare # # SPDX-License-Identifier: EUPL-1.2 [ test_host_2_cnaf_infn_it ] default_bits = 2048 default_keyfile = ${ENV::CA_NAME}/certs/test_host_2_cnaf_infn_it.key.pem distinguished_name = test_host_2_cnaf_infn_it_dn prompt = no output_password = pass default_md = sha512 x509_extensions = test_host_2_cnaf_infn_it_extensions [ test_host_2_cnaf_infn_it_dn ] C = IT O = IGI CN = test-host.cnaf.infn.it [ test_host_2_cnaf_infn_it_extensions ] basicConstraints = critical,CA:FALSE subjectKeyIdentifier = hash keyUsage = critical, digitalSignature extendedKeyUsage = serverAuth, clientAuth authorityKeyIdentifier = keyid, issuer subjectAltName = DNS:test-host.cnaf.infn.it voms-api-java-3.3.5/src/test/resources/conf.d/test_host_cnaf_infn_it.conf000066400000000000000000000015631477577347300265400ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2024 Istituto Nazionale di Fisica Nucleare # # SPDX-License-Identifier: EUPL-1.2 [ test_host_cnaf_infn_it ] default_bits = 2048 default_keyfile = ${ENV::CA_NAME}/certs/test_host_cnaf_infn_it.key.pem distinguished_name = test_host_cnaf_infn_it_dn prompt = no encrypt_key = no default_md = sha512 x509_extensions = test_host_cnaf_infn_it_extensions [ test_host_cnaf_infn_it_dn ] C = IT O = IGI CN = test-host.cnaf.infn.it [ test_host_cnaf_infn_it_extensions ] basicConstraints = critical,CA:FALSE subjectKeyIdentifier = hash keyUsage = critical, digitalSignature extendedKeyUsage = serverAuth, clientAuth authorityKeyIdentifier = keyid, issuer subjectAltName = DNS:test-host.cnaf.infn.it voms-api-java-3.3.5/src/test/resources/conf.d/wilco_cnaf_infn_it.conf000066400000000000000000000015231477577347300256350ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2024 Istituto Nazionale di Fisica Nucleare # # SPDX-License-Identifier: EUPL-1.2 [ wilco_cnaf_infn_it ] default_bits = 2048 default_keyfile = ${ENV::CA_NAME}/certs/wilco_cnaf_infn_it.key.pem distinguished_name = wilco_cnaf_infn_it_dn prompt = no encrypt_key = no default_md = sha512 x509_extensions = wilco_cnaf_infn_it_extensions [ wilco_cnaf_infn_it_dn ] C = IT O = IGI CN = wilco.cnaf.infn.it [ wilco_cnaf_infn_it_extensions ] basicConstraints = critical,CA:FALSE subjectKeyIdentifier = hash keyUsage = critical, digitalSignature extendedKeyUsage = serverAuth, clientAuth authorityKeyIdentifier = keyid, issuer subjectAltName = DNS:wilco.cnaf.infn.it voms-api-java-3.3.5/src/test/resources/empty-vomsdir/000077500000000000000000000000001477577347300226235ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/resources/empty-vomsdir/.this-dir-is-empty-on-purpose000066400000000000000000000000001477577347300302070ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/resources/empty-vomses/000077500000000000000000000000001477577347300224545ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/resources/empty-vomses/.this-should-be-ignored000066400000000000000000000000001477577347300267170ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/resources/openssl.conf000066400000000000000000000003121477577347300223320ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2024 Istituto Nazionale di Fisica Nucleare # # SPDX-License-Identifier: EUPL-1.2 config_diagnostics = 1 [ ca ] default_ca = ${ENV::CA_NAME} .include conf.d voms-api-java-3.3.5/src/test/resources/setup.sh000077500000000000000000000054201477577347300215040ustar00rootroot00000000000000#!/bin/bash # SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare # # SPDX-License-Identifier: Apache-2.0 set -e if [ ! -e "openssl.conf" ]; then >&2 echo "The configuration file 'openssl.conf' doesn't exist in this directory" exit 1 fi base_dir=$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd) certs_dir="${base_dir}"/certs ta_dir="${base_dir}"/trust-anchors sha1_ta_dir="${base_dir}"/sha1-trust-anchors md5_ta_dir="${base_dir}"/md5-trust-anchors vomsdir="${base_dir}"/vomsdir rm -rf certs/ trust-anchors/ md5-trust-anchors/ sha1-trust-anchors/ perm-test/ homes/pem-creds/ homes/pkcs12-creds/ # rm -rf "${certs_dir}" mkdir -p "${certs_dir}" # rm -rf "${ta_dir}" mkdir -p "${ta_dir}" # rm -rf "${sha1_ta_dir}" mkdir -p "${sha1_ta_dir}" # rm -rf "${md5_ta_dir}" mkdir -p "${md5_ta_dir}" # rm -rf "${vomsdir}" mkdir -p "${vomsdir}" [ -d "igi_test_ca" ] && remove_ca.sh igi_test_ca export CA_NAME=igi_test_ca make_ca.sh for i in $(seq 0 5); do make_cert.sh test${i} cp igi_test_ca/certs/test${i}.* "${certs_dir}" done mkdir -p homes/pem-creds/.globus cp certs/test0.*.pem homes/pem-creds/.globus ln -sf test0.cert.pem homes/pem-creds/.globus/usercert.pem ln -sf test0.key.pem homes/pem-creds/.globus/userkey.pem mkdir -p homes/pkcs12-creds/.globus cp certs/test0.p12 homes/pkcs12-creds/.globus ln -sf test0.p12 homes/pkcs12-creds/.globus/usercred.p12 mkdir -p perm-test cp certs/test0.* perm-test chmod 664 perm-test/test0.cert.pem chmod 400 perm-test/test0.key.pem chmod 600 perm-test/test0.p12 cp certs/test1.* perm-test chmod 664 perm-test/test1.cert.pem chmod 777 perm-test/test1.key.pem chmod 777 perm-test/test1.p12 cp certs/test2.key.pem perm-test chmod 600 perm-test/test2.key.pem for c in revoked test_host_cnaf_infn_it test_host_2_cnaf_infn_it wilco_cnaf_infn_it; do make_cert.sh ${c} cp igi_test_ca/certs/${c}.* "${certs_dir}" done revoke_cert.sh revoked faketime -f -1y make_cert.sh expired cp igi_test_ca/certs/expired.* "${certs_dir}" make_crl.sh install_ca.sh igi_test_ca "${ta_dir}" ca_subject_sha1=$(openssl x509 -in "${ta_dir}/igi_test_ca.pem" -noout -subject_hash) ca_subject_md5=$(openssl x509 -in "${ta_dir}/igi_test_ca.pem" -noout -subject_hash_old) cp ${ta_dir}/${ca_subject_sha1}.* "${sha1_ta_dir}" cp ${ta_dir}/${ca_subject_md5}.* "${md5_ta_dir}" mkdir -p "${vomsdir}"/test.vo cp ${certs_dir}/test_host_cnaf_infn_it.cert.pem ${vomsdir}/test-host.cnaf.infn.it.pem mkdir -p vomsdir-expired-aa-cert cp ${certs_dir}/expired.cert.pem vomsdir-expired-aa-cert mkdir -p vomsdir-fake-aa-cert cp ${certs_dir}/test_host_2_cnaf_infn_it.cert.pem vomsdir-fake-aa-cert # openssl x509 -in "${certs_dir}"/star_test_example.cert.pem -noout -subject -issuer -nameopt compat \ # | sed -e 's/subject=//' -e 's/issuer=//' > "${vomsdir}"/test.vo/voms.example.lsc voms-api-java-3.3.5/src/test/resources/vomsdir/000077500000000000000000000000001477577347300214675ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/resources/vomsdir/atlas/000077500000000000000000000000001477577347300225735ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/resources/vomsdir/atlas/lcg-voms.cern.ch.lsc000066400000000000000000000001471477577347300263460ustar00rootroot00000000000000/DC=ch/DC=cern/OU=computers/CN=lcg-voms.cern.ch /DC=ch/DC=cern/CN=CERN Trusted Certification Authority voms-api-java-3.3.5/src/test/resources/vomsdir/atlas/vo.racf.bnl.gov.lsc000066400000000000000000000001631477577347300262000ustar00rootroot00000000000000/DC=org/DC=doegrids/OU=Services/CN=vo.racf.bnl.gov /DC=org/DC=DOEGrids/OU=Certificate Authorities/CN=DOEGrids CA 1 voms-api-java-3.3.5/src/test/resources/vomsdir/atlas/voms.cern.ch.lsc000066400000000000000000000001431477577347300255770ustar00rootroot00000000000000/DC=ch/DC=cern/OU=computers/CN=voms.cern.ch /DC=ch/DC=cern/CN=CERN Trusted Certification Authority voms-api-java-3.3.5/src/test/resources/vomsdir/cms/000077500000000000000000000000001477577347300222515ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/resources/vomsdir/cms/lcg-voms.cern.ch.lsc000066400000000000000000000001471477577347300260240ustar00rootroot00000000000000/DC=ch/DC=cern/OU=computers/CN=lcg-voms.cern.ch /DC=ch/DC=cern/CN=CERN Trusted Certification Authority voms-api-java-3.3.5/src/test/resources/vomsdir/cms/voms.cern.ch.lsc000066400000000000000000000001431477577347300252550ustar00rootroot00000000000000/DC=ch/DC=cern/OU=computers/CN=voms.cern.ch /DC=ch/DC=cern/CN=CERN Trusted Certification Authority voms-api-java-3.3.5/src/test/resources/vomsdir/igi.italiangrid.it/000077500000000000000000000000001477577347300251405ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/resources/vomsdir/igi.italiangrid.it/vomsmania.cnaf.infn.it.lsc000066400000000000000000000001161477577347300321050ustar00rootroot00000000000000/C=IT/O=INFN/OU=Host/L=CNAF/CN=vomsmania.cnaf.infn.it /C=IT/O=INFN/CN=INFN CA voms-api-java-3.3.5/src/test/resources/vomsdir/superbvo.org/000077500000000000000000000000001477577347300241225ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/resources/vomsdir/superbvo.org/voms-02.pd.infn.it.lsc000066400000000000000000000001141477577347300277720ustar00rootroot00000000000000/C=IT/O=INFN/OU=Host/L=Padova/CN=voms-02.pd.infn.it /C=IT/O=INFN/CN=INFN CA voms-api-java-3.3.5/src/test/resources/vomsdir/superbvo.org/voms2.cnaf.infn.it.lsc000066400000000000000000000001121477577347300301370ustar00rootroot00000000000000/C=IT/O=INFN/OU=Host/L=CNAF/CN=voms2.cnaf.infn.it /C=IT/O=INFN/CN=INFN CA voms-api-java-3.3.5/src/test/resources/vomsdir/test.vo.1/000077500000000000000000000000001477577347300232305ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/resources/vomsdir/test.vo.1/wilco.cnaf.infn.it.lsc000066400000000000000000000000761477577347300273250ustar00rootroot00000000000000/C=IT/O=IGI/CN=wilco-error.cnaf.infn.it /C=IT/O=IGI/CN=Test CAvoms-api-java-3.3.5/src/test/resources/vomsdir/test.vo.2/000077500000000000000000000000001477577347300232315ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/resources/vomsdir/test.vo.2/wilco.cnaf.infn.it.lsc000066400000000000000000000000701477577347300273200ustar00rootroot00000000000000/C=IT/O=IGI/CN=wilco.cnaf.infn.it /C=IT/O=IGI/CN=Test CAvoms-api-java-3.3.5/src/test/resources/vomsdir/test.vo/000077500000000000000000000000001477577347300230715ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/resources/vomsdir/test.vo/test-expired.cnaf.infn.it.lsc000066400000000000000000000000551477577347300304630ustar00rootroot00000000000000/C=IT/O=IGI/CN=expired /C=IT/O=IGI/CN=Test CAvoms-api-java-3.3.5/src/test/resources/vomsdir/test.vo/test-host.cnaf.infn.it.lsc000066400000000000000000000000741477577347300300010ustar00rootroot00000000000000/C=IT/O=IGI/CN=test-host.cnaf.infn.it /C=IT/O=IGI/CN=Test CAvoms-api-java-3.3.5/src/test/resources/vomsdir/test.vo/test-multichain.cnaf.infn.it.lsc000066400000000000000000000002211477577347300311530ustar00rootroot00000000000000/C=IT/O=IGI/CN=test-host.cnaf.infn.it /C=IT/O=IGI/CN=Test CA ------NEXT CHAIN------ /C=IT/O=IGI/CN=test-host2.cnaf.infn.it /C=IT/O=IGI/CN=Test CAvoms-api-java-3.3.5/src/test/resources/vomsdir/test.vo/test-revoked.cnaf.infn.it.lsc000066400000000000000000000000551477577347300304620ustar00rootroot00000000000000/C=IT/O=IGI/CN=revoked /C=IT/O=IGI/CN=Test CAvoms-api-java-3.3.5/src/test/resources/vomses-alias-singlechar/000077500000000000000000000000001477577347300245245ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/resources/vomses-alias-singlechar/atlas000066400000000000000000000002701477577347300255520ustar00rootroot00000000000000"atlas" "lcg-voms.cern.ch" "15001" "/DC=ch/DC=cern/OU=computers/CN=lcg-voms.cern.ch" "atlas" "24" "a" "voms.cern.ch" "15001" "/DC=ch/DC=cern/OU=computers/CN=voms.cern.ch" "atlas" "24" voms-api-java-3.3.5/src/test/resources/vomses-alias/000077500000000000000000000000001477577347300224075ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/resources/vomses-alias/atlas000066400000000000000000000007431477577347300234420ustar00rootroot00000000000000"atlas" "lcg-voms.cern.ch" "15001" "/DC=ch/DC=cern/OU=computers/CN=lcg-voms.cern.ch" "atlas" "24" "atlas" "voms.cern.ch" "15001" "/DC=ch/DC=cern/OU=computers/CN=voms.cern.ch" "atlas" "24" "atlas" "vo.racf.bnl.gov" "15003" "/DC=org/DC=doegrids/OU=Services/CN=vo.racf.bnl.gov" "atlas" "24" "my-atlas" "voms.cern.ch" "15001" "/DC=ch/DC=cern/OU=computers/CN=voms.cern.ch" "atlas" "24" "my-atlas" "vo.racf.bnl.gov" "15003" "/DC=org/DC=doegrids/OU=Services/CN=vo.racf.bnl.gov" "atlas" "24"voms-api-java-3.3.5/src/test/resources/vomses-alias/eumed000066400000000000000000000003031477577347300234250ustar00rootroot00000000000000"eumed" "voms-02.pd.infn.it" "15016" "/C=IT/O=INFN/OU=Host/L=Padova/CN=voms-02.pd.infn.it" "eumed" "eumed" "voms2.cnaf.infn.it" "15016" "/C=IT/O=INFN/OU=Host/L=CNAF/CN=voms2.cnaf.infn.it" "eumed"voms-api-java-3.3.5/src/test/resources/vomses/000077500000000000000000000000001477577347300213205ustar00rootroot00000000000000voms-api-java-3.3.5/src/test/resources/vomses/atlas000066400000000000000000000004371477577347300223530ustar00rootroot00000000000000"atlas" "lcg-voms.cern.ch" "15001" "/DC=ch/DC=cern/OU=computers/CN=lcg-voms.cern.ch" "atlas" "24" "atlas" "voms.cern.ch" "15001" "/DC=ch/DC=cern/OU=computers/CN=voms.cern.ch" "atlas" "24" "atlas" "vo.racf.bnl.gov" "15003" "/DC=org/DC=doegrids/OU=Services/CN=vo.racf.bnl.gov" "atlas" "24"voms-api-java-3.3.5/src/test/resources/vomses/eumed000066400000000000000000000003031477577347300223360ustar00rootroot00000000000000"eumed" "voms-02.pd.infn.it" "15016" "/C=IT/O=INFN/OU=Host/L=Padova/CN=voms-02.pd.infn.it" "eumed" "eumed" "voms2.cnaf.infn.it" "15016" "/C=IT/O=INFN/OU=Host/L=CNAF/CN=voms2.cnaf.infn.it" "eumed"voms-api-java-3.3.5/voms-api-java.spec000066400000000000000000000040701477577347300175530ustar00rootroot00000000000000# SPDX-FileCopyrightText: 2006 Istituto Nazionale di Fisica Nucleare # # SPDX-License-Identifier: Apache-2.0 # Remember to define the base_version and version_pom macros %{!?base_version: %global base_version 0.0.0} %{!?version_pom: %global version_pom 0.0.0} Name: voms-api-java Version: %{base_version} Release: 1%{?dist} Summary: The Virtual Organisation Membership Service Java APIs Group: System Environment/Libraries License: Apache-2.0 URL: https://github.com/italiangrid/voms-api-java BuildArch: noarch BuildRequires: maven-openjdk17 Provides: voms-api-java3 = %{version} Requires: canl-java >= 2.7 Requires: java-17-openjdk-headless %description The Virtual Organization Membership Service (VOMS) is an attribute authority which serves as central repository for VO user authorization information, providing support for sorting users into group hierarchies, keeping track of their roles and other attributes in order to issue trusted attribute certificates and SAML assertions used in the Grid environment for authorization purposes. This package provides a Java client APIs for VOMS. %package javadoc Summary: Javadoc for the VOMS Java APIs Group: Documentation BuildArch: noarch Requires: %{name} = %{version} %description javadoc Virtual Organization Membership Service (VOMS) Java API Documentation. %prep %build mvn %{?mvn_settings} -U -Dmaven.test.skip=true clean package %install rm -rf %{buildroot} mkdir -p %{buildroot}%{_javadir} mkdir -p %{buildroot}%{_javadocdir}/%{name}-%{version_pom} install -m 644 target/%{name}-%{version_pom}.jar -t %{buildroot}%{_javadir} ln -s %{name}-%{version_pom}.jar %{buildroot}%{_javadir}/%{name}.jar cp -r target/javadoc/* %{buildroot}%{_javadocdir}/%{name}-%{version_pom} ln -s %{name}-%{version_pom} %{buildroot}%{_javadocdir}/%{name} %clean rm -rf %{buildroot} %files %defattr(-,root,root,-) %{_javadir}/%{name}.jar %{_javadir}/%{name}-%{version_pom}.jar %doc AUTHORS LICENSE %files javadoc %defattr(-,root,root,-) %doc %{_javadocdir}/%{name} %doc %{_javadocdir}/%{name}-%{version_pom} %changelog